2014-12-28 16:11:01 +08:00
/*
2017-01-12 05:23:02 +08:00
* Catch v1 .6 .0
* Generated : 2017 - 01 - 11 16 : 38 : 09.405017
2014-12-28 16:11:01 +08: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 .
*
* 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)
*/
# ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
# define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
# define TWOBLUECUBES_CATCH_HPP_INCLUDED
2015-06-20 21:47:26 +08:00
# ifdef __clang__
# pragma clang system_header
# elif defined __GNUC__
# pragma GCC system_header
# endif
2014-12-28 16:11:01 +08:00
// #included from: internal/catch_suppress_warnings.h
# ifdef __clang__
2015-06-20 21:47:26 +08: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"
# pragma clang diagnostic ignored "-Wswitch-enum"
2015-12-20 22:42:01 +08:00
# pragma clang diagnostic ignored "-Wcovered-switch-default"
2015-06-20 21:47:26 +08:00
# endif
2014-12-28 16:11:01 +08:00
# elif defined __GNUC__
2015-06-20 21:47:26 +08:00
# pragma GCC diagnostic ignored "-Wvariadic-macros"
# pragma GCC diagnostic ignored "-Wunused-variable"
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wpadded"
2014-12-28 16:11:01 +08:00
# endif
2015-06-20 21:47:26 +08:00
# if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER)
# define CATCH_IMPL
2014-12-28 16:11:01 +08:00
# endif
2015-06-20 21:47:26 +08:00
# ifdef CATCH_IMPL
2015-02-06 05:45:21 +08:00
# ifndef CLARA_CONFIG_MAIN
# define CLARA_CONFIG_MAIN_NOT_DEFINED
# define CLARA_CONFIG_MAIN
# endif
2014-12-28 16:11:01 +08:00
# endif
// #included from: internal/catch_notimplemented_exception.h
# define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED
// #included from: catch_common.h
# define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED
// #included from: catch_compiler_capabilities.h
# define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED
2015-06-20 21:47:26 +08: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-12-20 22:42:01 +08:00
// CATCH_CONFIG_CPP11_LONG_LONG : is long long supported?
// CATCH_CONFIG_CPP11_OVERRIDE : is override supported?
// CATCH_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr)
2015-06-20 21:47:26 +08:00
// CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported?
// CATCH_CONFIG_VARIADIC_MACROS : are variadic macros supported?
2016-06-20 00:25:43 +08:00
// CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported?
2015-12-20 22:42:01 +08:00
// ****************
// Note to maintainers: if new toggles are added please document them
// in configuration.md, too
// ****************
2015-07-26 16:41:38 +08: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
2014-12-28 16:11:01 +08:00
2016-06-20 00:25:43 +08:00
# ifdef __cplusplus
# if __cplusplus >= 201103L
# define CATCH_CPP11_OR_GREATER
# endif
# if __cplusplus >= 201402L
# define CATCH_CPP14_OR_GREATER
# endif
# endif
2014-12-28 16:11:01 +08:00
# ifdef __clang__
2015-02-06 05:45:21 +08:00
# if __has_feature(cxx_nullptr)
2015-07-26 16:41:38 +08:00
# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
2015-02-06 05:45:21 +08:00
# endif
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
# if __has_feature(cxx_noexcept)
2015-07-26 16:41:38 +08:00
# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
2015-02-06 05:45:21 +08:00
# endif
2014-12-28 16:11:01 +08:00
2016-06-20 00:25:43 +08:00
# if defined(CATCH_CPP11_OR_GREATER)
# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS _Pragma( "clang diagnostic ignored \"-Wparentheses\"" )
# endif
2014-12-28 16:11:01 +08:00
# endif // __clang__
////////////////////////////////////////////////////////////////////////////////
// Borland
# ifdef __BORLANDC__
# endif // __BORLANDC__
////////////////////////////////////////////////////////////////////////////////
// EDG
# ifdef __EDG_VERSION__
# endif // __EDG_VERSION__
////////////////////////////////////////////////////////////////////////////////
// Digital Mars
# ifdef __DMC__
# endif // __DMC__
////////////////////////////////////////////////////////////////////////////////
// GCC
# ifdef __GNUC__
2016-06-20 00:25:43 +08:00
# if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__)
# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
# endif
# if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) && defined(CATCH_CPP11_OR_GREATER)
# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS _Pragma( "GCC diagnostic ignored \"-Wparentheses\"" )
# endif
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
// - otherwise more recent versions define __cplusplus >= 201103L
// and will get picked up below
2014-12-28 16:11:01 +08:00
# endif // __GNUC__
////////////////////////////////////////////////////////////////////////////////
// Visual C++
# ifdef _MSC_VER
2015-06-20 21:47:26 +08:00
# if (_MSC_VER >= 1600)
2015-07-26 16:41:38 +08:00
# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
2015-12-20 22:42:01 +08:00
# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
2015-06-20 21:47:26 +08:00
# endif
# if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015))
2015-07-26 16:41:38 +08:00
# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
# define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
2017-01-12 05:23:02 +08:00
# define CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE
2015-06-20 21:47:26 +08:00
# endif
2014-12-28 16:11:01 +08:00
# endif // _MSC_VER
2015-12-20 22:42:01 +08:00
////////////////////////////////////////////////////////////////////////////////
2014-12-28 16:11:01 +08:00
// 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 )
2015-07-26 16:41:38 +08:00
# define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
2014-12-28 16:11:01 +08:00
# endif
2016-06-20 00:25:43 +08:00
// Use __COUNTER__ if the compiler supports it
# if ( defined _MSC_VER && _MSC_VER >= 1300 ) || \
( defined __GNUC__ & & __GNUC__ > = 4 & & __GNUC_MINOR__ > = 3 ) | | \
( defined __clang__ & & __clang_major__ > = 3 )
# define CATCH_INTERNAL_CONFIG_COUNTER
# endif
2014-12-28 16:11:01 +08:00
////////////////////////////////////////////////////////////////////////////////
// C++ language feature support
2015-06-20 21:47:26 +08:00
// catch all support for C++11
2016-06-20 00:25:43 +08:00
# if defined(CATCH_CPP11_OR_GREATER)
2015-06-20 21:47:26 +08:00
2015-07-26 16:41:38 +08:00
# if !defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR)
# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
2015-06-20 21:47:26 +08:00
# endif
2015-07-26 16:41:38 +08:00
# ifndef CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
2015-06-20 21:47:26 +08:00
# endif
2015-07-26 16:41:38 +08:00
# ifndef CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
# define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
2015-06-20 21:47:26 +08:00
# endif
2015-07-26 16:41:38 +08:00
# ifndef CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM
# define CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM
2015-06-20 21:47:26 +08:00
# endif
2015-07-26 16:41:38 +08:00
# ifndef CATCH_INTERNAL_CONFIG_CPP11_TUPLE
# define CATCH_INTERNAL_CONFIG_CPP11_TUPLE
2015-06-20 21:47:26 +08:00
# endif
2015-07-26 16:41:38 +08:00
# ifndef CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
# define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
2015-06-20 21:47:26 +08:00
# endif
2015-12-20 22:42:01 +08:00
# if !defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG)
# define CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG
# endif
# if !defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE)
# define CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE
# endif
# if !defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR)
# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
# endif
2017-01-12 05:23:02 +08:00
# if !defined(CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE)
# define CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE
# endif
2015-12-20 22:42:01 +08:00
2015-06-20 21:47:26 +08:00
# endif // __cplusplus >= 201103L
2014-12-28 16:11:01 +08:00
2015-07-26 16:41:38 +08: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-12-20 22:42:01 +08:00
# define CATCH_CONFIG_VARIADIC_MACROS
# endif
2017-01-12 05:23:02 +08:00
# if defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_NO_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_CPP11)
2015-12-20 22:42:01 +08:00
# define CATCH_CONFIG_CPP11_LONG_LONG
# endif
2017-01-12 05:23:02 +08:00
# if defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_NO_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_CPP11)
2015-12-20 22:42:01 +08:00
# define CATCH_CONFIG_CPP11_OVERRIDE
# endif
2017-01-12 05:23:02 +08:00
# if defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_NO_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_CPP11)
2015-12-20 22:42:01 +08:00
# define CATCH_CONFIG_CPP11_UNIQUE_PTR
2015-07-26 16:41:38 +08:00
# endif
2016-06-20 00:25:43 +08:00
# if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER)
# define CATCH_CONFIG_COUNTER
# endif
2017-01-12 05:23:02 +08:00
# if defined(CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE) && !defined(CATCH_CONFIG_CPP11_NO_SHUFFLE) && !defined(CATCH_CONFIG_CPP11_SHUFFLE) && !defined(CATCH_CONFIG_NO_CPP11)
# define CATCH_CONFIG_CPP11_SHUFFLE
# endif
2016-06-20 00:25:43 +08:00
# if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS)
# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS
# endif
2015-07-26 16:41:38 +08:00
2014-12-28 16:11:01 +08:00
// noexcept support:
# if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT)
2015-02-06 05:45:21 +08:00
# define CATCH_NOEXCEPT noexcept
# define CATCH_NOEXCEPT_IS(x) noexcept(x)
2014-12-28 16:11:01 +08:00
# else
2015-02-06 05:45:21 +08:00
# define CATCH_NOEXCEPT throw()
# define CATCH_NOEXCEPT_IS(x)
2014-12-28 16:11:01 +08:00
# endif
2015-12-20 22:42:01 +08:00
// nullptr support
# ifdef CATCH_CONFIG_CPP11_NULLPTR
# define CATCH_NULL nullptr
# else
# define CATCH_NULL NULL
# endif
// override support
# ifdef CATCH_CONFIG_CPP11_OVERRIDE
# define CATCH_OVERRIDE override
# else
# define CATCH_OVERRIDE
# endif
// unique_ptr support
# ifdef CATCH_CONFIG_CPP11_UNIQUE_PTR
# define CATCH_AUTO_PTR( T ) std::unique_ptr<T>
# else
# define CATCH_AUTO_PTR( T ) std::auto_ptr<T>
# endif
2017-01-12 05:23:02 +08: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 )
# ifdef CATCH_CONFIG_COUNTER
# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ )
# else
# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
# endif
# define INTERNAL_CATCH_STRINGIFY2( expr ) #expr
# define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr )
# include <sstream>
# include <stdexcept>
# include <algorithm>
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
struct IConfig ;
struct CaseSensitive { enum Choice {
Yes ,
No
} ; } ;
2015-02-06 05:45:21 +08:00
class NonCopyable {
2015-06-20 21:47:26 +08:00
# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
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
2015-02-06 05:45:21 +08:00
protected :
NonCopyable ( ) { }
virtual ~ NonCopyable ( ) ;
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
class SafeBool {
public :
typedef void ( SafeBool : : * type ) ( ) const ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
static type makeSafe ( bool value ) {
return value ? & SafeBool : : trueValue : 0 ;
}
private :
void trueValue ( ) const { }
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
template < typename ContainerT >
inline void deleteAll ( ContainerT & container ) {
typename ContainerT : : const_iterator it = container . begin ( ) ;
typename ContainerT : : const_iterator itEnd = container . end ( ) ;
for ( ; it ! = itEnd ; + + it )
delete * it ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
template < typename AssociativeContainerT >
inline void deleteAllValues ( AssociativeContainerT & container ) {
typename AssociativeContainerT : : const_iterator it = container . begin ( ) ;
typename AssociativeContainerT : : const_iterator itEnd = container . end ( ) ;
for ( ; it ! = itEnd ; + + it )
delete it - > second ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08: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 ) ;
2015-06-20 21:47:26 +08:00
bool replaceInPlace ( std : : string & str , std : : string const & replaceThis , std : : string const & withThis ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
struct pluralise {
pluralise ( std : : size_t count , std : : string const & label ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
friend std : : ostream & operator < < ( std : : ostream & os , pluralise const & pluraliser ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
std : : size_t m_count ;
std : : string m_label ;
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
struct SourceLineInfo {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
SourceLineInfo ( ) ;
SourceLineInfo ( char const * _file , std : : size_t _line ) ;
SourceLineInfo ( SourceLineInfo const & other ) ;
2015-06-20 21:47:26 +08:00
# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
2015-02-06 05:45:21 +08:00
SourceLineInfo ( SourceLineInfo & & ) = default ;
SourceLineInfo & operator = ( SourceLineInfo const & ) = default ;
SourceLineInfo & operator = ( SourceLineInfo & & ) = default ;
2014-12-28 16:11:01 +08:00
# endif
2015-02-06 05:45:21 +08:00
bool empty ( ) const ;
bool operator = = ( SourceLineInfo const & other ) const ;
2015-06-20 21:47:26 +08:00
bool operator < ( SourceLineInfo const & other ) const ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
std : : string file ;
std : : size_t line ;
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
std : : ostream & operator < < ( std : : ostream & os , SourceLineInfo const & info ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
// This is just here to avoid compiler warnings with macro constants and boolean literals
inline bool isTrue ( bool value ) { return value ; }
inline bool alwaysTrue ( ) { return true ; }
inline bool alwaysFalse ( ) { return false ; }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
void throwLogicError ( std : : string const & message , SourceLineInfo const & locationInfo ) ;
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
void seedRng ( IConfig const & config ) ;
unsigned int rngSeed ( ) ;
2015-02-06 05:45:21 +08: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 ;
2014-12-28 16:11:01 +08: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 );
# include <ostream>
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
class NotImplementedException : public std : : exception
{
public :
NotImplementedException ( SourceLineInfo const & lineInfo ) ;
NotImplementedException ( NotImplementedException const & ) { }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
virtual ~ NotImplementedException ( ) CATCH_NOEXCEPT { }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
virtual const char * what ( ) const CATCH_NOEXCEPT ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
private :
std : : string m_what ;
SourceLineInfo m_lineInfo ;
} ;
2014-12-28 16:11:01 +08:00
} // 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
// #included from: catch_interfaces_generators.h
# define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED
# include <string>
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
struct IGeneratorInfo {
virtual ~ IGeneratorInfo ( ) ;
virtual bool moveNext ( ) = 0 ;
virtual std : : size_t getCurrentIndex ( ) const = 0 ;
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
struct IGeneratorsForTest {
virtual ~ IGeneratorsForTest ( ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
virtual IGeneratorInfo & getGeneratorInfo ( std : : string const & fileInfo , std : : size_t size ) = 0 ;
virtual bool moveNext ( ) = 0 ;
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
IGeneratorsForTest * createGeneratorsForTest ( ) ;
2014-12-28 16:11:01 +08:00
} // end namespace Catch
// #included from: catch_ptr.hpp
# define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED
# ifdef __clang__
2015-02-06 05:45:21 +08:00
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wpadded"
2014-12-28 16:11:01 +08:00
# endif
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
// An intrusive reference counting smart pointer.
// T must implement addRef() and release() methods
// typically implementing the IShared interface
template < typename T >
class Ptr {
public :
2015-12-20 22:42:01 +08:00
Ptr ( ) : m_p ( CATCH_NULL ) { }
2015-02-06 05:45:21 +08:00
Ptr ( T * p ) : m_p ( p ) {
if ( m_p )
m_p - > addRef ( ) ;
}
Ptr ( Ptr const & other ) : m_p ( other . m_p ) {
if ( m_p )
m_p - > addRef ( ) ;
}
~ Ptr ( ) {
if ( m_p )
m_p - > release ( ) ;
}
void reset ( ) {
if ( m_p )
m_p - > release ( ) ;
2015-12-20 22:42:01 +08:00
m_p = CATCH_NULL ;
2015-02-06 05:45:21 +08:00
}
Ptr & operator = ( T * p ) {
Ptr temp ( p ) ;
swap ( temp ) ;
return * this ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
Ptr & operator = ( Ptr const & other ) {
Ptr temp ( other ) ;
swap ( temp ) ;
return * this ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
void swap ( Ptr & other ) { std : : swap ( m_p , other . m_p ) ; }
2015-12-20 22:42:01 +08:00
T * get ( ) const { return m_p ; }
2015-02-06 05:45:21 +08:00
T & operator * ( ) const { return * m_p ; }
T * operator - > ( ) const { return m_p ; }
2015-12-20 22:42:01 +08:00
bool operator ! ( ) const { return m_p = = CATCH_NULL ; }
operator SafeBool : : type ( ) const { return SafeBool : : makeSafe ( m_p ! = CATCH_NULL ) ; }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
private :
T * m_p ;
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
struct IShared : NonCopyable {
virtual ~ IShared ( ) ;
virtual void addRef ( ) const = 0 ;
virtual void release ( ) const = 0 ;
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
template < typename T = IShared >
struct SharedImpl : T {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
SharedImpl ( ) : m_rc ( 0 ) { }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
virtual void addRef ( ) const {
+ + m_rc ;
}
virtual void release ( ) const {
if ( - - m_rc = = 0 )
delete this ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
mutable unsigned int m_rc ;
} ;
2014-12-28 16:11:01 +08:00
} // end namespace Catch
# ifdef __clang__
2015-02-06 05:45:21 +08:00
# pragma clang diagnostic pop
2014-12-28 16:11:01 +08:00
# endif
# include <memory>
# include <vector>
# include <stdlib.h>
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
class TestCase ;
class Stream ;
struct IResultCapture ;
struct IRunner ;
struct IGeneratorsForTest ;
struct IConfig ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
struct IContext
{
virtual ~ IContext ( ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
virtual IResultCapture * getResultCapture ( ) = 0 ;
virtual IRunner * getRunner ( ) = 0 ;
virtual size_t getGeneratorIndex ( std : : string const & fileInfo , size_t totalSize ) = 0 ;
virtual bool advanceGeneratorsForCurrentTest ( ) = 0 ;
virtual Ptr < IConfig const > getConfig ( ) const = 0 ;
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
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 ;
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
IContext & getCurrentContext ( ) ;
IMutableContext & getCurrentMutableContext ( ) ;
void cleanUpContext ( ) ;
Stream createStream ( std : : string const & streamName ) ;
2014-12-28 16:11:01 +08:00
}
// #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
# include <vector>
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
class TestSpec ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
struct ITestCase : IShared {
virtual void invoke ( ) const = 0 ;
protected :
virtual ~ ITestCase ( ) ;
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
class TestCase ;
struct IConfig ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
struct ITestCaseRegistry {
virtual ~ ITestCaseRegistry ( ) ;
virtual std : : vector < TestCase > const & getAllTests ( ) const = 0 ;
2015-12-20 22:42:01 +08:00
virtual std : : vector < TestCase > const & getAllTestsSorted ( IConfig const & config ) const = 0 ;
2015-02-06 05:45:21 +08:00
} ;
2015-12-20 22:42:01 +08: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 ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
template < typename C >
2015-02-06 05:45:21 +08:00
class MethodTestCase : public SharedImpl < ITestCase > {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
public :
2014-12-28 16:11:01 +08:00
MethodTestCase ( void ( C : : * method ) ( ) ) : m_method ( method ) { }
2015-02-06 05:45:21 +08:00
virtual void invoke ( ) const {
2014-12-28 16:11:01 +08:00
C obj ;
( obj . * m_method ) ( ) ;
}
2015-02-06 05:45:21 +08:00
private :
2014-12-28 16:11:01 +08:00
virtual ~ MethodTestCase ( ) { }
void ( C : : * m_method ) ( ) ;
} ;
typedef void ( * TestFunction ) ( ) ;
2015-02-06 05:45:21 +08:00
struct NameAndDesc {
NameAndDesc ( const char * _name = " " , const char * _description = " " )
: name ( _name ) , description ( _description )
2014-12-28 16:11:01 +08:00
{ }
const char * name ;
const char * description ;
} ;
2015-12-20 22:42:01 +08:00
void registerTestCase
( ITestCase * testCase ,
char const * className ,
NameAndDesc const & nameAndDesc ,
SourceLineInfo const & lineInfo ) ;
2015-02-06 05:45:21 +08:00
struct AutoReg {
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
AutoReg
( TestFunction function ,
SourceLineInfo const & lineInfo ,
NameAndDesc const & nameAndDesc ) ;
2014-12-28 16:11:01 +08:00
template < typename C >
2015-12-20 22:42:01 +08:00
AutoReg
( void ( C : : * method ) ( ) ,
char const * className ,
NameAndDesc const & nameAndDesc ,
SourceLineInfo const & lineInfo ) {
registerTestCase
( new MethodTestCase < C > ( method ) ,
className ,
nameAndDesc ,
lineInfo ) ;
}
2014-12-28 16:11:01 +08:00
~ AutoReg ( ) ;
2015-02-06 05:45:21 +08:00
private :
AutoReg ( AutoReg const & ) ;
void operator = ( AutoReg const & ) ;
2014-12-28 16:11:01 +08:00
} ;
2015-12-20 22:42:01 +08:00
void registerTestCaseFunction
( TestFunction function ,
SourceLineInfo const & lineInfo ,
NameAndDesc const & nameAndDesc ) ;
2014-12-28 16:11:01 +08:00
} // end namespace Catch
# ifdef CATCH_CONFIG_VARIADIC_MACROS
2015-02-06 05:45:21 +08:00
///////////////////////////////////////////////////////////////////////////////
2016-06-20 00:25:43 +08:00
# define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \
static void TestName ( ) ; \
namespace { Catch : : AutoReg INTERNAL_CATCH_UNIQUE_NAME ( autoRegistrar ) ( & TestName , CATCH_INTERNAL_LINEINFO , Catch : : NameAndDesc ( __VA_ARGS__ ) ) ; } \
static void TestName ( )
2015-02-06 05:45:21 +08:00
# define INTERNAL_CATCH_TESTCASE( ... ) \
2016-06-20 00:25:43 +08:00
INTERNAL_CATCH_TESTCASE2 ( INTERNAL_CATCH_UNIQUE_NAME ( ____C_A_T_C_H____T_E_S_T____ ) , __VA_ARGS__ )
2015-02-06 05:45:21 +08: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 ) ; }
///////////////////////////////////////////////////////////////////////////////
2016-06-20 00:25:43 +08:00
# define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\
2015-02-06 05:45:21 +08:00
namespace { \
2016-06-20 00:25:43 +08:00
struct TestName : ClassName { \
2015-02-06 05:45:21 +08:00
void test ( ) ; \
} ; \
2016-06-20 00:25:43 +08:00
Catch : : AutoReg INTERNAL_CATCH_UNIQUE_NAME ( autoRegistrar ) ( & TestName : : test , # ClassName , Catch : : NameAndDesc ( __VA_ARGS__ ) , CATCH_INTERNAL_LINEINFO ) ; \
2015-02-06 05:45:21 +08:00
} \
2016-06-20 00:25:43 +08:00
void TestName : : test ( )
# define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \
INTERNAL_CATCH_TEST_CASE_METHOD2 ( INTERNAL_CATCH_UNIQUE_NAME ( ____C_A_T_C_H____T_E_S_T____ ) , ClassName , __VA_ARGS__ )
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
///////////////////////////////////////////////////////////////////////////////
# define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \
Catch : : AutoReg ( Function , CATCH_INTERNAL_LINEINFO , Catch : : NameAndDesc ( __VA_ARGS__ ) ) ;
2014-12-28 16:11:01 +08:00
# else
2015-02-06 05:45:21 +08:00
///////////////////////////////////////////////////////////////////////////////
2016-06-20 00:25:43 +08:00
# define INTERNAL_CATCH_TESTCASE2( TestName, Name, Desc ) \
static void TestName ( ) ; \
namespace { Catch : : AutoReg INTERNAL_CATCH_UNIQUE_NAME ( autoRegistrar ) ( & TestName , CATCH_INTERNAL_LINEINFO , Catch : : NameAndDesc ( Name , Desc ) ) ; } \
static void TestName ( )
2015-02-06 05:45:21 +08:00
# define INTERNAL_CATCH_TESTCASE( Name, Desc ) \
2016-06-20 00:25:43 +08:00
INTERNAL_CATCH_TESTCASE2 ( INTERNAL_CATCH_UNIQUE_NAME ( ____C_A_T_C_H____T_E_S_T____ ) , Name , Desc )
2015-02-06 05:45:21 +08: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 ) ; }
///////////////////////////////////////////////////////////////////////////////
2016-06-20 00:25:43 +08:00
# define INTERNAL_CATCH_TEST_CASE_METHOD2( TestCaseName, ClassName, TestName, Desc )\
2015-02-06 05:45:21 +08:00
namespace { \
2016-06-20 00:25:43 +08:00
struct TestCaseName : ClassName { \
2015-02-06 05:45:21 +08:00
void test ( ) ; \
} ; \
2016-06-20 00:25:43 +08:00
Catch : : AutoReg INTERNAL_CATCH_UNIQUE_NAME ( autoRegistrar ) ( & TestCaseName : : test , # ClassName , Catch : : NameAndDesc ( TestName , Desc ) , CATCH_INTERNAL_LINEINFO ) ; \
2015-02-06 05:45:21 +08:00
} \
2016-06-20 00:25:43 +08:00
void TestCaseName : : test ( )
# define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\
INTERNAL_CATCH_TEST_CASE_METHOD2 ( INTERNAL_CATCH_UNIQUE_NAME ( ____C_A_T_C_H____T_E_S_T____ ) , ClassName , TestName , Desc )
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
///////////////////////////////////////////////////////////////////////////////
# define INTERNAL_CATCH_REGISTER_TESTCASE( Function, Name, Desc ) \
Catch : : AutoReg ( Function , CATCH_INTERNAL_LINEINFO , Catch : : NameAndDesc ( Name , Desc ) ) ;
2014-12-28 16:11:01 +08:00
# endif
// #included from: internal/catch_capture.hpp
# define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
// #included from: catch_result_builder.h
# define TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED
// #included from: catch_result_type.h
# define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
// ResultWas::OfType enum
struct ResultWas { enum OfType {
2014-12-28 16:11:01 +08:00
Unknown = - 1 ,
Ok = 0 ,
Info = 1 ,
Warning = 2 ,
FailureBit = 0x10 ,
ExpressionFailed = FailureBit | 1 ,
ExplicitFailure = FailureBit | 2 ,
Exception = 0x100 | FailureBit ,
ThrewException = Exception | 1 ,
2015-06-20 21:47:26 +08:00
DidntThrowException = Exception | 2 ,
FatalErrorCondition = 0x200 | FailureBit
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
} ; } ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
inline bool isOk ( ResultWas : : OfType resultType ) {
return ( resultType & ResultWas : : FailureBit ) = = 0 ;
}
inline bool isJustInfo ( int flags ) {
return flags = = ResultWas : : Info ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
// ResultDisposition::Flags enum
struct ResultDisposition { enum Flags {
2015-06-20 21:47:26 +08:00
Normal = 0x01 ,
2014-12-28 16:11:01 +08:00
2015-06-20 21:47:26 +08: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
2015-02-06 05:45:21 +08:00
} ; } ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
inline ResultDisposition : : Flags operator | ( ResultDisposition : : Flags lhs , ResultDisposition : : Flags rhs ) {
return static_cast < ResultDisposition : : Flags > ( static_cast < int > ( lhs ) | static_cast < int > ( rhs ) ) ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
inline bool shouldContinueOnFailure ( int flags ) { return ( flags & ResultDisposition : : ContinueOnFailure ) ! = 0 ; }
inline bool isFalseTest ( int flags ) { return ( flags & ResultDisposition : : FalseTest ) ! = 0 ; }
inline bool shouldSuppressFailure ( int flags ) { return ( flags & ResultDisposition : : SuppressFail ) ! = 0 ; }
2014-12-28 16:11:01 +08:00
} // end namespace Catch
// #included from: catch_assertionresult.h
# define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED
# include <string>
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
struct AssertionInfo
{
AssertionInfo ( ) { }
AssertionInfo ( std : : string const & _macroName ,
SourceLineInfo const & _lineInfo ,
std : : string const & _capturedExpression ,
ResultDisposition : : Flags _resultDisposition ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
std : : string macroName ;
SourceLineInfo lineInfo ;
std : : string capturedExpression ;
ResultDisposition : : Flags resultDisposition ;
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
struct AssertionResultData
{
AssertionResultData ( ) : resultType ( ResultWas : : Unknown ) { }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
std : : string reconstructedExpression ;
std : : string message ;
ResultWas : : OfType resultType ;
} ;
class AssertionResult {
public :
AssertionResult ( ) ;
AssertionResult ( AssertionInfo const & info , AssertionResultData const & data ) ;
~ AssertionResult ( ) ;
2015-06-20 21:47:26 +08:00
# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
2015-02-06 05:45:21 +08:00
AssertionResult ( AssertionResult const & ) = default ;
AssertionResult ( AssertionResult & & ) = default ;
AssertionResult & operator = ( AssertionResult const & ) = default ;
AssertionResult & operator = ( AssertionResult & & ) = default ;
2014-12-28 16:11:01 +08:00
# endif
2015-02-06 05:45:21 +08:00
bool isOk ( ) const ;
bool succeeded ( ) const ;
ResultWas : : OfType getResultType ( ) const ;
bool hasExpression ( ) const ;
bool hasMessage ( ) const ;
std : : string getExpression ( ) const ;
std : : string getExpressionInMacro ( ) const ;
bool hasExpandedExpression ( ) const ;
std : : string getExpandedExpression ( ) const ;
std : : string getMessage ( ) const ;
SourceLineInfo getSourceInfo ( ) const ;
std : : string getTestMacroName ( ) const ;
protected :
AssertionInfo m_info ;
AssertionResultData m_resultData ;
} ;
2014-12-28 16:11:01 +08:00
} // end namespace Catch
2015-12-20 22:42:01 +08:00
// #included from: catch_matchers.hpp
# define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED
2015-02-06 05:45:21 +08:00
namespace Catch {
2015-12-20 22:42:01 +08:00
namespace Matchers {
namespace Impl {
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
namespace Generic {
template < typename ExpressionT > class AllOf ;
template < typename ExpressionT > class AnyOf ;
template < typename ExpressionT > class Not ;
}
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
template < typename ExpressionT >
struct Matcher : SharedImpl < IShared >
{
typedef ExpressionT ExpressionType ;
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
virtual ~ Matcher ( ) { }
virtual Ptr < Matcher > clone ( ) const = 0 ;
virtual bool match ( ExpressionT const & expr ) const = 0 ;
virtual std : : string toString ( ) const = 0 ;
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
Generic : : AllOf < ExpressionT > operator & & ( Matcher < ExpressionT > const & other ) const ;
Generic : : AnyOf < ExpressionT > operator | | ( Matcher < ExpressionT > const & other ) const ;
Generic : : Not < ExpressionT > operator ! ( ) const ;
} ;
template < typename DerivedT , typename ExpressionT >
struct MatcherImpl : Matcher < ExpressionT > {
virtual Ptr < Matcher < ExpressionT > > clone ( ) const {
return Ptr < Matcher < ExpressionT > > ( new DerivedT ( static_cast < DerivedT const & > ( * this ) ) ) ;
2015-02-06 05:45:21 +08:00
}
} ;
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
namespace Generic {
template < typename ExpressionT >
class Not : public MatcherImpl < Not < ExpressionT > , ExpressionT > {
public :
explicit Not ( Matcher < ExpressionT > const & matcher ) : m_matcher ( matcher . clone ( ) ) { }
Not ( Not const & other ) : m_matcher ( other . m_matcher ) { }
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
virtual bool match ( ExpressionT const & expr ) const CATCH_OVERRIDE {
return ! m_matcher - > match ( expr ) ;
}
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
virtual std : : string toString ( ) const CATCH_OVERRIDE {
return " not " + m_matcher - > toString ( ) ;
}
private :
Ptr < Matcher < ExpressionT > > m_matcher ;
} ;
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
template < typename ExpressionT >
class AllOf : public MatcherImpl < AllOf < ExpressionT > , ExpressionT > {
public :
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
AllOf ( ) { }
AllOf ( AllOf const & other ) : m_matchers ( other . m_matchers ) { }
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
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 ( ) ;
}
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
AllOf operator & & ( Matcher < ExpressionT > const & other ) const {
AllOf allOfExpr ( * this ) ;
allOfExpr . add ( other ) ;
return allOfExpr ;
}
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
private :
std : : vector < Ptr < Matcher < ExpressionT > > > m_matchers ;
} ;
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
template < typename ExpressionT >
class AnyOf : public MatcherImpl < AnyOf < ExpressionT > , ExpressionT > {
public :
2015-02-06 05:45:21 +08:00
2015-12-20 22:42:01 +08:00
AnyOf ( ) { }
AnyOf ( AnyOf const & other ) : m_matchers ( other . m_matchers ) { }
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
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 ( ) ;
}
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
AnyOf operator | | ( Matcher < ExpressionT > const & other ) const {
AnyOf anyOfExpr ( * this ) ;
anyOfExpr . add ( other ) ;
return anyOfExpr ;
}
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
private :
std : : vector < Ptr < Matcher < ExpressionT > > > m_matchers ;
} ;
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
} // namespace Generic
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
template < typename ExpressionT >
Generic : : AllOf < ExpressionT > Matcher < ExpressionT > : : operator & & ( Matcher < ExpressionT > const & other ) const {
Generic : : AllOf < ExpressionT > allOfExpr ;
allOfExpr . add ( * this ) ;
allOfExpr . add ( other ) ;
return allOfExpr ;
}
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
template < typename ExpressionT >
Generic : : AnyOf < ExpressionT > Matcher < ExpressionT > : : operator | | ( Matcher < ExpressionT > const & other ) const {
Generic : : AnyOf < ExpressionT > anyOfExpr ;
anyOfExpr . add ( * this ) ;
anyOfExpr . add ( other ) ;
return anyOfExpr ;
}
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
template < typename ExpressionT >
Generic : : Not < ExpressionT > Matcher < ExpressionT > : : operator ! ( ) const {
return Generic : : Not < ExpressionT > ( * this ) ;
}
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
namespace StdString {
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
inline std : : string makeString ( std : : string const & str ) { return str ; }
inline std : : string makeString ( const char * str ) { return str ? std : : string ( str ) : std : : string ( ) ; }
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
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 ;
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
}
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 {
2016-02-15 04:36:43 +08:00
return startsWith ( m_data . adjustString ( expr ) , m_data . m_str ) ;
2015-12-20 22:42:01 +08:00
}
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 {
2016-02-15 04:36:43 +08:00
return endsWith ( m_data . adjustString ( expr ) , m_data . m_str ) ;
2015-12-20 22:42:01 +08:00
}
virtual std : : string toString ( ) const {
return " ends with: \" " + m_data . m_str + " \" " + m_data . toStringSuffix ( ) ;
}
CasedString m_data ;
} ;
} // namespace StdString
} // namespace Impl
// The following functions create the actual matcher objects.
// This allows the types to be inferred
template < typename ExpressionT >
inline Impl : : Generic : : Not < ExpressionT > Not ( Impl : : Matcher < ExpressionT > const & m ) {
return Impl : : Generic : : Not < ExpressionT > ( m ) ;
}
template < typename ExpressionT >
inline Impl : : Generic : : AllOf < ExpressionT > AllOf ( Impl : : Matcher < ExpressionT > const & m1 ,
Impl : : Matcher < ExpressionT > const & m2 ) {
return Impl : : Generic : : AllOf < ExpressionT > ( ) . add ( m1 ) . add ( m2 ) ;
}
template < typename ExpressionT >
inline Impl : : Generic : : AllOf < ExpressionT > AllOf ( Impl : : Matcher < ExpressionT > const & m1 ,
Impl : : Matcher < ExpressionT > const & m2 ,
Impl : : Matcher < ExpressionT > const & m3 ) {
return Impl : : Generic : : AllOf < ExpressionT > ( ) . add ( m1 ) . add ( m2 ) . add ( m3 ) ;
}
template < typename ExpressionT >
inline Impl : : Generic : : AnyOf < ExpressionT > AnyOf ( Impl : : Matcher < ExpressionT > const & m1 ,
Impl : : Matcher < ExpressionT > const & m2 ) {
return Impl : : Generic : : AnyOf < ExpressionT > ( ) . add ( m1 ) . add ( m2 ) ;
}
template < typename ExpressionT >
inline Impl : : Generic : : AnyOf < ExpressionT > AnyOf ( Impl : : Matcher < ExpressionT > const & m1 ,
Impl : : Matcher < ExpressionT > const & m2 ,
Impl : : Matcher < ExpressionT > const & m3 ) {
return Impl : : Generic : : AnyOf < ExpressionT > ( ) . add ( m1 ) . add ( m2 ) . add ( m3 ) ;
}
inline Impl : : StdString : : Equals Equals ( std : : string const & str , CaseSensitive : : Choice caseSensitivity = CaseSensitive : : Yes ) {
return Impl : : StdString : : Equals ( str , caseSensitivity ) ;
}
inline Impl : : StdString : : Equals Equals ( const char * str , CaseSensitive : : Choice caseSensitivity = CaseSensitive : : Yes ) {
return Impl : : StdString : : Equals ( Impl : : StdString : : makeString ( str ) , caseSensitivity ) ;
}
inline Impl : : StdString : : Contains Contains ( std : : string const & substr , CaseSensitive : : Choice caseSensitivity = CaseSensitive : : Yes ) {
return Impl : : StdString : : Contains ( substr , caseSensitivity ) ;
}
inline Impl : : StdString : : Contains Contains ( const char * substr , CaseSensitive : : Choice caseSensitivity = CaseSensitive : : Yes ) {
return Impl : : StdString : : Contains ( Impl : : StdString : : makeString ( substr ) , caseSensitivity ) ;
}
inline Impl : : StdString : : StartsWith StartsWith ( std : : string const & substr ) {
return Impl : : StdString : : StartsWith ( substr ) ;
}
inline Impl : : StdString : : StartsWith StartsWith ( const char * substr ) {
return Impl : : StdString : : StartsWith ( Impl : : StdString : : makeString ( substr ) ) ;
}
inline Impl : : StdString : : EndsWith EndsWith ( std : : string const & substr ) {
return Impl : : StdString : : EndsWith ( substr ) ;
}
inline Impl : : StdString : : EndsWith EndsWith ( const char * substr ) {
return Impl : : StdString : : EndsWith ( Impl : : StdString : : makeString ( substr ) ) ;
}
} // namespace Matchers
using namespace Matchers ;
} // namespace Catch
namespace Catch {
struct TestFailureException { } ;
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 ,
ResultDisposition : : Flags resultDisposition ,
char const * secondArg = " " ) ;
template < typename T >
ExpressionLhs < T const & > operator < = ( T const & operand ) ;
ExpressionLhs < bool > operator < = ( bool value ) ;
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 ( ) ;
void captureExpectedException ( std : : string const & expectedMessage ) ;
void captureExpectedException ( Matchers : : Impl : : Matcher < std : : string > const & matcher ) ;
void handleResult ( AssertionResult const & result ) ;
void react ( ) ;
bool shouldDebugBreak ( ) const ;
bool allowThrows ( ) const ;
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
// #included from: catch_evaluate.hpp
# define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED
# ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable:4389) // '==' : signed/unsigned mismatch
# endif
# include <cstddef>
namespace Catch {
namespace Internal {
enum Operator {
IsEqualTo ,
IsNotEqualTo ,
IsLessThan ,
IsGreaterThan ,
IsLessThanOrEqualTo ,
IsGreaterThanOrEqualTo
} ;
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 " >= " ; } } ;
template < typename T >
inline T & opCast ( T const & t ) { return const_cast < T & > ( t ) ; }
// 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
// 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 { } ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
template < typename T1 , typename T2 >
2015-12-20 22:42:01 +08:00
struct Evaluator < T1 , T2 , IsEqualTo > {
static bool evaluate ( T1 const & lhs , T2 const & rhs ) {
2016-06-20 00:25:43 +08:00
return bool ( opCast ( lhs ) = = opCast ( rhs ) ) ;
2015-12-20 22:42:01 +08:00
}
} ;
template < typename T1 , typename T2 >
struct Evaluator < T1 , T2 , IsNotEqualTo > {
static bool evaluate ( T1 const & lhs , T2 const & rhs ) {
2016-06-20 00:25:43 +08:00
return bool ( opCast ( lhs ) ! = opCast ( rhs ) ) ;
2015-12-20 22:42:01 +08:00
}
} ;
template < typename T1 , typename T2 >
struct Evaluator < T1 , T2 , IsLessThan > {
static bool evaluate ( T1 const & lhs , T2 const & rhs ) {
2016-06-20 00:25:43 +08:00
return bool ( opCast ( lhs ) < opCast ( rhs ) ) ;
2015-12-20 22:42:01 +08:00
}
} ;
template < typename T1 , typename T2 >
2015-02-06 05:45:21 +08:00
struct Evaluator < T1 , T2 , IsGreaterThan > {
static bool evaluate ( T1 const & lhs , T2 const & rhs ) {
2016-06-20 00:25:43 +08:00
return bool ( opCast ( lhs ) > opCast ( rhs ) ) ;
2015-02-06 05:45:21 +08:00
}
} ;
template < typename T1 , typename T2 >
struct Evaluator < T1 , T2 , IsGreaterThanOrEqualTo > {
static bool evaluate ( T1 const & lhs , T2 const & rhs ) {
2016-06-20 00:25:43 +08:00
return bool ( opCast ( lhs ) > = opCast ( rhs ) ) ;
2015-02-06 05:45:21 +08:00
}
} ;
template < typename T1 , typename T2 >
struct Evaluator < T1 , T2 , IsLessThanOrEqualTo > {
static bool evaluate ( T1 const & lhs , T2 const & rhs ) {
2016-06-20 00:25:43 +08:00
return bool ( opCast ( lhs ) < = opCast ( rhs ) ) ;
2015-02-06 05:45:21 +08:00
}
} ;
template < Operator Op , typename T1 , typename T2 >
bool applyEvaluator ( T1 const & lhs , T2 const & rhs ) {
return Evaluator < T1 , T2 , Op > : : evaluate ( lhs , rhs ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
// This level of indirection allows us to specialise for integer types
// to avoid signed/ unsigned warnings
// "base" overload
template < Operator Op , typename T1 , typename T2 >
bool compare ( T1 const & lhs , T2 const & rhs ) {
return Evaluator < T1 , T2 , Op > : : evaluate ( lhs , rhs ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
// unsigned X to int
template < Operator Op > bool compare ( unsigned int lhs , int rhs ) {
return applyEvaluator < Op > ( lhs , static_cast < unsigned int > ( rhs ) ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
template < Operator Op > bool compare ( unsigned long lhs , int rhs ) {
return applyEvaluator < Op > ( lhs , static_cast < unsigned int > ( rhs ) ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
template < Operator Op > bool compare ( unsigned char lhs , int rhs ) {
return applyEvaluator < Op > ( lhs , static_cast < unsigned int > ( rhs ) ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
// unsigned X to long
template < Operator Op > bool compare ( unsigned int lhs , long rhs ) {
return applyEvaluator < Op > ( lhs , static_cast < unsigned long > ( rhs ) ) ;
}
template < Operator Op > bool compare ( unsigned long lhs , long rhs ) {
return applyEvaluator < Op > ( lhs , static_cast < unsigned long > ( rhs ) ) ;
}
template < Operator Op > bool compare ( unsigned char lhs , long rhs ) {
return applyEvaluator < Op > ( lhs , static_cast < unsigned long > ( rhs ) ) ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
// int to unsigned X
template < Operator Op > bool compare ( int lhs , unsigned int rhs ) {
return applyEvaluator < Op > ( static_cast < unsigned int > ( lhs ) , rhs ) ;
}
template < Operator Op > bool compare ( int lhs , unsigned long rhs ) {
return applyEvaluator < Op > ( static_cast < unsigned int > ( lhs ) , rhs ) ;
}
template < Operator Op > bool compare ( int lhs , unsigned char rhs ) {
return applyEvaluator < Op > ( static_cast < unsigned int > ( lhs ) , rhs ) ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
// long to unsigned X
template < Operator Op > bool compare ( long lhs , unsigned int rhs ) {
return applyEvaluator < Op > ( static_cast < unsigned long > ( lhs ) , rhs ) ;
}
template < Operator Op > bool compare ( long lhs , unsigned long rhs ) {
return applyEvaluator < Op > ( static_cast < unsigned long > ( lhs ) , rhs ) ;
}
template < Operator Op > bool compare ( long lhs , unsigned char rhs ) {
return applyEvaluator < Op > ( static_cast < unsigned long > ( lhs ) , rhs ) ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
// pointer to long (when comparing against NULL)
template < Operator Op , typename T > bool compare ( 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 rhs ) {
return Evaluator < T * , T * , Op > : : evaluate ( lhs , reinterpret_cast < T * > ( rhs ) ) ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
// pointer to int (when comparing against NULL)
template < Operator Op , typename T > bool compare ( int lhs , T * rhs ) {
return Evaluator < T * , T * , Op > : : evaluate ( reinterpret_cast < T * > ( lhs ) , rhs ) ;
}
template < Operator Op , typename T > bool compare ( T * lhs , int rhs ) {
return Evaluator < T * , T * , Op > : : evaluate ( lhs , reinterpret_cast < T * > ( rhs ) ) ;
}
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08: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
2014-12-28 16:11:01 +08:00
# ifdef CATCH_CONFIG_CPP11_NULLPTR
2015-02-06 05:45:21 +08:00
// pointer to nullptr_t (when comparing against nullptr)
template < Operator Op , typename T > bool compare ( std : : nullptr_t , T * rhs ) {
2015-12-20 22:42:01 +08:00
return Evaluator < T * , T * , Op > : : evaluate ( nullptr , rhs ) ;
2015-02-06 05:45:21 +08:00
}
template < Operator Op , typename T > bool compare ( T * lhs , std : : nullptr_t ) {
2015-12-20 22:42:01 +08:00
return Evaluator < T * , T * , Op > : : evaluate ( lhs , nullptr ) ;
2015-02-06 05:45:21 +08:00
}
2014-12-28 16:11:01 +08:00
# endif // CATCH_CONFIG_CPP11_NULLPTR
} // end of namespace Internal
} // end of namespace Catch
# ifdef _MSC_VER
2015-02-06 05:45:21 +08:00
# pragma warning(pop)
2014-12-28 16:11:01 +08:00
# endif
// #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
2015-02-06 05:45:21 +08:00
# define CATCH_ARC_ENABLED __has_feature(objc_arc)
2014-12-28 16:11:01 +08:00
# else
2015-02-06 05:45:21 +08:00
# define CATCH_ARC_ENABLED 0
2014-12-28 16:11:01 +08:00
# endif
void arcSafeRelease ( NSObject * obj ) ;
id performOptionalSelector ( id obj , SEL sel ) ;
# if !CATCH_ARC_ENABLED
2015-02-06 05:45:21 +08:00
inline void arcSafeRelease ( NSObject * obj ) {
2014-12-28 16:11:01 +08:00
[ obj release ] ;
}
2015-02-06 05:45:21 +08:00
inline id performOptionalSelector ( id obj , SEL sel ) {
if ( [ obj respondsToSelector : sel ] )
2014-12-28 16:11:01 +08:00
return [ obj performSelector : sel ] ;
return nil ;
}
# define CATCH_UNSAFE_UNRETAINED
# define CATCH_ARC_STRONG
# else
2015-02-06 05:45:21 +08:00
inline void arcSafeRelease ( NSObject * ) { }
inline id performOptionalSelector ( id obj , SEL sel ) {
2014-12-28 16:11:01 +08:00
# ifdef __clang__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Warc-performSelector-leaks"
# endif
2015-02-06 05:45:21 +08:00
if ( [ obj respondsToSelector : sel ] )
2014-12-28 16:11:01 +08:00
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-06-20 21:47:26 +08:00
# ifdef CATCH_CONFIG_CPP11_TUPLE
# include <tuple>
# endif
# ifdef CATCH_CONFIG_CPP11_IS_ENUM
# include <type_traits>
# endif
2015-02-06 05:45:21 +08:00
namespace Catch {
2015-06-20 21:47:26 +08:00
// Why we're here.
template < typename T >
std : : string toString ( T const & value ) ;
// Built in overloads
std : : string toString ( std : : string const & value ) ;
std : : string toString ( std : : wstring const & value ) ;
std : : string toString ( const char * const value ) ;
std : : string toString ( char * const value ) ;
std : : string toString ( const wchar_t * const value ) ;
std : : string toString ( wchar_t * const value ) ;
std : : string toString ( int value ) ;
std : : string toString ( unsigned long value ) ;
std : : string toString ( unsigned int value ) ;
std : : string toString ( const double value ) ;
std : : string toString ( const float value ) ;
std : : string toString ( bool value ) ;
std : : string toString ( char value ) ;
std : : string toString ( signed char value ) ;
std : : string toString ( unsigned char value ) ;
2015-12-20 22:42:01 +08:00
# ifdef CATCH_CONFIG_CPP11_LONG_LONG
std : : string toString ( long long value ) ;
std : : string toString ( unsigned long long value ) ;
# endif
2015-06-20 21:47:26 +08: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
2015-02-06 05:45:21 +08:00
namespace Detail {
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
extern const std : : string unprintableString ;
2015-06-20 21:47:26 +08:00
2015-02-06 05:45:21 +08:00
struct BorgType {
template < typename T > BorgType ( T const & ) ;
} ;
2014-12-28 16:11:01 +08:00
2015-07-26 16:41:38 +08:00
struct TrueType { char sizer [ 1 ] ; } ;
struct FalseType { char sizer [ 2 ] ; } ;
2015-02-06 05:45:21 +08:00
TrueType & testStreamable ( std : : ostream & ) ;
FalseType testStreamable ( FalseType ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
FalseType operator < < ( std : : ostream const & , BorgType const & ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
template < typename T >
struct IsStreamInsertable {
static std : : ostream & s ;
static T const & t ;
enum { value = sizeof ( testStreamable ( s < < t ) ) = = sizeof ( TrueType ) } ;
} ;
2014-12-28 16:11:01 +08:00
2015-06-20 21:47:26 +08:00
# if defined(CATCH_CONFIG_CPP11_IS_ENUM)
template < typename T ,
bool IsEnum = std : : is_enum < T > : : value
>
struct EnumStringMaker
{
static std : : string convert ( T const & ) { return unprintableString ; }
} ;
template < typename T >
struct EnumStringMaker < T , true >
{
static std : : string convert ( T const & v )
{
return : : Catch : : toString (
static_cast < typename std : : underlying_type < T > : : type > ( v )
) ;
}
} ;
# endif
2015-02-06 05:45:21 +08:00
template < bool C >
struct StringMakerBase {
2015-06-20 21:47:26 +08:00
# if defined(CATCH_CONFIG_CPP11_IS_ENUM)
2015-02-06 05:45:21 +08:00
template < typename T >
2015-06-20 21:47:26 +08:00
static std : : string convert ( T const & v )
{
return EnumStringMaker < T > : : convert ( v ) ;
}
# else
template < typename T >
static std : : string convert ( T const & ) { return unprintableString ; }
# endif
2015-02-06 05:45:21 +08:00
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
template < >
struct StringMakerBase < true > {
template < typename T >
static std : : string convert ( T const & _value ) {
std : : ostringstream oss ;
oss < < _value ;
return oss . str ( ) ;
}
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
std : : string rawMemoryToString ( const void * object , std : : size_t size ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
template < typename T >
inline std : : string rawMemoryToString ( const T & object ) {
return rawMemoryToString ( & object , sizeof ( object ) ) ;
}
2014-12-28 16:11:01 +08:00
} // end namespace Detail
template < typename T >
struct StringMaker :
Detail : : StringMakerBase < Detail : : IsStreamInsertable < T > : : value > { } ;
template < typename T >
2015-02-06 05:45:21 +08:00
struct StringMaker < T * > {
2014-12-28 16:11:01 +08:00
template < typename U >
2015-02-06 05:45:21 +08:00
static std : : string convert ( U * p ) {
if ( ! p )
2015-12-20 22:42:01 +08:00
return " NULL " ;
2014-12-28 16:11:01 +08:00
else
return Detail : : rawMemoryToString ( p ) ;
}
} ;
template < typename R , typename C >
2015-02-06 05:45:21 +08:00
struct StringMaker < R C : : * > {
static std : : string convert ( R C : : * p ) {
if ( ! p )
2015-12-20 22:42:01 +08:00
return " NULL " ;
2014-12-28 16:11:01 +08:00
else
return Detail : : rawMemoryToString ( p ) ;
}
} ;
2015-02-06 05:45:21 +08:00
namespace Detail {
template < typename InputIterator >
std : : string rangeToString ( InputIterator first , InputIterator last ) ;
2014-12-28 16:11:01 +08:00
}
2015-06-20 21:47:26 +08: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-12-28 16:11:01 +08:00
template < typename T , typename Allocator >
2015-06-20 21:47:26 +08:00
std : : string toString ( std : : vector < T , Allocator > const & v ) {
return Detail : : rangeToString ( v . begin ( ) , v . end ( ) ) ;
}
# ifdef CATCH_CONFIG_CPP11_TUPLE
// toString for tuples
namespace TupleDetail {
template <
typename Tuple ,
std : : size_t N = 0 ,
bool = ( N < std : : tuple_size < Tuple > : : value )
>
struct ElementPrinter {
static void print ( const Tuple & tuple , std : : ostream & os )
{
os < < ( N ? " , " : " " )
< < Catch : : toString ( std : : get < N > ( tuple ) ) ;
ElementPrinter < Tuple , N + 1 > : : print ( tuple , os ) ;
}
} ;
template <
typename Tuple ,
std : : size_t N
>
struct ElementPrinter < Tuple , N , false > {
static void print ( const Tuple & , std : : ostream & ) { }
} ;
}
template < typename . . . Types >
struct StringMaker < std : : tuple < Types . . . > > {
static std : : string convert ( const std : : tuple < Types . . . > & tuple )
{
std : : ostringstream os ;
os < < ' { ' ;
TupleDetail : : ElementPrinter < std : : tuple < Types . . . > > : : print ( tuple , os ) ;
os < < " } " ;
return os . str ( ) ;
2014-12-28 16:11:01 +08:00
}
} ;
2015-06-20 21:47:26 +08:00
# endif // CATCH_CONFIG_CPP11_TUPLE
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
namespace Detail {
template < typename T >
std : : string makeString ( T const & value ) {
return StringMaker < T > : : convert ( value ) ;
}
2014-12-28 16:11:01 +08:00
} // 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 >
2015-02-06 05:45:21 +08:00
std : : string toString ( T const & value ) {
2014-12-28 16:11:01 +08:00
return StringMaker < T > : : convert ( value ) ;
}
2015-02-06 05:45:21 +08:00
namespace Detail {
template < typename InputIterator >
std : : string rangeToString ( InputIterator first , InputIterator last ) {
std : : ostringstream oss ;
oss < < " { " ;
if ( first ! = last ) {
2015-06-20 21:47:26 +08:00
oss < < Catch : : toString ( * first ) ;
for ( + + first ; first ! = last ; + + first )
oss < < " , " < < Catch : : toString ( * first ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
oss < < " } " ;
return oss . str ( ) ;
2014-12-28 16:11:01 +08:00
}
}
} // end namespace Catch
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
// Wraps the LHS of an expression and captures the operator and RHS (if any) -
// wrapping them all in a ResultBuilder object
template < typename T >
2015-02-06 05:45:21 +08:00
class ExpressionLhs {
ExpressionLhs & operator = ( ExpressionLhs const & ) ;
2015-06-20 21:47:26 +08:00
# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
2015-02-06 05:45:21 +08:00
ExpressionLhs & operator = ( ExpressionLhs & & ) = delete ;
2014-12-28 16:11:01 +08:00
# endif
2015-02-06 05:45:21 +08:00
public :
2014-12-28 16:11:01 +08:00
ExpressionLhs ( ResultBuilder & rb , T lhs ) : m_rb ( rb ) , m_lhs ( lhs ) { }
2015-06-20 21:47:26 +08:00
# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
2015-02-06 05:45:21 +08:00
ExpressionLhs ( ExpressionLhs const & ) = default ;
ExpressionLhs ( ExpressionLhs & & ) = default ;
2014-12-28 16:11:01 +08:00
# endif
template < typename RhsT >
2015-02-06 05:45:21 +08:00
ResultBuilder & operator = = ( RhsT const & rhs ) {
2014-12-28 16:11:01 +08:00
return captureExpression < Internal : : IsEqualTo > ( rhs ) ;
}
template < typename RhsT >
2015-02-06 05:45:21 +08:00
ResultBuilder & operator ! = ( RhsT const & rhs ) {
2014-12-28 16:11:01 +08:00
return captureExpression < Internal : : IsNotEqualTo > ( rhs ) ;
}
template < typename RhsT >
2015-02-06 05:45:21 +08:00
ResultBuilder & operator < ( RhsT const & rhs ) {
2014-12-28 16:11:01 +08:00
return captureExpression < Internal : : IsLessThan > ( rhs ) ;
}
template < typename RhsT >
2015-02-06 05:45:21 +08:00
ResultBuilder & operator > ( RhsT const & rhs ) {
2014-12-28 16:11:01 +08:00
return captureExpression < Internal : : IsGreaterThan > ( rhs ) ;
}
template < typename RhsT >
2015-02-06 05:45:21 +08:00
ResultBuilder & operator < = ( RhsT const & rhs ) {
2014-12-28 16:11:01 +08:00
return captureExpression < Internal : : IsLessThanOrEqualTo > ( rhs ) ;
}
template < typename RhsT >
2015-02-06 05:45:21 +08:00
ResultBuilder & operator > = ( RhsT const & rhs ) {
2014-12-28 16:11:01 +08:00
return captureExpression < Internal : : IsGreaterThanOrEqualTo > ( rhs ) ;
}
2015-02-06 05:45:21 +08:00
ResultBuilder & operator = = ( bool rhs ) {
2014-12-28 16:11:01 +08:00
return captureExpression < Internal : : IsEqualTo > ( rhs ) ;
}
2015-02-06 05:45:21 +08:00
ResultBuilder & operator ! = ( bool rhs ) {
2014-12-28 16:11:01 +08:00
return captureExpression < Internal : : IsNotEqualTo > ( rhs ) ;
}
2015-02-06 05:45:21 +08:00
void endExpression ( ) {
2014-12-28 16:11:01 +08:00
bool value = m_lhs ? true : false ;
m_rb
2015-02-06 05:45:21 +08:00
. setLhs ( Catch : : toString ( value ) )
. setResultType ( value )
. endExpression ( ) ;
2014-12-28 16:11:01 +08:00
}
// Only simple binary expressions are allowed on the LHS.
// If more complex compositions are required then place the sub expression in parentheses
2015-02-06 05:45:21 +08: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 & ) ;
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 & ) ;
private :
2014-12-28 16:11:01 +08:00
template < Internal : : Operator Op , typename RhsT >
2015-02-06 05:45:21 +08:00
ResultBuilder & captureExpression ( RhsT const & rhs ) {
2014-12-28 16:11:01 +08:00
return m_rb
2015-02-06 05:45:21 +08:00
. setResultType ( Internal : : compare < Op > ( m_lhs , rhs ) )
. setLhs ( Catch : : toString ( m_lhs ) )
. setRhs ( Catch : : toString ( rhs ) )
. setOp ( Internal : : OperatorTraits < Op > : : getName ( ) ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
private :
2014-12-28 16:11:01 +08:00
ResultBuilder & m_rb ;
T m_lhs ;
} ;
} // end namespace Catch
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
template < typename T >
2015-07-26 16:41:38 +08:00
inline ExpressionLhs < T const & > ResultBuilder : : operator < = ( T const & operand ) {
2015-02-06 05:45:21 +08:00
return ExpressionLhs < T const & > ( * this , operand ) ;
}
2014-12-28 16:11:01 +08:00
2015-07-26 16:41:38 +08:00
inline ExpressionLhs < bool > ResultBuilder : : operator < = ( bool value ) {
2015-02-06 05:45:21 +08:00
return ExpressionLhs < bool > ( * this , value ) ;
}
2014-12-28 16:11:01 +08:00
} // namespace Catch
// #included from: catch_message.h
# define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED
# include <string>
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
struct MessageInfo {
MessageInfo ( std : : string const & _macroName ,
SourceLineInfo const & _lineInfo ,
ResultWas : : OfType _type ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
std : : string macroName ;
SourceLineInfo lineInfo ;
ResultWas : : OfType type ;
std : : string message ;
unsigned int sequence ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
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 ;
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
struct MessageBuilder {
MessageBuilder ( std : : string const & macroName ,
SourceLineInfo const & lineInfo ,
ResultWas : : OfType type )
2014-12-28 16:11:01 +08:00
: m_info ( macroName , lineInfo , type )
2015-02-06 05:45:21 +08:00
{ }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
template < typename T >
MessageBuilder & operator < < ( T const & value ) {
m_stream < < value ;
return * this ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
MessageInfo m_info ;
std : : ostringstream m_stream ;
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
class ScopedMessage {
public :
ScopedMessage ( MessageBuilder const & builder ) ;
ScopedMessage ( ScopedMessage const & other ) ;
~ ScopedMessage ( ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
MessageInfo m_info ;
} ;
2014-12-28 16:11:01 +08:00
} // end namespace Catch
// #included from: catch_interfaces_capture.h
# define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED
# include <string>
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
class TestCase ;
class AssertionResult ;
struct AssertionInfo ;
struct SectionInfo ;
2015-12-20 22:42:01 +08:00
struct SectionEndInfo ;
2015-02-06 05:45:21 +08:00
struct MessageInfo ;
class ScopedMessageBuilder ;
struct Counts ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
struct IResultCapture {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
virtual ~ IResultCapture ( ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
virtual void assertionEnded ( AssertionResult const & result ) = 0 ;
virtual bool sectionStarted ( SectionInfo const & sectionInfo ,
Counts & assertions ) = 0 ;
2015-12-20 22:42:01 +08:00
virtual void sectionEnded ( SectionEndInfo const & endInfo ) = 0 ;
virtual void sectionEndedEarly ( SectionEndInfo const & endInfo ) = 0 ;
2015-02-06 05:45:21 +08:00
virtual void pushScopedMessage ( MessageInfo const & message ) = 0 ;
virtual void popScopedMessage ( MessageInfo const & message ) = 0 ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
virtual std : : string getCurrentTestName ( ) const = 0 ;
virtual const AssertionResult * getLastResult ( ) const = 0 ;
2015-06-20 21:47:26 +08:00
virtual void handleFatalErrorCondition ( std : : string const & message ) = 0 ;
2015-02-06 05:45:21 +08:00
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
IResultCapture & getResultCapture ( ) ;
2014-12-28 16:11:01 +08:00
}
// #included from: catch_debugger.h
# define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED
// #included from: catch_platform.h
# define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED
# if defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
2015-02-06 05:45:21 +08:00
# define CATCH_PLATFORM_MAC
2014-12-28 16:11:01 +08:00
# elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
2015-02-06 05:45:21 +08:00
# define CATCH_PLATFORM_IPHONE
2014-12-28 16:11:01 +08:00
# elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
2015-02-06 05:45:21 +08:00
# define CATCH_PLATFORM_WINDOWS
2014-12-28 16:11:01 +08:00
# endif
# include <string>
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
bool isDebuggerActive ( ) ;
void writeToDebugConsole ( std : : string const & text ) ;
2014-12-28 16:11:01 +08:00
}
# ifdef CATCH_PLATFORM_MAC
2015-02-06 05:45:21 +08:00
// The following code snippet based on:
// http://cocoawithlove.com/2008/03/break-into-debugger.html
# ifdef DEBUG
# if defined(__ppc64__) || defined(__ppc__)
# define CATCH_BREAK_INTO_DEBUGGER() \
if ( Catch : : isDebuggerActive ( ) ) { \
__asm__ ( " li r0, 20 \n sc \n nop \n li r0, 37 \n li r4, 2 \n sc \n nop \n " \
: : : " memory " , " r0 " , " r3 " , " r4 " ) ; \
}
# else
# define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );}
# endif
# endif
2014-12-28 16:11:01 +08:00
# elif defined(_MSC_VER)
2015-02-06 05:45:21 +08:00
# define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { __debugbreak(); }
2014-12-28 16:11:01 +08:00
# elif defined(__MINGW32__)
2015-02-06 05:45:21 +08:00
extern " C " __declspec ( dllimport ) void __stdcall DebugBreak ( ) ;
# define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { DebugBreak(); }
2014-12-28 16:11:01 +08:00
# endif
# ifndef CATCH_BREAK_INTO_DEBUGGER
2015-02-06 05:45:21 +08:00
# define CATCH_BREAK_INTO_DEBUGGER() Catch::alwaysTrue();
2014-12-28 16:11:01 +08:00
# endif
// #included from: catch_interfaces_runner.h
# define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED
2015-02-06 05:45:21 +08:00
namespace Catch {
class TestCase ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
struct IRunner {
virtual ~ IRunner ( ) ;
virtual bool aborting ( ) const = 0 ;
} ;
2014-12-28 16:11:01 +08: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 ( ) ;
///////////////////////////////////////////////////////////////////////////////
# define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \
do { \
Catch : : ResultBuilder __catchResult ( macroName , CATCH_INTERNAL_LINEINFO , # expr , resultDisposition ) ; \
try { \
2016-06-20 00:25:43 +08:00
CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
2015-07-26 16:41:38 +08:00
( __catchResult < = expr ) . endExpression ( ) ; \
2014-12-28 16:11:01 +08:00
} \
catch ( . . . ) { \
__catchResult . useActiveException ( Catch : : ResultDisposition : : Normal ) ; \
} \
INTERNAL_CATCH_REACT ( __catchResult ) \
2016-06-20 00:25:43 +08:00
} while ( Catch : : isTrue ( false & & ! ! ( expr ) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look
2014-12-28 16:11:01 +08:00
///////////////////////////////////////////////////////////////////////////////
# define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \
INTERNAL_CATCH_TEST ( expr , resultDisposition , macroName ) ; \
if ( Catch : : getResultCapture ( ) . getLastResult ( ) - > succeeded ( ) )
///////////////////////////////////////////////////////////////////////////////
# define INTERNAL_CATCH_ELSE( expr, resultDisposition, macroName ) \
INTERNAL_CATCH_TEST ( expr , resultDisposition , macroName ) ; \
if ( ! Catch : : getResultCapture ( ) . getLastResult ( ) - > succeeded ( ) )
///////////////////////////////////////////////////////////////////////////////
# define INTERNAL_CATCH_NO_THROW( expr, resultDisposition, macroName ) \
do { \
Catch : : ResultBuilder __catchResult ( macroName , CATCH_INTERNAL_LINEINFO , # expr , resultDisposition ) ; \
try { \
expr ; \
__catchResult . captureResult ( Catch : : ResultWas : : Ok ) ; \
} \
catch ( . . . ) { \
__catchResult . useActiveException ( resultDisposition ) ; \
} \
INTERNAL_CATCH_REACT ( __catchResult ) \
} while ( Catch : : alwaysFalse ( ) )
///////////////////////////////////////////////////////////////////////////////
2015-12-20 22:42:01 +08:00
# define INTERNAL_CATCH_THROWS( expr, resultDisposition, matcher, macroName ) \
2014-12-28 16:11:01 +08:00
do { \
2015-12-20 22:42:01 +08:00
Catch : : ResultBuilder __catchResult ( macroName , CATCH_INTERNAL_LINEINFO , # expr , resultDisposition , # matcher ) ; \
2014-12-28 16:11:01 +08:00
if ( __catchResult . allowThrows ( ) ) \
try { \
expr ; \
__catchResult . captureResult ( Catch : : ResultWas : : DidntThrowException ) ; \
} \
catch ( . . . ) { \
2015-12-20 22:42:01 +08:00
__catchResult . captureExpectedException ( matcher ) ; \
2014-12-28 16:11:01 +08:00
} \
else \
__catchResult . captureResult ( Catch : : ResultWas : : Ok ) ; \
INTERNAL_CATCH_REACT ( __catchResult ) \
} while ( Catch : : alwaysFalse ( ) )
///////////////////////////////////////////////////////////////////////////////
# define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, resultDisposition, macroName ) \
do { \
Catch : : ResultBuilder __catchResult ( macroName , CATCH_INTERNAL_LINEINFO , # expr , resultDisposition ) ; \
if ( __catchResult . allowThrows ( ) ) \
try { \
expr ; \
__catchResult . captureResult ( Catch : : ResultWas : : DidntThrowException ) ; \
} \
catch ( exceptionType ) { \
__catchResult . captureResult ( Catch : : ResultWas : : Ok ) ; \
} \
catch ( . . . ) { \
__catchResult . useActiveException ( resultDisposition ) ; \
} \
else \
__catchResult . captureResult ( Catch : : ResultWas : : Ok ) ; \
INTERNAL_CATCH_REACT ( __catchResult ) \
} while ( Catch : : alwaysFalse ( ) )
///////////////////////////////////////////////////////////////////////////////
# ifdef CATCH_CONFIG_VARIADIC_MACROS
2015-02-06 05:45:21 +08:00
# define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, ... ) \
do { \
Catch : : ResultBuilder __catchResult ( macroName , CATCH_INTERNAL_LINEINFO , " " , resultDisposition ) ; \
__catchResult < < __VA_ARGS__ + : : Catch : : StreamEndStop ( ) ; \
__catchResult . captureResult ( messageType ) ; \
INTERNAL_CATCH_REACT ( __catchResult ) \
} while ( Catch : : alwaysFalse ( ) )
2014-12-28 16:11:01 +08:00
# else
2015-02-06 05:45:21 +08:00
# define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, log ) \
do { \
Catch : : ResultBuilder __catchResult ( macroName , CATCH_INTERNAL_LINEINFO , " " , resultDisposition ) ; \
__catchResult < < log + : : Catch : : StreamEndStop ( ) ; \
__catchResult . captureResult ( messageType ) ; \
INTERNAL_CATCH_REACT ( __catchResult ) \
} while ( Catch : : alwaysFalse ( ) )
2014-12-28 16:11:01 +08:00
# endif
///////////////////////////////////////////////////////////////////////////////
# define INTERNAL_CATCH_INFO( log, macroName ) \
Catch : : ScopedMessage INTERNAL_CATCH_UNIQUE_NAME ( scopedMessage ) = Catch : : MessageBuilder ( macroName , CATCH_INTERNAL_LINEINFO , Catch : : ResultWas : : Info ) < < log ;
///////////////////////////////////////////////////////////////////////////////
# define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \
do { \
2016-02-15 04:36:43 +08:00
Catch : : ResultBuilder __catchResult ( macroName , CATCH_INTERNAL_LINEINFO , # arg " , " # matcher , resultDisposition ) ; \
2014-12-28 16:11:01 +08:00
try { \
2015-12-20 22:42:01 +08:00
std : : string matcherAsString = ( matcher ) . toString ( ) ; \
2014-12-28 16:11:01 +08:00
__catchResult \
2015-02-06 05:45:21 +08:00
. setLhs ( Catch : : toString ( arg ) ) \
2015-06-20 21:47:26 +08:00
. setRhs ( matcherAsString = = Catch : : Detail : : unprintableString ? # matcher : matcherAsString ) \
2015-02-06 05:45:21 +08:00
. setOp ( " matches " ) \
2015-12-20 22:42:01 +08:00
. setResultType ( ( matcher ) . match ( arg ) ) ; \
2014-12-28 16:11:01 +08:00
__catchResult . captureExpression ( ) ; \
} catch ( . . . ) { \
__catchResult . useActiveException ( resultDisposition | Catch : : ResultDisposition : : ContinueOnFailure ) ; \
} \
INTERNAL_CATCH_REACT ( __catchResult ) \
2015-12-20 22:42:01 +08:00
} while ( Catch : : alwaysFalse ( ) )
2015-02-06 05:45:21 +08:00
2015-12-20 22:42:01 +08:00
// #included from: internal/catch_section.h
# define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
// #included from: catch_section_info.h
# define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED
2014-12-28 16:11:01 +08:00
// #included from: catch_totals.hpp
# define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED
# include <cstddef>
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
struct Counts {
Counts ( ) : passed ( 0 ) , failed ( 0 ) , failedButOk ( 0 ) { }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
Counts operator - ( Counts const & other ) const {
Counts diff ;
diff . passed = passed - other . passed ;
diff . failed = failed - other . failed ;
diff . failedButOk = failedButOk - other . failedButOk ;
return diff ;
}
Counts & operator + = ( Counts const & other ) {
passed + = other . passed ;
failed + = other . failed ;
failedButOk + = other . failedButOk ;
return * this ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
std : : size_t total ( ) const {
return passed + failed + failedButOk ;
}
bool allPassed ( ) const {
return failed = = 0 & & failedButOk = = 0 ;
}
2015-06-20 21:47:26 +08:00
bool allOk ( ) const {
return failed = = 0 ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
std : : size_t passed ;
std : : size_t failed ;
std : : size_t failedButOk ;
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
struct Totals {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
Totals operator - ( Totals const & other ) const {
Totals diff ;
diff . assertions = assertions - other . assertions ;
diff . testCases = testCases - other . testCases ;
return diff ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
Totals delta ( Totals const & prevTotals ) const {
Totals diff = * this - prevTotals ;
if ( diff . assertions . failed > 0 )
+ + diff . testCases . failed ;
else if ( diff . assertions . failedButOk > 0 )
+ + diff . testCases . failedButOk ;
else
+ + diff . testCases . passed ;
return diff ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
Totals & operator + = ( Totals const & other ) {
assertions + = other . assertions ;
testCases + = other . testCases ;
return * this ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
Counts assertions ;
Counts testCases ;
} ;
2014-12-28 16:11:01 +08:00
}
2015-12-20 22:42:01 +08:00
namespace Catch {
struct SectionInfo {
SectionInfo
( SourceLineInfo const & _lineInfo ,
std : : string const & _name ,
std : : string const & _description = std : : string ( ) ) ;
std : : string name ;
std : : string description ;
SourceLineInfo lineInfo ;
} ;
struct SectionEndInfo {
SectionEndInfo ( SectionInfo const & _sectionInfo , Counts const & _prevAssertions , double _durationInSeconds )
: sectionInfo ( _sectionInfo ) , prevAssertions ( _prevAssertions ) , durationInSeconds ( _durationInSeconds )
{ }
SectionInfo sectionInfo ;
Counts prevAssertions ;
double durationInSeconds ;
} ;
} // end namespace Catch
2014-12-28 16:11:01 +08:00
// #included from: catch_timer.h
# define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED
# ifdef CATCH_PLATFORM_WINDOWS
2015-02-06 05:45:21 +08:00
typedef unsigned long long uint64_t ;
2014-12-28 16:11:01 +08:00
# else
2015-02-06 05:45:21 +08:00
# include <stdint.h>
2014-12-28 16:11:01 +08:00
# endif
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
class Timer {
public :
Timer ( ) : m_ticks ( 0 ) { }
void start ( ) ;
2015-06-20 21:47:26 +08:00
unsigned int getElapsedMicroseconds ( ) const ;
2015-02-06 05:45:21 +08:00
unsigned int getElapsedMilliseconds ( ) const ;
double getElapsedSeconds ( ) const ;
private :
uint64_t m_ticks ;
} ;
2014-12-28 16:11:01 +08:00
} // namespace Catch
# include <string>
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-06-20 21:47:26 +08:00
class Section : NonCopyable {
2015-02-06 05:45:21 +08:00
public :
Section ( SectionInfo const & info ) ;
~ Section ( ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
// This indicates whether the section should be executed or not
operator bool ( ) const ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
private :
SectionInfo m_info ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
std : : string m_name ;
Counts m_assertions ;
bool m_sectionIncluded ;
Timer m_timer ;
} ;
2014-12-28 16:11:01 +08:00
} // end namespace Catch
# ifdef CATCH_CONFIG_VARIADIC_MACROS
2015-02-06 05:45:21 +08:00
# define INTERNAL_CATCH_SECTION( ... ) \
if ( Catch : : Section const & INTERNAL_CATCH_UNIQUE_NAME ( catch_internal_Section ) = Catch : : SectionInfo ( CATCH_INTERNAL_LINEINFO , __VA_ARGS__ ) )
2014-12-28 16:11:01 +08:00
# else
2015-02-06 05:45:21 +08:00
# define INTERNAL_CATCH_SECTION( name, desc ) \
if ( Catch : : Section const & INTERNAL_CATCH_UNIQUE_NAME ( catch_internal_Section ) = Catch : : SectionInfo ( CATCH_INTERNAL_LINEINFO , name , desc ) )
2014-12-28 16:11:01 +08:00
# endif
// #included from: internal/catch_generators.hpp
# define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED
# include <iterator>
# include <vector>
# include <string>
# include <stdlib.h>
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
template < typename T >
2015-02-06 05:45:21 +08:00
struct IGenerator {
2014-12-28 16:11:01 +08:00
virtual ~ IGenerator ( ) { }
virtual T getValue ( std : : size_t index ) const = 0 ;
virtual std : : size_t size ( ) const = 0 ;
} ;
template < typename T >
2015-02-06 05:45:21 +08:00
class BetweenGenerator : public IGenerator < T > {
public :
BetweenGenerator ( T from , T to ) : m_from ( from ) , m_to ( to ) { }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
virtual T getValue ( std : : size_t index ) const {
return m_from + static_cast < int > ( index ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
virtual std : : size_t size ( ) const {
return static_cast < std : : size_t > ( 1 + m_to - m_from ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
private :
2014-12-28 16:11:01 +08:00
T m_from ;
T m_to ;
} ;
template < typename T >
2015-02-06 05:45:21 +08:00
class ValuesGenerator : public IGenerator < T > {
public :
ValuesGenerator ( ) { }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
void add ( T value ) {
2014-12-28 16:11:01 +08:00
m_values . push_back ( value ) ;
}
2015-02-06 05:45:21 +08:00
virtual T getValue ( std : : size_t index ) const {
2014-12-28 16:11:01 +08:00
return m_values [ index ] ;
}
2015-02-06 05:45:21 +08:00
virtual std : : size_t size ( ) const {
2014-12-28 16:11:01 +08:00
return m_values . size ( ) ;
}
2015-02-06 05:45:21 +08:00
private :
2014-12-28 16:11:01 +08:00
std : : vector < T > m_values ;
} ;
template < typename T >
2015-02-06 05:45:21 +08:00
class CompositeGenerator {
public :
2014-12-28 16:11:01 +08:00
CompositeGenerator ( ) : m_totalSize ( 0 ) { }
// *** Move semantics, similar to auto_ptr ***
CompositeGenerator ( CompositeGenerator & other )
2015-02-06 05:45:21 +08:00
: m_fileInfo ( other . m_fileInfo ) ,
m_totalSize ( 0 )
2014-12-28 16:11:01 +08:00
{
move ( other ) ;
}
2015-02-06 05:45:21 +08:00
CompositeGenerator & setFileInfo ( const char * fileInfo ) {
2014-12-28 16:11:01 +08:00
m_fileInfo = fileInfo ;
return * this ;
}
2015-02-06 05:45:21 +08:00
~ CompositeGenerator ( ) {
2014-12-28 16:11:01 +08:00
deleteAll ( m_composed ) ;
}
2015-02-06 05:45:21 +08:00
operator T ( ) const {
2014-12-28 16:11:01 +08:00
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 ( ) ;
2015-02-06 05:45:21 +08:00
for ( size_t index = 0 ; it ! = itEnd ; + + it )
2014-12-28 16:11:01 +08:00
{
const IGenerator < T > * generator = * it ;
2015-02-06 05:45:21 +08:00
if ( overallIndex > = index & & overallIndex < index + generator - > size ( ) )
2014-12-28 16:11:01 +08:00
{
2015-02-06 05:45:21 +08:00
return generator - > getValue ( overallIndex - index ) ;
2014-12-28 16:11:01 +08:00
}
index + = generator - > size ( ) ;
}
CATCH_INTERNAL_ERROR ( " Indexed past end of generated range " ) ;
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
}
2015-02-06 05:45:21 +08:00
void add ( const IGenerator < T > * generator ) {
2014-12-28 16:11:01 +08:00
m_totalSize + = generator - > size ( ) ;
m_composed . push_back ( generator ) ;
}
2015-02-06 05:45:21 +08:00
CompositeGenerator & then ( CompositeGenerator & other ) {
2014-12-28 16:11:01 +08:00
move ( other ) ;
return * this ;
}
2015-02-06 05:45:21 +08:00
CompositeGenerator & then ( T value ) {
2014-12-28 16:11:01 +08:00
ValuesGenerator < T > * valuesGen = new ValuesGenerator < T > ( ) ;
valuesGen - > add ( value ) ;
add ( valuesGen ) ;
return * this ;
}
2015-02-06 05:45:21 +08:00
private :
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
void move ( CompositeGenerator & other ) {
2014-12-28 16:11:01 +08:00
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
{
2015-02-06 05:45:21 +08:00
template < typename T >
CompositeGenerator < T > between ( T from , T to ) {
CompositeGenerator < T > generators ;
generators . add ( new BetweenGenerator < T > ( from , to ) ) ;
return generators ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
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 ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
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 ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
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 ;
}
2014-12-28 16:11:01 +08:00
} // 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>
2015-12-20 22:42:01 +08:00
# include <vector>
2014-12-28 16:11:01 +08:00
// #included from: catch_interfaces_registry_hub.h
# define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED
# include <string>
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
class TestCase ;
struct ITestCaseRegistry ;
struct IExceptionTranslatorRegistry ;
struct IExceptionTranslator ;
struct IReporterRegistry ;
struct IReporterFactory ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
struct IRegistryHub {
virtual ~ IRegistryHub ( ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
virtual IReporterRegistry const & getReporterRegistry ( ) const = 0 ;
virtual ITestCaseRegistry const & getTestCaseRegistry ( ) const = 0 ;
virtual IExceptionTranslatorRegistry & getExceptionTranslatorRegistry ( ) = 0 ;
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
struct IMutableRegistryHub {
virtual ~ IMutableRegistryHub ( ) ;
2015-12-20 22:42:01 +08:00
virtual void registerReporter ( std : : string const & name , Ptr < IReporterFactory > const & factory ) = 0 ;
virtual void registerListener ( Ptr < IReporterFactory > const & factory ) = 0 ;
2015-02-06 05:45:21 +08:00
virtual void registerTest ( TestCase const & testInfo ) = 0 ;
virtual void registerTranslator ( const IExceptionTranslator * translator ) = 0 ;
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
IRegistryHub & getRegistryHub ( ) ;
IMutableRegistryHub & getMutableRegistryHub ( ) ;
void cleanUp ( ) ;
std : : string translateActiveException ( ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
typedef std : : string ( * exceptionTranslateFunction ) ( ) ;
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
struct IExceptionTranslator ;
typedef std : : vector < const IExceptionTranslator * > ExceptionTranslators ;
2015-02-06 05:45:21 +08:00
struct IExceptionTranslator {
virtual ~ IExceptionTranslator ( ) ;
2015-12-20 22:42:01 +08:00
virtual std : : string translate ( ExceptionTranslators : : const_iterator it , ExceptionTranslators : : const_iterator itEnd ) const = 0 ;
2015-02-06 05:45:21 +08:00
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
struct IExceptionTranslatorRegistry {
virtual ~ IExceptionTranslatorRegistry ( ) ;
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
virtual std : : string translateActiveException ( ) const = 0 ;
} ;
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
class ExceptionTranslatorRegistrar {
template < typename T >
class ExceptionTranslator : public IExceptionTranslator {
public :
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
ExceptionTranslator ( std : : string ( * translateFunction ) ( T & ) )
: m_translateFunction ( translateFunction )
{ }
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
virtual std : : string translate ( ExceptionTranslators : : const_iterator it , ExceptionTranslators : : const_iterator itEnd ) const CATCH_OVERRIDE {
try {
if ( it = = itEnd )
throw ;
else
return ( * it ) - > translate ( it + 1 , itEnd ) ;
}
catch ( T & ex ) {
return m_translateFunction ( ex ) ;
}
2015-02-06 05:45:21 +08:00
}
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
protected :
std : : string ( * m_translateFunction ) ( T & ) ;
2015-02-06 05:45:21 +08:00
} ;
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
public :
template < typename T >
ExceptionTranslatorRegistrar ( std : : string ( * translateFunction ) ( T & ) ) {
getMutableRegistryHub ( ) . registerTranslator
( new ExceptionTranslator < T > ( translateFunction ) ) ;
}
} ;
}
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
///////////////////////////////////////////////////////////////////////////////
2016-06-20 00:25:43 +08:00
# define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \
static std : : string translatorName ( signature ) ; \
namespace { Catch : : ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME ( catch_internal_ExceptionRegistrar ) ( & translatorName ) ; } \
static std : : string translatorName ( signature )
# define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
// #included from: internal/catch_approx.hpp
# define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
# include <cmath>
# include <limits>
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
namespace Catch {
namespace Detail {
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
class Approx {
public :
explicit Approx ( double value )
: m_epsilon ( std : : numeric_limits < float > : : epsilon ( ) * 100 ) ,
m_scale ( 1.0 ) ,
m_value ( value )
{ }
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
Approx ( Approx const & other )
: m_epsilon ( other . m_epsilon ) ,
m_scale ( other . m_scale ) ,
m_value ( other . m_value )
{ }
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
static Approx custom ( ) {
return Approx ( 0 ) ;
}
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
Approx operator ( ) ( double value ) {
Approx approx ( value ) ;
approx . epsilon ( m_epsilon ) ;
approx . scale ( m_scale ) ;
return approx ;
}
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
friend bool operator = = ( double lhs , Approx const & rhs ) {
// 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 ) ) ) ;
}
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
friend bool operator = = ( Approx const & lhs , double rhs ) {
return operator = = ( rhs , lhs ) ;
}
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
friend bool operator ! = ( double lhs , Approx const & rhs ) {
return ! operator = = ( lhs , rhs ) ;
}
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
friend bool operator ! = ( Approx const & lhs , double rhs ) {
return ! operator = = ( rhs , lhs ) ;
}
2014-12-28 16:11:01 +08:00
2017-01-12 05:23:02 +08:00
friend bool operator < = ( double lhs , Approx const & rhs )
{
return lhs < rhs . m_value | | lhs = = rhs ;
}
friend bool operator < = ( Approx const & lhs , double rhs )
{
return lhs . m_value < rhs | | lhs = = rhs ;
}
friend bool operator > = ( double lhs , Approx const & rhs )
{
return lhs > rhs . m_value | | lhs = = rhs ;
}
friend bool operator > = ( Approx const & lhs , double rhs )
{
return lhs . m_value > rhs | | lhs = = rhs ;
}
2015-12-20 22:42:01 +08:00
Approx & epsilon ( double newEpsilon ) {
m_epsilon = newEpsilon ;
return * this ;
}
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
Approx & scale ( double newScale ) {
m_scale = newScale ;
return * this ;
}
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
std : : string toString ( ) const {
std : : ostringstream oss ;
oss < < " Approx( " < < Catch : : toString ( m_value ) < < " ) " ;
return oss . str ( ) ;
}
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
private :
double m_epsilon ;
double m_scale ;
double m_value ;
} ;
}
template < >
inline std : : string toString < Detail : : Approx > ( Detail : : Approx const & value ) {
return value . toString ( ) ;
}
} // end namespace Catch
2014-12-28 16:11:01 +08: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>
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
struct TagAlias {
TagAlias ( std : : string _tag , SourceLineInfo _lineInfo ) : tag ( _tag ) , lineInfo ( _lineInfo ) { }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
std : : string tag ;
SourceLineInfo lineInfo ;
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
struct RegistrarForTagAliases {
RegistrarForTagAliases ( char const * alias , char const * tag , SourceLineInfo const & lineInfo ) ;
} ;
2014-12-28 16:11:01 +08:00
} // 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
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
// An optional type
template < typename T >
class Option {
public :
2015-12-20 22:42:01 +08:00
Option ( ) : nullableValue ( CATCH_NULL ) { }
2015-02-06 05:45:21 +08:00
Option ( T const & _value )
2014-12-28 16:11:01 +08:00
: nullableValue ( new ( storage ) T ( _value ) )
2015-02-06 05:45:21 +08:00
{ }
Option ( Option const & _other )
2015-12-20 22:42:01 +08:00
: nullableValue ( _other ? new ( storage ) T ( * _other ) : CATCH_NULL )
2015-02-06 05:45:21 +08:00
{ }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
~ Option ( ) {
2014-12-28 16:11:01 +08:00
reset ( ) ;
2015-02-06 05:45:21 +08:00
}
Option & operator = ( Option const & _other ) {
if ( & _other ! = this ) {
reset ( ) ;
if ( _other )
nullableValue = new ( storage ) T ( * _other ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
return * this ;
}
Option & operator = ( T const & _value ) {
reset ( ) ;
nullableValue = new ( storage ) T ( _value ) ;
return * this ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
void reset ( ) {
if ( nullableValue )
nullableValue - > ~ T ( ) ;
2015-12-20 22:42:01 +08:00
nullableValue = CATCH_NULL ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
T & operator * ( ) { return * nullableValue ; }
T const & operator * ( ) const { return * nullableValue ; }
T * operator - > ( ) { return nullableValue ; }
const T * operator - > ( ) const { return nullableValue ; }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
T valueOr ( T const & defaultValue ) const {
return nullableValue ? * nullableValue : defaultValue ;
}
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
bool some ( ) const { return nullableValue ! = CATCH_NULL ; }
bool none ( ) const { return nullableValue = = CATCH_NULL ; }
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
bool operator ! ( ) const { return nullableValue = = CATCH_NULL ; }
2015-02-06 05:45:21 +08:00
operator SafeBool : : type ( ) const {
return SafeBool : : makeSafe ( some ( ) ) ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
private :
T * nullableValue ;
char storage [ sizeof ( T ) ] ;
} ;
2014-12-28 16:11:01 +08:00
} // end namespace Catch
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
struct ITagAliasRegistry {
virtual ~ ITagAliasRegistry ( ) ;
virtual Option < TagAlias > find ( std : : string const & alias ) const = 0 ;
virtual std : : string expandAliases ( std : : string const & unexpandedTestSpec ) const = 0 ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
static ITagAliasRegistry const & get ( ) ;
} ;
2014-12-28 16:11:01 +08:00
} // end namespace Catch
// These files are included here so the single_include script doesn't put them
// in the conditionally compiled sections
// #included from: internal/catch_test_case_info.h
# define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED
# include <string>
# include <set>
# ifdef __clang__
2015-02-06 05:45:21 +08:00
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wpadded"
2014-12-28 16:11:01 +08:00
# endif
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
struct ITestCase ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
struct TestCaseInfo {
enum SpecialProperties {
None = 0 ,
IsHidden = 1 < < 1 ,
ShouldFail = 1 < < 2 ,
MayFail = 1 < < 3 ,
Throws = 1 < < 4
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08: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-12-20 22:42:01 +08:00
friend void setTags ( TestCaseInfo & testCaseInfo , std : : set < std : : string > const & tags ) ;
2015-02-06 05:45:21 +08:00
bool isHidden ( ) const ;
bool throws ( ) const ;
bool okToFail ( ) const ;
bool expectedToFail ( ) const ;
std : : string name ;
std : : string className ;
std : : string description ;
std : : set < std : : string > tags ;
std : : set < std : : string > lcaseTags ;
std : : string tagsAsString ;
SourceLineInfo lineInfo ;
SpecialProperties properties ;
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
class TestCase : public TestCaseInfo {
public :
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
TestCase ( ITestCase * testCase , TestCaseInfo const & info ) ;
TestCase ( TestCase const & other ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
TestCase withName ( std : : string const & _newName ) const ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
void invoke ( ) const ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
TestCaseInfo const & getTestCaseInfo ( ) const ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
void swap ( TestCase & other ) ;
bool operator = = ( TestCase const & other ) const ;
bool operator < ( TestCase const & other ) const ;
TestCase & operator = ( TestCase const & other ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
private :
Ptr < ITestCase > test ;
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
TestCase makeTestCase ( ITestCase * testCase ,
std : : string const & className ,
std : : string const & name ,
std : : string const & description ,
SourceLineInfo const & lineInfo ) ;
2014-12-28 16:11:01 +08:00
}
# ifdef __clang__
2015-02-06 05:45:21 +08:00
# pragma clang diagnostic pop
2014-12-28 16:11:01 +08:00
# endif
# ifdef __OBJC__
// #included from: internal/catch_objc.hpp
# define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED
# 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
///////////////////////////////////////////////////////////////////////////////
// This protocol is really only here for (self) documenting purposes, since
// all its methods are optional.
@ protocol OcFixture
@ optional
- ( void ) setUp ;
- ( void ) tearDown ;
@ end
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
class OcMethod : public SharedImpl < ITestCase > {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
public :
OcMethod ( Class cls , SEL sel ) : m_cls ( cls ) , m_sel ( sel ) { }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
virtual void invoke ( ) const {
id obj = [ [ m_cls alloc ] init ] ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
performOptionalSelector ( obj , @ selector ( setUp ) ) ;
performOptionalSelector ( obj , m_sel ) ;
performOptionalSelector ( obj , @ selector ( tearDown ) ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
arcSafeRelease ( obj ) ;
}
private :
virtual ~ OcMethod ( ) { }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
Class m_cls ;
SEL m_sel ;
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
namespace Detail {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
inline std : : string getAnnotation ( Class cls ,
std : : string const & annotationName ,
std : : string const & testCaseName ) {
NSString * selStr = [ [ NSString alloc ] initWithFormat : @ " Catch_%s_%s " , annotationName . c_str ( ) , testCaseName . c_str ( ) ] ;
SEL sel = NSSelectorFromString ( selStr ) ;
arcSafeRelease ( selStr ) ;
id value = performOptionalSelector ( cls , sel ) ;
if ( value )
return [ ( NSString * ) value UTF8String ] ;
return " " ;
}
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
inline size_t registerTestMethods ( ) {
size_t noTestMethods = 0 ;
2015-12-20 22:42:01 +08:00
int noClasses = objc_getClassList ( CATCH_NULL , 0 ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
Class * classes = ( CATCH_UNSAFE_UNRETAINED Class * ) malloc ( sizeof ( Class ) * noClasses ) ;
objc_getClassList ( classes , noClasses ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
for ( int c = 0 ; c < noClasses ; c + + ) {
Class cls = classes [ c ] ;
2014-12-28 16:11:01 +08:00
{
2015-02-06 05:45:21 +08:00
u_int count ;
Method * methods = class_copyMethodList ( cls , & count ) ;
for ( u_int m = 0 ; m < count ; m + + ) {
SEL selector = method_getName ( methods [ m ] ) ;
std : : string methodName = sel_getName ( selector ) ;
if ( startsWith ( methodName , " Catch_TestCase_ " ) ) {
std : : string testCaseName = methodName . substr ( 15 ) ;
std : : string name = Detail : : getAnnotation ( cls , " Name " , testCaseName ) ;
std : : string desc = Detail : : getAnnotation ( cls , " Description " , testCaseName ) ;
const char * className = class_getName ( cls ) ;
getMutableRegistryHub ( ) . registerTest ( makeTestCase ( new OcMethod ( cls , selector ) , className , name . c_str ( ) , desc . c_str ( ) , SourceLineInfo ( ) ) ) ;
noTestMethods + + ;
}
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
free ( methods ) ;
2014-12-28 16:11:01 +08:00
}
}
2015-02-06 05:45:21 +08:00
return noTestMethods ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
namespace Matchers {
namespace Impl {
namespace NSStringMatchers {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
template < typename MatcherT >
struct StringHolder : MatcherImpl < MatcherT , NSString * > {
StringHolder ( NSString * substr ) : m_substr ( [ substr copy ] ) { }
StringHolder ( StringHolder const & other ) : m_substr ( [ other . m_substr copy ] ) { }
StringHolder ( ) {
arcSafeRelease ( m_substr ) ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
NSString * m_substr ;
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
struct Equals : StringHolder < Equals > {
Equals ( NSString * substr ) : StringHolder ( substr ) { }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
virtual bool match ( ExpressionType const & str ) const {
return ( str ! = nil | | m_substr = = nil ) & &
[ str isEqualToString : m_substr ] ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
virtual std : : string toString ( ) const {
return " equals string: " + Catch : : toString ( m_substr ) ;
}
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
struct Contains : StringHolder < Contains > {
Contains ( NSString * substr ) : StringHolder ( substr ) { }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
virtual bool match ( ExpressionType const & str ) const {
return ( str ! = nil | | m_substr = = nil ) & &
[ str rangeOfString : m_substr ] . location ! = NSNotFound ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
virtual std : : string toString ( ) const {
return " contains string: " + Catch : : toString ( m_substr ) ;
}
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
struct StartsWith : StringHolder < StartsWith > {
StartsWith ( NSString * substr ) : StringHolder ( substr ) { }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
virtual bool match ( ExpressionType const & str ) const {
return ( str ! = nil | | m_substr = = nil ) & &
[ str rangeOfString : m_substr ] . location = = 0 ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
virtual std : : string toString ( ) const {
return " starts with: " + Catch : : toString ( m_substr ) ;
}
} ;
struct EndsWith : StringHolder < EndsWith > {
EndsWith ( NSString * substr ) : StringHolder ( substr ) { }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
virtual bool match ( ExpressionType const & str ) const {
return ( str ! = nil | | m_substr = = nil ) & &
[ str rangeOfString : m_substr ] . location = = [ str length ] - [ m_substr length ] ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
virtual std : : string toString ( ) const {
return " ends with: " + Catch : : toString ( m_substr ) ;
}
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
} // namespace NSStringMatchers
} // namespace Impl
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
inline Impl : : NSStringMatchers : : Equals
Equals ( NSString * substr ) { return Impl : : NSStringMatchers : : Equals ( substr ) ; }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
inline Impl : : NSStringMatchers : : Contains
Contains ( NSString * substr ) { return Impl : : NSStringMatchers : : Contains ( substr ) ; }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
inline Impl : : NSStringMatchers : : StartsWith
StartsWith ( NSString * substr ) { return Impl : : NSStringMatchers : : StartsWith ( substr ) ; }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
inline Impl : : NSStringMatchers : : EndsWith
EndsWith ( NSString * substr ) { return Impl : : NSStringMatchers : : EndsWith ( substr ) ; }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
} // namespace Matchers
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
using namespace Matchers ;
2014-12-28 16:11:01 +08:00
} // namespace Catch
///////////////////////////////////////////////////////////////////////////////
# define OC_TEST_CASE( name, desc )\
2015-02-06 05:45:21 +08:00
+ ( NSString * ) INTERNAL_CATCH_UNIQUE_NAME ( Catch_Name_test ) \
{ \
return @ name ; \
} \
+ ( NSString * ) INTERNAL_CATCH_UNIQUE_NAME ( Catch_Description_test ) \
{ \
return @ desc ; \
} \
- ( void ) INTERNAL_CATCH_UNIQUE_NAME ( Catch_TestCase_test )
2014-12-28 16:11:01 +08:00
# endif
2015-06-20 21:47:26 +08:00
# ifdef CATCH_IMPL
2014-12-28 16:11:01 +08:00
// #included from: internal/catch_impl.hpp
# define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED
// Collect all the implementation files together here
// These are the equivalent of what would usually be cpp files
# ifdef __clang__
2015-02-06 05:45:21 +08:00
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wweak-vtables"
2014-12-28 16:11:01 +08:00
# endif
2015-12-20 22:42:01 +08:00
// #included from: ../catch_session.hpp
2014-12-28 16:11:01 +08:00
# define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED
// #included from: internal/catch_commandline.hpp
# define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED
// #included from: catch_config.hpp
# define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED
// #included from: catch_test_spec_parser.hpp
# define TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED
# ifdef __clang__
2015-02-06 05:45:21 +08:00
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wpadded"
2014-12-28 16:11:01 +08:00
# endif
// #included from: catch_test_spec.hpp
# define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED
# ifdef __clang__
2015-02-06 05:45:21 +08:00
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wpadded"
2014-12-28 16:11:01 +08:00
# endif
2015-12-20 22:42:01 +08: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 :
WildcardPattern ( std : : string const & pattern , CaseSensitive : : Choice caseSensitivity )
: m_caseSensitivity ( caseSensitivity ) ,
m_wildcard ( NoWildcard ) ,
m_pattern ( adjustCase ( pattern ) )
{
if ( startsWith ( m_pattern , " * " ) ) {
m_pattern = m_pattern . substr ( 1 ) ;
m_wildcard = WildcardAtStart ;
}
if ( endsWith ( m_pattern , " * " ) ) {
m_pattern = m_pattern . substr ( 0 , m_pattern . size ( ) - 1 ) ;
m_wildcard = static_cast < WildcardPosition > ( m_wildcard | WildcardAtEnd ) ;
}
}
virtual ~ WildcardPattern ( ) ;
virtual bool matches ( std : : string const & str ) const {
switch ( m_wildcard ) {
case NoWildcard :
return m_pattern = = adjustCase ( str ) ;
case WildcardAtStart :
return endsWith ( adjustCase ( str ) , m_pattern ) ;
case WildcardAtEnd :
return startsWith ( adjustCase ( str ) , m_pattern ) ;
case WildcardAtBothEnds :
return contains ( adjustCase ( str ) , m_pattern ) ;
}
# ifdef __clang__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wunreachable-code"
# endif
throw std : : logic_error ( " Unknown enum " ) ;
# ifdef __clang__
# pragma clang diagnostic pop
# endif
}
private :
std : : string adjustCase ( std : : string const & str ) const {
return m_caseSensitivity = = CaseSensitive : : No ? toLower ( str ) : str ;
}
CaseSensitive : : Choice m_caseSensitivity ;
WildcardPosition m_wildcard ;
std : : string m_pattern ;
} ;
}
2014-12-28 16:11:01 +08:00
# include <string>
# include <vector>
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
class TestSpec {
struct Pattern : SharedImpl < > {
virtual ~ Pattern ( ) ;
virtual bool matches ( TestCaseInfo const & testCase ) const = 0 ;
2014-12-28 16:11:01 +08:00
} ;
2015-02-06 05:45:21 +08:00
class NamePattern : public Pattern {
public :
2015-12-20 22:42:01 +08:00
NamePattern ( std : : string const & name )
: m_wildcardPattern ( toLower ( name ) , CaseSensitive : : No )
{ }
2015-02-06 05:45:21 +08:00
virtual ~ NamePattern ( ) ;
virtual bool matches ( TestCaseInfo const & testCase ) const {
2015-12-20 22:42:01 +08:00
return m_wildcardPattern . matches ( toLower ( testCase . name ) ) ;
2015-02-06 05:45:21 +08:00
}
private :
2015-12-20 22:42:01 +08:00
WildcardPattern m_wildcardPattern ;
2015-02-06 05:45:21 +08:00
} ;
2015-12-20 22:42:01 +08:00
2015-02-06 05:45:21 +08:00
class TagPattern : public Pattern {
public :
TagPattern ( std : : string const & tag ) : m_tag ( toLower ( tag ) ) { }
virtual ~ TagPattern ( ) ;
virtual bool matches ( TestCaseInfo const & testCase ) const {
return testCase . lcaseTags . find ( m_tag ) ! = testCase . lcaseTags . end ( ) ;
}
private :
std : : string m_tag ;
} ;
2015-12-20 22:42:01 +08:00
2015-02-06 05:45:21 +08: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 ;
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
struct Filter {
std : : vector < Ptr < Pattern > > m_patterns ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
bool matches ( TestCaseInfo const & testCase ) const {
// All patterns in a filter must match for the filter to be a match
2016-11-17 02:15:54 +08:00
for ( std : : vector < Ptr < Pattern > > : : const_iterator it = m_patterns . begin ( ) , itEnd = m_patterns . end ( ) ; it ! = itEnd ; + + it ) {
2015-02-06 05:45:21 +08:00
if ( ! ( * it ) - > matches ( testCase ) )
return false ;
2016-11-17 02:15:54 +08:00
}
return true ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
} ;
public :
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 ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
private :
std : : vector < Filter > m_filters ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
friend class TestSpecParser ;
} ;
2014-12-28 16:11:01 +08:00
}
# ifdef __clang__
2015-02-06 05:45:21 +08:00
# pragma clang diagnostic pop
2014-12-28 16:11:01 +08:00
# endif
2015-02-06 05:45:21 +08:00
namespace Catch {
class TestSpecParser {
2017-01-12 05:23:02 +08:00
enum Mode { None , Name , QuotedName , Tag , EscapedName } ;
2015-02-06 05:45:21 +08:00
Mode m_mode ;
bool m_exclusion ;
std : : size_t m_start , m_pos ;
std : : string m_arg ;
2017-01-12 05:23:02 +08:00
std : : vector < std : : size_t > m_escapeChars ;
2015-02-06 05:45:21 +08:00
TestSpec : : Filter m_currentFilter ;
TestSpec m_testSpec ;
ITagAliasRegistry const * m_tagAliases ;
public :
TestSpecParser ( ITagAliasRegistry const & tagAliases ) : m_tagAliases ( & tagAliases ) { }
TestSpecParser & parse ( std : : string const & arg ) {
m_mode = None ;
m_exclusion = false ;
m_start = std : : string : : npos ;
m_arg = m_tagAliases - > expandAliases ( arg ) ;
2017-01-12 05:23:02 +08:00
m_escapeChars . clear ( ) ;
2015-02-06 05:45:21 +08:00
for ( m_pos = 0 ; m_pos < m_arg . size ( ) ; + + m_pos )
visitChar ( m_arg [ m_pos ] ) ;
if ( m_mode = = Name )
2014-12-28 16:11:01 +08:00
addPattern < TestSpec : : NamePattern > ( ) ;
2015-02-06 05:45:21 +08:00
return * this ;
}
TestSpec testSpec ( ) {
addFilter ( ) ;
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 ) ;
2017-01-12 05:23:02 +08:00
case ' \\ ' : return escape ( ) ;
2015-02-06 05:45:21 +08:00
default : startNewMode ( Name , m_pos ) ; break ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
}
if ( m_mode = = Name ) {
if ( c = = ' , ' ) {
2014-12-28 16:11:01 +08:00
addPattern < TestSpec : : NamePattern > ( ) ;
2015-02-06 05:45:21 +08:00
addFilter ( ) ;
}
else if ( c = = ' [ ' ) {
if ( subString ( ) = = " exclude: " )
m_exclusion = true ;
else
addPattern < TestSpec : : NamePattern > ( ) ;
startNewMode ( Tag , + + m_pos ) ;
2014-12-28 16:11:01 +08:00
}
2017-01-12 05:23:02 +08:00
else if ( c = = ' \\ ' )
escape ( ) ;
2014-12-28 16:11:01 +08:00
}
2017-01-12 05:23:02 +08:00
else if ( m_mode = = EscapedName )
m_mode = Name ;
2015-02-06 05:45:21 +08:00
else if ( m_mode = = QuotedName & & c = = ' " ' )
addPattern < TestSpec : : NamePattern > ( ) ;
else if ( m_mode = = Tag & & c = = ' ] ' )
addPattern < TestSpec : : TagPattern > ( ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
void startNewMode ( Mode mode , std : : size_t start ) {
m_mode = mode ;
m_start = start ;
2014-12-28 16:11:01 +08:00
}
2017-01-12 05:23:02 +08:00
void escape ( ) {
m_mode = EscapedName ;
m_escapeChars . push_back ( m_pos ) ;
}
2015-02-06 05:45:21 +08:00
std : : string subString ( ) const { return m_arg . substr ( m_start , m_pos - m_start ) ; }
template < typename T >
void addPattern ( ) {
std : : string token = subString ( ) ;
2017-01-12 05:23:02 +08:00
for ( size_t i = 0 ; i < m_escapeChars . size ( ) ; + + i )
token = token . substr ( 0 , m_escapeChars [ i ] ) + token . substr ( m_escapeChars [ i ] + 1 ) ;
m_escapeChars . clear ( ) ;
2015-02-06 05:45:21 +08:00
if ( startsWith ( token , " exclude: " ) ) {
m_exclusion = true ;
token = token . substr ( 8 ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
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 ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
void addFilter ( ) {
if ( ! m_currentFilter . m_patterns . empty ( ) ) {
m_testSpec . m_filters . push_back ( m_currentFilter ) ;
m_currentFilter = TestSpec : : Filter ( ) ;
}
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
} ;
inline TestSpec parseTestSpec ( std : : string const & arg ) {
return TestSpecParser ( ITagAliasRegistry : : get ( ) ) . parse ( arg ) . testSpec ( ) ;
2014-12-28 16:11:01 +08:00
}
} // namespace Catch
# ifdef __clang__
2015-02-06 05:45:21 +08:00
# pragma clang diagnostic pop
2014-12-28 16:11:01 +08:00
# endif
// #included from: catch_interfaces_config.h
# define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED
# include <iostream>
# include <string>
# include <vector>
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
struct Verbosity { enum Level {
2014-12-28 16:11:01 +08:00
NoOutput = 0 ,
Quiet ,
Normal
2015-02-06 05:45:21 +08:00
} ; } ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
struct WarnAbout { enum What {
2014-12-28 16:11:01 +08:00
Nothing = 0x00 ,
NoAssertions = 0x01
2015-02-06 05:45:21 +08:00
} ; } ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
struct ShowDurations { enum OrNot {
2014-12-28 16:11:01 +08:00
DefaultForReporter ,
Always ,
Never
2015-02-06 05:45:21 +08:00
} ; } ;
2015-06-20 21:47:26 +08:00
struct RunTests { enum InWhatOrder {
InDeclarationOrder ,
InLexicographicalOrder ,
InRandomOrder
} ; } ;
2016-06-20 00:25:43 +08:00
struct UseColour { enum YesOrNo {
Auto ,
Yes ,
No
} ; } ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
class TestSpec ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
struct IConfig : IShared {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
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 ;
2015-06-20 21:47:26 +08:00
virtual RunTests : : InWhatOrder runOrder ( ) const = 0 ;
virtual unsigned int rngSeed ( ) const = 0 ;
2016-06-20 00:25:43 +08:00
virtual UseColour : : YesOrNo useColour ( ) const = 0 ;
2015-02-06 05:45:21 +08:00
} ;
2014-12-28 16:11:01 +08:00
}
// #included from: catch_stream.h
# define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED
2015-12-20 22:42:01 +08:00
// #included from: catch_streambuf.h
# define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
# include <streambuf>
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
class StreamBufBase : public std : : streambuf {
2015-02-06 05:45:21 +08:00
public :
2015-12-20 22:42:01 +08:00
virtual ~ StreamBufBase ( ) CATCH_NOEXCEPT ;
} ;
}
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
# include <streambuf>
# include <ostream>
# include <fstream>
2016-12-22 16:37:15 +08:00
# include <memory>
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
namespace Catch {
2015-06-20 21:47:26 +08:00
std : : ostream & cout ( ) ;
std : : ostream & cerr ( ) ;
2015-12-20 22:42:01 +08:00
struct IStream {
virtual ~ IStream ( ) CATCH_NOEXCEPT ;
virtual std : : ostream & stream ( ) const = 0 ;
} ;
class FileStream : public IStream {
mutable std : : ofstream m_ofs ;
public :
FileStream ( std : : string const & filename ) ;
virtual ~ FileStream ( ) CATCH_NOEXCEPT ;
public : // IStream
virtual std : : ostream & stream ( ) const CATCH_OVERRIDE ;
} ;
class CoutStream : public IStream {
mutable std : : ostream m_os ;
public :
CoutStream ( ) ;
virtual ~ CoutStream ( ) CATCH_NOEXCEPT ;
public : // IStream
virtual std : : ostream & stream ( ) const CATCH_OVERRIDE ;
} ;
class DebugOutStream : public IStream {
2016-06-20 00:25:43 +08:00
CATCH_AUTO_PTR ( StreamBufBase ) m_streamBuf ;
2015-12-20 22:42:01 +08:00
mutable std : : ostream m_os ;
public :
DebugOutStream ( ) ;
virtual ~ DebugOutStream ( ) CATCH_NOEXCEPT ;
public : // IStream
virtual std : : ostream & stream ( ) const CATCH_OVERRIDE ;
} ;
2014-12-28 16:11:01 +08:00
}
# include <memory>
# include <vector>
# include <string>
# include <iostream>
2015-06-20 21:47:26 +08:00
# include <ctime>
2014-12-28 16:11:01 +08:00
# ifndef CATCH_CONFIG_CONSOLE_WIDTH
2015-02-06 05:45:21 +08:00
# define CATCH_CONFIG_CONSOLE_WIDTH 80
2014-12-28 16:11:01 +08:00
# endif
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
struct ConfigData {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
ConfigData ( )
2014-12-28 16:11:01 +08:00
: listTests ( false ) ,
listTags ( false ) ,
listReporters ( false ) ,
listTestNamesOnly ( false ) ,
showSuccessfulTests ( false ) ,
shouldDebugBreak ( false ) ,
noThrow ( false ) ,
showHelp ( false ) ,
showInvisibles ( false ) ,
2015-12-20 22:42:01 +08:00
filenamesAsTags ( false ) ,
2014-12-28 16:11:01 +08:00
abortAfter ( - 1 ) ,
2015-06-20 21:47:26 +08:00
rngSeed ( 0 ) ,
2014-12-28 16:11:01 +08:00
verbosity ( Verbosity : : Normal ) ,
warnings ( WarnAbout : : Nothing ) ,
2015-06-20 21:47:26 +08:00
showDurations ( ShowDurations : : DefaultForReporter ) ,
2016-06-20 00:25:43 +08:00
runOrder ( RunTests : : InDeclarationOrder ) ,
useColour ( UseColour : : Auto )
2015-02-06 05:45:21 +08:00
{ }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
bool listTests ;
bool listTags ;
bool listReporters ;
bool listTestNamesOnly ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
bool showSuccessfulTests ;
bool shouldDebugBreak ;
bool noThrow ;
bool showHelp ;
bool showInvisibles ;
2015-12-20 22:42:01 +08:00
bool filenamesAsTags ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
int abortAfter ;
2015-06-20 21:47:26 +08:00
unsigned int rngSeed ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
Verbosity : : Level verbosity ;
WarnAbout : : What warnings ;
ShowDurations : : OrNot showDurations ;
2015-06-20 21:47:26 +08:00
RunTests : : InWhatOrder runOrder ;
2016-06-20 00:25:43 +08:00
UseColour : : YesOrNo useColour ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
std : : string outputFilename ;
std : : string name ;
std : : string processName ;
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
std : : vector < std : : string > reporterNames ;
2015-02-06 05:45:21 +08:00
std : : vector < std : : string > testsOrTags ;
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
class Config : public SharedImpl < IConfig > {
private :
Config ( Config const & other ) ;
Config & operator = ( Config const & other ) ;
virtual void dummy ( ) ;
public :
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
Config ( )
{ }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
Config ( ConfigData const & data )
2014-12-28 16:11:01 +08:00
: m_data ( data ) ,
2015-12-20 22:42:01 +08:00
m_stream ( openStream ( ) )
2014-12-28 16:11:01 +08:00
{
2015-02-06 05:45:21 +08:00
if ( ! data . testsOrTags . empty ( ) ) {
TestSpecParser parser ( ITagAliasRegistry : : get ( ) ) ;
for ( std : : size_t i = 0 ; i < data . testsOrTags . size ( ) ; + + i )
parser . parse ( data . testsOrTags [ i ] ) ;
m_testSpec = parser . testSpec ( ) ;
2014-12-28 16:11:01 +08:00
}
}
2015-02-06 05:45:21 +08:00
virtual ~ Config ( ) {
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
std : : string const & getFilename ( ) const {
return m_data . outputFilename ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
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-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
std : : string getProcessName ( ) const { return m_data . processName ; }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
bool shouldDebugBreak ( ) const { return m_data . shouldDebugBreak ; }
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
std : : vector < std : : string > getReporterNames ( ) const { return m_data . reporterNames ; }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
int abortAfter ( ) const { return m_data . abortAfter ; }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
TestSpec const & testSpec ( ) const { return m_testSpec ; }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
bool showHelp ( ) const { return m_data . showHelp ; }
bool showInvisibles ( ) const { return m_data . showInvisibles ; }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
// IConfig interface
virtual bool allowThrows ( ) const { return ! m_data . noThrow ; }
2015-12-20 22:42:01 +08:00
virtual std : : ostream & stream ( ) const { return m_stream - > stream ( ) ; }
2015-02-06 05:45:21 +08:00
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 ; }
2015-06-20 21:47:26 +08:00
virtual RunTests : : InWhatOrder runOrder ( ) const { return m_data . runOrder ; }
virtual unsigned int rngSeed ( ) const { return m_data . rngSeed ; }
2016-06-20 00:25:43 +08:00
virtual UseColour : : YesOrNo useColour ( ) const { return m_data . useColour ; }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
private :
2015-12-20 22:42:01 +08:00
IStream const * openStream ( ) {
if ( m_data . outputFilename . empty ( ) )
return new CoutStream ( ) ;
else if ( m_data . outputFilename [ 0 ] = = ' % ' ) {
if ( m_data . outputFilename = = " %debug " )
return new DebugOutStream ( ) ;
else
throw std : : domain_error ( " Unrecognised stream: " + m_data . outputFilename ) ;
}
else
return new FileStream ( m_data . outputFilename ) ;
}
2015-02-06 05:45:21 +08:00
ConfigData m_data ;
2014-12-28 16:11:01 +08:00
2016-06-20 00:25:43 +08:00
CATCH_AUTO_PTR ( IStream const ) m_stream ;
2015-02-06 05:45:21 +08:00
TestSpec m_testSpec ;
} ;
2014-12-28 16:11:01 +08:00
} // end namespace Catch
// #included from: catch_clara.h
# define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED
// Use Catch's value for console width (store Clara's off to the side, if present)
# ifdef CLARA_CONFIG_CONSOLE_WIDTH
2015-02-06 05:45:21 +08:00
# define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH
# undef CLARA_CONFIG_CONSOLE_WIDTH
2014-12-28 16:11:01 +08:00
# endif
# define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH
// Declare Clara inside the Catch namespace
# define STITCH_CLARA_OPEN_NAMESPACE namespace Catch {
// #included from: ../external/clara.h
2016-06-20 00:25:43 +08:00
// Version 0.0.2.4
2016-02-15 04:36:43 +08:00
2014-12-28 16:11:01 +08:00
// Only use header guard if we are not using an outer namespace
# if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE)
# ifndef STITCH_CLARA_OPEN_NAMESPACE
2015-02-06 05:45:21 +08:00
# define TWOBLUECUBES_CLARA_H_INCLUDED
# define STITCH_CLARA_OPEN_NAMESPACE
# define STITCH_CLARA_CLOSE_NAMESPACE
2014-12-28 16:11:01 +08:00
# else
2015-02-06 05:45:21 +08:00
# define STITCH_CLARA_CLOSE_NAMESPACE }
2014-12-28 16:11:01 +08:00
# endif
# define STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE STITCH_CLARA_OPEN_NAMESPACE
// ----------- #included from tbc_text_format.h -----------
// Only use header guard if we are not using an outer namespace
# if !defined(TBC_TEXT_FORMAT_H_INCLUDED) || defined(STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE)
# ifndef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
2015-02-06 05:45:21 +08:00
# define TBC_TEXT_FORMAT_H_INCLUDED
2014-12-28 16:11:01 +08:00
# endif
# include <string>
# include <vector>
# include <sstream>
2016-02-15 04:36:43 +08:00
# include <algorithm>
2014-12-28 16:11:01 +08:00
// Use optional outer namespace
# ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
2015-02-06 05:45:21 +08:00
namespace STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE {
2014-12-28 16:11:01 +08:00
# endif
2015-02-06 05:45:21 +08:00
namespace Tbc {
2014-12-28 16:11:01 +08:00
# ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH
const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH ;
# else
const unsigned int consoleWidth = 80 ;
# endif
2015-02-06 05:45:21 +08:00
struct TextAttributes {
TextAttributes ( )
2014-12-28 16:11:01 +08:00
: initialIndent ( std : : string : : npos ) ,
indent ( 0 ) ,
2015-02-06 05:45:21 +08:00
width ( consoleWidth - 1 ) ,
2014-12-28 16:11:01 +08:00
tabChar ( ' \t ' )
2015-02-06 05:45:21 +08:00
{ }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08: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 ; }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08: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
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
class Text {
public :
Text ( std : : string const & _str , TextAttributes const & _attr = TextAttributes ( ) )
2014-12-28 16:11:01 +08:00
: attr ( _attr )
{
2015-02-06 05:45:21 +08:00
std : : string wrappableChars = " [({.,/| \\ - " ;
std : : size_t indent = _attr . initialIndent ! = std : : string : : npos
? _attr . initialIndent
: _attr . indent ;
std : : string remainder = _str ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
while ( ! remainder . empty ( ) ) {
if ( lines . size ( ) > = 1000 ) {
lines . push_back ( " ... message truncated due to excessive size " ) ;
return ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
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 ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
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 ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
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 ) ;
2014-12-28 16:11:01 +08:00
indent = _attr . indent ;
}
2015-02-06 05:45:21 +08:00
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 ;
2014-12-28 16:11:01 +08:00
}
}
}
2015-02-06 05:45:21 +08:00
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 ) ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
typedef std : : vector < std : : string > : : const_iterator const_iterator ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08: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 ] ; }
std : : string toString ( ) const {
std : : ostringstream oss ;
oss < < * this ;
return oss . str ( ) ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08: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 ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
return _stream ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
private :
std : : string str ;
TextAttributes attr ;
std : : vector < std : : string > lines ;
} ;
2014-12-28 16:11:01 +08:00
} // end namespace Tbc
# ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
} // end outer namespace
# endif
# endif // TBC_TEXT_FORMAT_H_INCLUDED
// ----------- end of #include from tbc_text_format.h -----------
2016-02-15 04:36:43 +08:00
// ........... back in clara.h
2014-12-28 16:11:01 +08:00
# undef STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE
2016-02-15 04:36:43 +08:00
// ----------- #included from clara_compilers.h -----------
# ifndef TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED
# define TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED
// Detect a number of compiler features - mostly C++11/14 conformance - by compiler
// The following features are defined:
//
// CLARA_CONFIG_CPP11_NULLPTR : is nullptr supported?
// CLARA_CONFIG_CPP11_NOEXCEPT : is noexcept supported?
// CLARA_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods
// CLARA_CONFIG_CPP11_OVERRIDE : is override supported?
// CLARA_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr)
// CLARA_CONFIG_CPP11_OR_GREATER : Is C++11 supported?
// CLARA_CONFIG_VARIADIC_MACROS : are variadic macros supported?
// In general each macro has a _NO_<feature name> form
// (e.g. CLARA_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 CLARA_CONFIG_NO_CPP11
# ifdef __clang__
# if __has_feature(cxx_nullptr)
# define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
# endif
# if __has_feature(cxx_noexcept)
# define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
# endif
# endif // __clang__
////////////////////////////////////////////////////////////////////////////////
// GCC
# ifdef __GNUC__
# if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__)
# define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
# endif
// - otherwise more recent versions define __cplusplus >= 201103L
// and will get picked up below
# endif // __GNUC__
////////////////////////////////////////////////////////////////////////////////
// Visual C++
# ifdef _MSC_VER
# if (_MSC_VER >= 1600)
# define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
# define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
# endif
# if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015))
# define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
# define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
# endif
# endif // _MSC_VER
////////////////////////////////////////////////////////////////////////////////
// C++ language feature support
// catch all support for C++11
# if defined(__cplusplus) && __cplusplus >= 201103L
# define CLARA_CPP11_OR_GREATER
# if !defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR)
# define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
# endif
# ifndef CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
# define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
# endif
# ifndef CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
# define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
# endif
# if !defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE)
# define CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE
# endif
# if !defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR)
# define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
# endif
# endif // __cplusplus >= 201103L
// Now set the actual defines based on the above + anything the user has configured
# if defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NO_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_NO_CPP11)
# define CLARA_CONFIG_CPP11_NULLPTR
# endif
# if defined(CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_NO_CPP11)
# define CLARA_CONFIG_CPP11_NOEXCEPT
# endif
# if defined(CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CLARA_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CLARA_CONFIG_CPP11_GENERATED_METHODS) && !defined(CLARA_CONFIG_NO_CPP11)
# define CLARA_CONFIG_CPP11_GENERATED_METHODS
# endif
# if defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_OVERRIDE) && !defined(CLARA_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_CPP11)
# define CLARA_CONFIG_CPP11_OVERRIDE
# endif
# if defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CLARA_CONFIG_NO_UNIQUE_PTR) && !defined(CLARA_CONFIG_CPP11_UNIQUE_PTR) && !defined(CLARA_CONFIG_NO_CPP11)
# define CLARA_CONFIG_CPP11_UNIQUE_PTR
# endif
// noexcept support:
# if defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_NOEXCEPT)
# define CLARA_NOEXCEPT noexcept
# define CLARA_NOEXCEPT_IS(x) noexcept(x)
# else
# define CLARA_NOEXCEPT throw()
# define CLARA_NOEXCEPT_IS(x)
# endif
// nullptr support
# ifdef CLARA_CONFIG_CPP11_NULLPTR
# define CLARA_NULL nullptr
# else
# define CLARA_NULL NULL
# endif
// override support
# ifdef CLARA_CONFIG_CPP11_OVERRIDE
# define CLARA_OVERRIDE override
# else
# define CLARA_OVERRIDE
# endif
// unique_ptr support
# ifdef CLARA_CONFIG_CPP11_UNIQUE_PTR
# define CLARA_AUTO_PTR( T ) std::unique_ptr<T>
# else
# define CLARA_AUTO_PTR( T ) std::auto_ptr<T>
# endif
# endif // TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED
// ----------- end of #include from clara_compilers.h -----------
// ........... back in clara.h
2014-12-28 16:11:01 +08:00
# include <map>
# include <stdexcept>
# include <memory>
2016-06-20 00:25:43 +08:00
# if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
# define CLARA_PLATFORM_WINDOWS
# endif
2014-12-28 16:11:01 +08:00
// Use optional outer namespace
# ifdef STITCH_CLARA_OPEN_NAMESPACE
2015-02-06 05:45:21 +08:00
STITCH_CLARA_OPEN_NAMESPACE
2014-12-28 16:11:01 +08:00
# endif
2015-02-06 05:45:21 +08:00
namespace Clara {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
struct UnpositionalTag { } ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
extern UnpositionalTag _ ;
2014-12-28 16:11:01 +08:00
# ifdef CLARA_CONFIG_MAIN
UnpositionalTag _ ;
# endif
2015-02-06 05:45:21 +08:00
namespace Detail {
2014-12-28 16:11:01 +08:00
# ifdef CLARA_CONSOLE_WIDTH
const unsigned int consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH ;
# else
const unsigned int consoleWidth = 80 ;
# endif
2015-02-06 05:45:21 +08:00
using namespace Tbc ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
inline bool startsWith ( std : : string const & str , std : : string const & prefix ) {
return str . size ( ) > = prefix . size ( ) & & str . substr ( 0 , prefix . size ( ) ) = = prefix ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08: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 ; } ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
template < typename T > struct IsBool { static const bool value = false ; } ;
template < > struct IsBool < bool > { static const bool value = true ; } ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
template < typename T >
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 ;
}
2016-12-22 16:37:15 +08:00
char toLowerCh ( char c ) {
return static_cast < char > ( : : tolower ( c ) ) ;
}
2015-02-06 05:45:21 +08:00
inline void convertInto ( std : : string const & _source , bool & _dest ) {
std : : string sourceLC = _source ;
2016-12-22 16:37:15 +08:00
std : : transform ( sourceLC . begin ( ) , sourceLC . end ( ) , sourceLC . begin ( ) , toLowerCh ) ;
2015-02-06 05:45:21 +08:00
if ( sourceLC = = " y " | | sourceLC = = " 1 " | | sourceLC = = " true " | | sourceLC = = " yes " | | sourceLC = = " on " )
_dest = true ;
else if ( sourceLC = = " n " | | sourceLC = = " 0 " | | sourceLC = = " false " | | sourceLC = = " no " | | sourceLC = = " off " )
_dest = false ;
else
throw std : : runtime_error ( " Expected a boolean value but did not recognise: \n ' " + _source + " ' " ) ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
template < typename ConfigT >
struct IArgFunction {
virtual ~ IArgFunction ( ) { }
2016-02-15 04:36:43 +08:00
# ifdef CLARA_CONFIG_CPP11_GENERATED_METHODS
2015-02-06 05:45:21 +08:00
IArgFunction ( ) = default ;
IArgFunction ( IArgFunction const & ) = default ;
2016-02-15 04:36:43 +08:00
# endif
2015-02-06 05:45:21 +08:00
virtual void set ( ConfigT & config , std : : string const & value ) const = 0 ;
virtual bool takesArg ( ) const = 0 ;
virtual IArgFunction * clone ( ) const = 0 ;
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
template < typename ConfigT >
class BoundArgFunction {
public :
2016-02-15 04:36:43 +08:00
BoundArgFunction ( ) : functionObj ( CLARA_NULL ) { }
2015-02-06 05:45:21 +08:00
BoundArgFunction ( IArgFunction < ConfigT > * _functionObj ) : functionObj ( _functionObj ) { }
2016-02-15 04:36:43 +08:00
BoundArgFunction ( BoundArgFunction const & other ) : functionObj ( other . functionObj ? other . functionObj - > clone ( ) : CLARA_NULL ) { }
2015-02-06 05:45:21 +08:00
BoundArgFunction & operator = ( BoundArgFunction const & other ) {
2016-02-15 04:36:43 +08:00
IArgFunction < ConfigT > * newFunctionObj = other . functionObj ? other . functionObj - > clone ( ) : CLARA_NULL ;
2015-02-06 05:45:21 +08:00
delete functionObj ;
functionObj = newFunctionObj ;
return * this ;
}
~ BoundArgFunction ( ) { delete functionObj ; }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
void set ( ConfigT & config , std : : string const & value ) const {
functionObj - > set ( config , value ) ;
}
bool takesArg ( ) const { return functionObj - > takesArg ( ) ; }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
bool isSet ( ) const {
2016-02-15 04:36:43 +08:00
return functionObj ! = CLARA_NULL ;
2015-02-06 05:45:21 +08:00
}
private :
IArgFunction < ConfigT > * functionObj ;
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
template < typename C >
struct NullBinder : IArgFunction < C > {
virtual void set ( C & , std : : string const & ) const { }
virtual bool takesArg ( ) const { return true ; }
virtual IArgFunction < C > * clone ( ) const { return new NullBinder ( * this ) ; }
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
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 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 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 bool takesArg ( ) const { return false ; }
virtual IArgFunction < C > * clone ( ) const { return new BoundNullaryMethod ( * this ) ; }
void ( C : : * member ) ( ) ;
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
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 bool takesArg ( ) const { return false ; }
virtual IArgFunction < C > * clone ( ) const { return new BoundUnaryFunction ( * this ) ; }
void ( * function ) ( C & ) ;
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
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 bool takesArg ( ) const { return ! IsBool < T > : : value ; }
virtual IArgFunction < C > * clone ( ) const { return new BoundBinaryFunction ( * this ) ; }
void ( * function ) ( C & , T ) ;
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
} // namespace Detail
2014-12-28 16:11:01 +08:00
2016-06-20 00:25:43 +08:00
inline std : : vector < std : : string > argsToVector ( int argc , char const * const * const argv ) {
std : : vector < std : : string > args ( static_cast < std : : size_t > ( argc ) ) ;
for ( std : : size_t i = 0 ; i < static_cast < std : : size_t > ( argc ) ; + + i )
args [ i ] = argv [ i ] ;
return args ;
}
class Parser {
enum Mode { None , MaybeShortOpt , SlashOpt , ShortOpt , LongOpt , Positional } ;
Mode mode ;
std : : size_t from ;
bool inQuotes ;
public :
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
struct Token {
enum Type { Positional , ShortOpt , LongOpt } ;
Token ( Type _type , std : : string const & _data ) : type ( _type ) , data ( _data ) { }
Type type ;
std : : string data ;
} ;
2014-12-28 16:11:01 +08:00
2016-06-20 00:25:43 +08:00
Parser ( ) : mode ( None ) , from ( 0 ) , inQuotes ( false ) { }
void parseIntoTokens ( std : : vector < std : : string > const & args , std : : vector < Token > & tokens ) {
2015-02-06 05:45:21 +08:00
const std : : string doubleDash = " -- " ;
2016-06-20 00:25:43 +08:00
for ( std : : size_t i = 1 ; i < args . size ( ) & & args [ i ] ! = doubleDash ; + + i )
parseIntoTokens ( args [ i ] , tokens ) ;
}
void parseIntoTokens ( std : : string const & arg , std : : vector < Token > & tokens ) {
for ( std : : size_t i = 0 ; i < = arg . size ( ) ; + + i ) {
char c = arg [ i ] ;
if ( c = = ' " ' )
inQuotes = ! inQuotes ;
mode = handleMode ( i , c , arg , tokens ) ;
}
}
Mode handleMode ( std : : size_t i , char c , std : : string const & arg , std : : vector < Token > & tokens ) {
switch ( mode ) {
case None : return handleNone ( i , c ) ;
case MaybeShortOpt : return handleMaybeShortOpt ( i , c ) ;
case ShortOpt :
case LongOpt :
case SlashOpt : return handleOpt ( i , c , arg , tokens ) ;
case Positional : return handlePositional ( i , c , arg , tokens ) ;
default : throw std : : logic_error ( " Unknown mode " ) ;
}
}
Mode handleNone ( std : : size_t i , char c ) {
if ( inQuotes ) {
from = i ;
return Positional ;
}
switch ( c ) {
case ' - ' : return MaybeShortOpt ;
# ifdef CLARA_PLATFORM_WINDOWS
case ' / ' : from = i + 1 ; return SlashOpt ;
# endif
default : from = i ; return Positional ;
}
}
Mode handleMaybeShortOpt ( std : : size_t i , char c ) {
switch ( c ) {
case ' - ' : from = i + 1 ; return LongOpt ;
default : from = i ; return ShortOpt ;
2014-12-28 16:11:01 +08:00
}
}
2016-06-20 00:25:43 +08:00
Mode handleOpt ( std : : size_t i , char c , std : : string const & arg , std : : vector < Token > & tokens ) {
if ( std : : string ( " := \0 " , 3 ) . find ( c ) = = std : : string : : npos )
return mode ;
std : : string optName = arg . substr ( from , i - from ) ;
if ( mode = = ShortOpt )
for ( std : : size_t j = 0 ; j < optName . size ( ) ; + + j )
tokens . push_back ( Token ( Token : : ShortOpt , optName . substr ( j , 1 ) ) ) ;
else if ( mode = = SlashOpt & & optName . size ( ) = = 1 )
tokens . push_back ( Token ( Token : : ShortOpt , optName ) ) ;
else
tokens . push_back ( Token ( Token : : LongOpt , optName ) ) ;
return None ;
}
Mode handlePositional ( std : : size_t i , char c , std : : string const & arg , std : : vector < Token > & tokens ) {
if ( inQuotes | | std : : string ( " \0 " , 1 ) . find ( c ) = = std : : string : : npos )
return mode ;
std : : string data = arg . substr ( from , i - from ) ;
tokens . push_back ( Token ( Token : : Positional , data ) ) ;
return None ;
}
2015-02-06 05:45:21 +08:00
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
template < typename ConfigT >
struct CommonArgProperties {
CommonArgProperties ( ) { }
CommonArgProperties ( Detail : : BoundArgFunction < ConfigT > const & _boundField ) : boundField ( _boundField ) { }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
Detail : : BoundArgFunction < ConfigT > boundField ;
std : : string description ;
std : : string detail ;
std : : string placeholder ; // Only value if boundField takes an arg
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
bool takesArg ( ) const {
return ! placeholder . empty ( ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
void validate ( ) const {
if ( ! boundField . isSet ( ) )
throw std : : logic_error ( " option not bound " ) ;
}
} ;
struct OptionArgProperties {
std : : vector < std : : string > shortNames ;
std : : string longName ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
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)
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
bool isFixedPositional ( ) const {
return position ! = - 1 ;
}
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
template < typename ConfigT >
class CommandLine {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
struct Arg : CommonArgProperties < ConfigT > , OptionArgProperties , PositionalArgProperties {
Arg ( ) { }
Arg ( Detail : : BoundArgFunction < ConfigT > const & _boundField ) : CommonArgProperties < ConfigT > ( _boundField ) { }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
using CommonArgProperties < ConfigT > : : placeholder ; // !TBD
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
std : : string dbgName ( ) const {
if ( ! longName . empty ( ) )
return " -- " + longName ;
if ( ! shortNames . empty ( ) )
return " - " + shortNames [ 0 ] ;
return " positional args " ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
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 ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
if ( ! longName . empty ( ) ) {
if ( ! first )
oss < < " , " ;
oss < < " -- " < < longName ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
if ( ! placeholder . empty ( ) )
oss < < " < " < < placeholder < < " > " ;
return oss . str ( ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
} ;
2014-12-28 16:11:01 +08:00
2016-02-15 04:36:43 +08:00
typedef CLARA_AUTO_PTR ( Arg ) ArgAutoPtr ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
friend void addOptName ( Arg & arg , std : : string const & optName )
2014-12-28 16:11:01 +08:00
{
2015-02-06 05:45:21 +08:00
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 + " ' " ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
friend void setPositionalArg ( Arg & arg , int position )
2014-12-28 16:11:01 +08:00
{
2015-02-06 05:45:21 +08:00
arg . position = position ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
class ArgBuilder {
public :
ArgBuilder ( Arg * arg ) : m_arg ( arg ) { }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
// Bind a non-boolean data member (requires placeholder string)
template < typename C , typename M >
void bind ( M C : : * field , std : : string const & placeholder ) {
m_arg - > boundField = new Detail : : BoundDataMember < C , M > ( field ) ;
m_arg - > placeholder = placeholder ;
}
// Bind a boolean data member (no placeholder required)
template < typename C >
void bind ( bool C : : * field ) {
m_arg - > boundField = new Detail : : BoundDataMember < C , bool > ( field ) ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
// Bind a method taking a single, non-boolean argument (requires a placeholder string)
template < typename C , typename M >
void bind ( void ( C : : * unaryMethod ) ( M ) , std : : string const & placeholder ) {
m_arg - > boundField = new Detail : : BoundUnaryMethod < C , M > ( unaryMethod ) ;
m_arg - > placeholder = placeholder ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
// Bind a method taking a single, boolean argument (no placeholder string required)
template < typename C >
void bind ( void ( C : : * unaryMethod ) ( bool ) ) {
m_arg - > boundField = new Detail : : BoundUnaryMethod < C , bool > ( unaryMethod ) ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
// Bind a method that takes no arguments (will be called if opt is present)
template < typename C >
void bind ( void ( C : : * nullaryMethod ) ( ) ) {
m_arg - > boundField = new Detail : : BoundNullaryMethod < C > ( nullaryMethod ) ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
// Bind a free function taking a single argument - the object to operate on (no placeholder string required)
template < typename C >
void bind ( void ( * unaryFunction ) ( C & ) ) {
m_arg - > boundField = new Detail : : BoundUnaryFunction < C > ( unaryFunction ) ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
// Bind a free function taking a single argument - the object to operate on (requires a placeholder string)
template < typename C , typename T >
void bind ( void ( * binaryFunction ) ( C & , T ) , std : : string const & placeholder ) {
m_arg - > boundField = new Detail : : BoundBinaryFunction < C , T > ( binaryFunction ) ;
m_arg - > placeholder = placeholder ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
ArgBuilder & describe ( std : : string const & description ) {
m_arg - > description = description ;
return * this ;
}
2016-02-15 04:36:43 +08:00
ArgBuilder & detail ( std : : string const & detail ) {
m_arg - > detail = detail ;
2015-02-06 05:45:21 +08:00
return * this ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
protected :
Arg * m_arg ;
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
class OptBuilder : public ArgBuilder {
public :
OptBuilder ( Arg * arg ) : ArgBuilder ( arg ) { }
OptBuilder ( OptBuilder & other ) : ArgBuilder ( other ) { }
OptBuilder & operator [ ] ( std : : string const & optName ) {
addOptName ( * ArgBuilder : : m_arg , optName ) ;
return * this ;
}
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
public :
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
CommandLine ( )
2014-12-28 16:11:01 +08:00
: m_boundProcessName ( new Detail : : NullBinder < ConfigT > ( ) ) ,
m_highestSpecifiedArgPosition ( 0 ) ,
m_throwOnUnrecognisedTokens ( false )
2015-02-06 05:45:21 +08:00
{ }
CommandLine ( CommandLine const & other )
2014-12-28 16:11:01 +08:00
: m_boundProcessName ( other . m_boundProcessName ) ,
m_options ( other . m_options ) ,
m_positionalArgs ( other . m_positionalArgs ) ,
m_highestSpecifiedArgPosition ( other . m_highestSpecifiedArgPosition ) ,
m_throwOnUnrecognisedTokens ( other . m_throwOnUnrecognisedTokens )
{
2015-02-06 05:45:21 +08:00
if ( other . m_floatingArg . get ( ) )
2015-06-20 21:47:26 +08:00
m_floatingArg . reset ( new Arg ( * other . m_floatingArg ) ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
CommandLine & setThrowOnUnrecognisedTokens ( bool shouldThrow = true ) {
m_throwOnUnrecognisedTokens = shouldThrow ;
return * this ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
OptBuilder operator [ ] ( std : : string const & optName ) {
m_options . push_back ( Arg ( ) ) ;
addOptName ( m_options . back ( ) , optName ) ;
OptBuilder builder ( & m_options . back ( ) ) ;
return builder ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
ArgBuilder operator [ ] ( int position ) {
m_positionalArgs . insert ( std : : make_pair ( position , Arg ( ) ) ) ;
if ( position > m_highestSpecifiedArgPosition )
m_highestSpecifiedArgPosition = position ;
setPositionalArg ( m_positionalArgs [ position ] , position ) ;
ArgBuilder builder ( & m_positionalArgs [ position ] ) ;
return builder ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
// Invoke this with the _ instance
ArgBuilder operator [ ] ( UnpositionalTag ) {
if ( m_floatingArg . get ( ) )
throw std : : logic_error ( " Only one unpositional argument can be added " ) ;
2015-06-20 21:47:26 +08:00
m_floatingArg . reset ( new Arg ( ) ) ;
2015-02-06 05:45:21 +08:00
ArgBuilder builder ( m_floatingArg . get ( ) ) ;
return builder ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08: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 ) ;
}
void optUsage ( std : : ostream & os , std : : size_t indent = 0 , std : : size_t width = Detail : : consoleWidth ) const {
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 ) {
2016-02-15 04:36:43 +08:00
Detail : : Text usage ( it - > commands ( ) , Detail : : TextAttributes ( )
2015-02-06 05:45:21 +08:00
. setWidth ( maxWidth + indent )
. setIndent ( indent ) ) ;
Detail : : Text desc ( it - > description , Detail : : TextAttributes ( )
. setWidth ( width - maxWidth - 3 ) ) ;
2016-02-15 04:36:43 +08:00
for ( std : : size_t i = 0 ; i < ( std : : max ) ( usage . size ( ) , desc . size ( ) ) ; + + i ) {
std : : string usageCol = i < usage . size ( ) ? usage [ i ] : " " ;
2015-02-06 05:45:21 +08:00
os < < usageCol ;
if ( i < desc . size ( ) & & ! desc [ i ] . empty ( ) )
os < < std : : string ( indent + 2 + maxWidth - usageCol . size ( ) , ' ' )
< < desc [ i ] ;
os < < " \n " ;
}
2014-12-28 16:11:01 +08:00
}
}
2015-02-06 05:45:21 +08:00
std : : string optUsage ( ) const {
std : : ostringstream oss ;
optUsage ( oss ) ;
return oss . str ( ) ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
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 ( ) )
os < < " < " < < it - > second . placeholder < < " > " ;
else if ( m_floatingArg . get ( ) )
os < < " < " < < m_floatingArg - > placeholder < < " > " ;
else
throw std : : logic_error ( " non consecutive positional arguments with no floating args " ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
// !TBD No indication of mandatory args
if ( m_floatingArg . get ( ) ) {
if ( m_highestSpecifiedArgPosition > 1 )
os < < " " ;
os < < " [< " < < m_floatingArg - > placeholder < < " > ...] " ;
2014-12-28 16:11:01 +08:00
}
}
2015-02-06 05:45:21 +08:00
std : : string argSynopsis ( ) const {
std : : ostringstream oss ;
argSynopsis ( oss ) ;
return oss . str ( ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
void usage ( std : : ostream & os , std : : string const & procName ) const {
validate ( ) ;
os < < " usage: \n " < < procName < < " " ;
argSynopsis ( os ) ;
if ( ! m_options . empty ( ) ) {
os < < " [options] \n \n where options are: \n " ;
optUsage ( os , 2 ) ;
}
os < < " \n " ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
std : : string usage ( std : : string const & procName ) const {
std : : ostringstream oss ;
usage ( oss , procName ) ;
return oss . str ( ) ;
2014-12-28 16:11:01 +08:00
}
2016-06-20 00:25:43 +08:00
ConfigT parse ( std : : vector < std : : string > const & args ) const {
2015-02-06 05:45:21 +08:00
ConfigT config ;
2016-06-20 00:25:43 +08:00
parseInto ( args , config ) ;
2015-02-06 05:45:21 +08:00
return config ;
}
2016-06-20 00:25:43 +08:00
std : : vector < Parser : : Token > parseInto ( std : : vector < std : : string > const & args , ConfigT & config ) const {
std : : string processName = args [ 0 ] ;
2015-02-06 05:45:21 +08:00
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 ;
2016-06-20 00:25:43 +08:00
parser . parseIntoTokens ( args , tokens ) ;
2015-02-06 05:45:21 +08:00
return populate ( tokens , config ) ;
}
std : : vector < Parser : : Token > populate ( std : : vector < Parser : : Token > const & tokens , ConfigT & config ) const {
validate ( ) ;
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 ;
std : : vector < std : : string > errors ;
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 )
errors . push_back ( " Expected argument to option: " + token . data ) ;
else
arg . boundField . set ( config , tokens [ + + i ] . data ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
else {
2016-06-20 00:25:43 +08:00
arg . boundField . set ( config , " true " ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
break ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
}
catch ( std : : exception & ex ) {
errors . push_back ( std : : string ( ex . what ( ) ) + " \n - while parsing: ( " + arg . commands ( ) + " ) " ) ;
2014-12-28 16:11:01 +08:00
}
}
2015-02-06 05:45:21 +08:00
if ( it = = itEnd ) {
if ( token . type = = Parser : : Token : : Positional | | ! m_throwOnUnrecognisedTokens )
unusedTokens . push_back ( token ) ;
2015-06-20 21:47:26 +08:00
else if ( errors . empty ( ) & & m_throwOnUnrecognisedTokens )
2015-02-06 05:45:21 +08:00
errors . push_back ( " unrecognised option: " + token . data ) ;
2014-12-28 16:11:01 +08:00
}
}
2015-02-06 05:45:21 +08:00
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 ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
throw std : : runtime_error ( oss . str ( ) ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08: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 + + ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
return unusedTokens ;
}
std : : vector < Parser : : Token > populateFloatingArgs ( std : : vector < Parser : : Token > const & tokens , ConfigT & config ) const {
if ( ! m_floatingArg . get ( ) )
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 )
m_floatingArg - > boundField . set ( config , token . data ) ;
else
unusedTokens . push_back ( token ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
return unusedTokens ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
void validate ( ) const
2014-12-28 16:11:01 +08:00
{
2015-02-06 05:45:21 +08:00
if ( m_options . empty ( ) & & m_positionalArgs . empty ( ) & & ! m_floatingArg . get ( ) )
throw std : : logic_error ( " No options or arguments specified " ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
for ( typename std : : vector < Arg > : : const_iterator it = m_options . begin ( ) ,
itEnd = m_options . end ( ) ;
it ! = itEnd ; + + it )
it - > validate ( ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
private :
Detail : : BoundArgFunction < ConfigT > m_boundProcessName ;
std : : vector < Arg > m_options ;
std : : map < int , Arg > m_positionalArgs ;
ArgAutoPtr m_floatingArg ;
int m_highestSpecifiedArgPosition ;
bool m_throwOnUnrecognisedTokens ;
} ;
2014-12-28 16:11:01 +08:00
} // end namespace Clara
STITCH_CLARA_CLOSE_NAMESPACE
# undef STITCH_CLARA_OPEN_NAMESPACE
# undef STITCH_CLARA_CLOSE_NAMESPACE
# endif // TWOBLUECUBES_CLARA_H_INCLUDED
# undef STITCH_CLARA_OPEN_NAMESPACE
// Restore Clara's value for console width, if present
# ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
2015-02-06 05:45:21 +08:00
# define CLARA_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
# undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
2014-12-28 16:11:01 +08:00
# endif
# include <fstream>
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
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 ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
inline void addTestOrTags ( ConfigData & config , std : : string const & _testSpec ) { config . testsOrTags . push_back ( _testSpec ) ; }
2015-12-20 22:42:01 +08:00
inline void addReporterName ( ConfigData & config , std : : string const & _reporterName ) { config . reporterNames . push_back ( _reporterName ) ; }
2015-02-06 05:45:21 +08:00
inline void addWarning ( ConfigData & config , std : : string const & _warning ) {
if ( _warning = = " NoAssertions " )
config . warnings = static_cast < WarnAbout : : What > ( config . warnings | WarnAbout : : NoAssertions ) ;
else
throw std : : runtime_error ( " Unrecognised warning: ' " + _warning + " ' " ) ;
2015-06-20 21:47:26 +08: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 " ) ;
}
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
inline void setVerbosity ( ConfigData & config , int level ) {
// !TBD: accept strings?
config . verbosity = static_cast < Verbosity : : Level > ( level ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
inline void setShowDurations ( ConfigData & config , bool _showDurations ) {
config . showDurations = _showDurations
? ShowDurations : : Always
: ShowDurations : : Never ;
2014-12-28 16:11:01 +08:00
}
2016-06-20 00:25:43 +08:00
inline void setUseColour ( ConfigData & config , std : : string const & value ) {
std : : string mode = toLower ( value ) ;
if ( mode = = " yes " )
config . useColour = UseColour : : Yes ;
else if ( mode = = " no " )
config . useColour = UseColour : : No ;
else if ( mode = = " auto " )
config . useColour = UseColour : : Auto ;
else
throw std : : runtime_error ( " colour mode must be one of: auto, yes or no " ) ;
}
inline void forceColour ( ConfigData & config ) {
config . useColour = UseColour : : Yes ;
}
2015-02-06 05:45:21 +08: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 ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
std : : string line ;
while ( std : : getline ( f , line ) ) {
line = trim ( line ) ;
2016-11-17 02:15:54 +08:00
if ( ! line . empty ( ) & & ! startsWith ( line , " # " ) ) {
if ( ! startsWith ( line , " \" " ) )
line = " \" " + line + " \" " ;
addTestOrTags ( config , line + " , " ) ;
}
2014-12-28 16:11:01 +08:00
}
}
2015-02-06 05:45:21 +08:00
inline Clara : : CommandLine < ConfigData > makeCommandLineParser ( ) {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
using namespace Clara ;
CommandLine < ConfigData > cli ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
cli . bindProcessName ( & ConfigData : : processName ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
cli [ " -? " ] [ " -h " ] [ " --help " ]
. describe ( " display usage information " )
. bind ( & ConfigData : : showHelp ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
cli [ " -l " ] [ " --list-tests " ]
. describe ( " list all/matching test cases " )
. bind ( & ConfigData : : listTests ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
cli [ " -t " ] [ " --list-tags " ]
. describe ( " list all/matching tags " )
. bind ( & ConfigData : : listTags ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
cli [ " -s " ] [ " --success " ]
. describe ( " include successful tests in output " )
. bind ( & ConfigData : : showSuccessfulTests ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
cli [ " -b " ] [ " --break " ]
. describe ( " break into debugger on failure " )
. bind ( & ConfigData : : shouldDebugBreak ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
cli [ " -e " ] [ " --nothrow " ]
. describe ( " skip exception tests " )
. bind ( & ConfigData : : noThrow ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
cli [ " -i " ] [ " --invisibles " ]
. describe ( " show invisibles (tabs, newlines) " )
. bind ( & ConfigData : : showInvisibles ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
cli [ " -o " ] [ " --out " ]
. describe ( " output filename " )
. bind ( & ConfigData : : outputFilename , " filename " ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
cli [ " -r " ] [ " --reporter " ]
// .placeholder( "name[:filename]" )
. describe ( " reporter to use (defaults to console) " )
2015-12-20 22:42:01 +08:00
. bind ( & addReporterName , " name " ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
cli [ " -n " ] [ " --name " ]
. describe ( " suite name " )
. bind ( & ConfigData : : name , " name " ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
cli [ " -a " ] [ " --abort " ]
. describe ( " abort at first failure " )
. bind ( & abortAfterFirst ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
cli [ " -x " ] [ " --abortx " ]
. describe ( " abort after x failures " )
. bind ( & abortAfterX , " no. failures " ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
cli [ " -w " ] [ " --warn " ]
. describe ( " enable warnings " )
. bind ( & addWarning , " warning name " ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
// - needs updating if reinstated
// cli.into( &setVerbosity )
// .describe( "level of verbosity (0=no output)" )
// .shortOpt( "v")
// .longOpt( "verbosity" )
// .placeholder( "level" );
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
cli [ _ ]
. describe ( " which test or tests to use " )
. bind ( & addTestOrTags , " test name, pattern or tags " ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
cli [ " -d " ] [ " --durations " ]
. describe ( " show test durations " )
2016-06-20 00:25:43 +08:00
. bind ( & setShowDurations , " yes|no " ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
cli [ " -f " ] [ " --input-file " ]
. describe ( " load test names to run from a file " )
. bind ( & loadTestNamesFromFile , " filename " ) ;
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
cli [ " -# " ] [ " --filenames-as-tags " ]
. describe ( " adds a tag for the filename " )
. bind ( & ConfigData : : filenamesAsTags ) ;
2015-02-06 05:45:21 +08:00
// Less common commands which don't have a short form
cli [ " --list-test-names-only " ]
. describe ( " list all/matching test cases names only " )
. bind ( & ConfigData : : listTestNamesOnly ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
cli [ " --list-reporters " ]
. describe ( " list all reporters " )
. bind ( & ConfigData : : listReporters ) ;
2014-12-28 16:11:01 +08:00
2015-06-20 21:47:26 +08: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 " ) ;
cli [ " --force-colour " ]
2016-06-20 00:25:43 +08:00
. describe ( " force colourised output (deprecated) " )
. bind ( & forceColour ) ;
cli [ " --use-colour " ]
. describe ( " should output be colourised " )
. bind ( & setUseColour , " yes|no " ) ;
2015-06-20 21:47:26 +08:00
2015-02-06 05:45:21 +08:00
return cli ;
}
2014-12-28 16:11:01 +08:00
} // end namespace Catch
// #included from: internal/catch_list.hpp
# define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED
// #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
// #included from: ../external/tbc_text_format.h
// Only use header guard if we are not using an outer namespace
# ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
2015-02-06 05:45:21 +08:00
# 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
2014-12-28 16:11:01 +08:00
# 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
2015-02-06 05:45:21 +08:00
namespace CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE {
2014-12-28 16:11:01 +08:00
# endif
2015-02-06 05:45:21 +08:00
namespace Tbc {
2014-12-28 16:11:01 +08:00
# ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH
const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH ;
# else
const unsigned int consoleWidth = 80 ;
# endif
2015-02-06 05:45:21 +08:00
struct TextAttributes {
TextAttributes ( )
2014-12-28 16:11:01 +08:00
: initialIndent ( std : : string : : npos ) ,
indent ( 0 ) ,
2015-02-06 05:45:21 +08:00
width ( consoleWidth - 1 ) ,
2014-12-28 16:11:01 +08:00
tabChar ( ' \t ' )
2015-02-06 05:45:21 +08:00
{ }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08: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 ; }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08: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
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
class Text {
public :
Text ( std : : string const & _str , TextAttributes const & _attr = TextAttributes ( ) )
2014-12-28 16:11:01 +08:00
: attr ( _attr )
{
2015-02-06 05:45:21 +08:00
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 ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
if ( width = = remainder . size ( ) ) {
spliceLine ( indent , remainder , width ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
else if ( remainder [ width ] = = ' \n ' ) {
spliceLine ( indent , remainder , width ) ;
if ( width < = 1 | | remainder . size ( ) ! = 1 )
2014-12-28 16:11:01 +08:00
remainder = remainder . substr ( 1 ) ;
2015-02-06 05:45:21 +08:00
indent = _attr . indent ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
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 ;
2014-12-28 16:11:01 +08:00
}
}
}
2015-02-06 05:45:21 +08:00
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 ) ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
typedef std : : vector < std : : string > : : const_iterator const_iterator ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08: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 ] ; }
std : : string toString ( ) const {
std : : ostringstream oss ;
oss < < * this ;
return oss . str ( ) ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08: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 ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
return _stream ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
private :
std : : string str ;
TextAttributes attr ;
std : : vector < std : : string > lines ;
} ;
2014-12-28 16:11:01 +08:00
} // 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
2015-02-06 05:45:21 +08:00
namespace Catch {
using Tbc : : Text ;
using Tbc : : TextAttributes ;
2014-12-28 16:11:01 +08:00
}
// #included from: catch_console_colour.hpp
# define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
struct Colour {
enum Code {
None = 0 ,
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
White ,
Red ,
Green ,
Blue ,
Cyan ,
Yellow ,
Grey ,
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
Bright = 0x10 ,
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
BrightRed = Bright | Red ,
BrightGreen = Bright | Green ,
LightGrey = Bright | Grey ,
BrightWhite = Bright | White ,
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
// By intention
FileName = LightGrey ,
Warning = Yellow ,
ResultError = BrightRed ,
ResultSuccess = BrightGreen ,
ResultExpectedFailure = Warning ,
Error = BrightRed ,
Success = Green ,
OriginalExpression = Cyan ,
ReconstructedExpression = Yellow ,
SecondaryText = LightGrey ,
Headers = White
} ;
// Use constructed object for RAII guard
Colour ( Code _colourCode ) ;
Colour ( Colour const & other ) ;
~ Colour ( ) ;
// Use static method for one-shot changes
static void use ( Code _colourCode ) ;
private :
bool m_moved ;
} ;
inline std : : ostream & operator < < ( std : : ostream & os , Colour const & ) { return os ; }
2014-12-28 16:11:01 +08:00
} // end namespace Catch
// #included from: catch_interfaces_reporter.h
# define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED
# include <string>
# include <ostream>
# include <map>
# include <assert.h>
namespace Catch
{
2015-02-06 05:45:21 +08:00
struct ReporterConfig {
2015-12-20 22:42:01 +08:00
explicit ReporterConfig ( Ptr < IConfig const > const & _fullConfig )
2014-12-28 16:11:01 +08:00
: m_stream ( & _fullConfig - > stream ( ) ) , m_fullConfig ( _fullConfig ) { }
2015-12-20 22:42:01 +08:00
ReporterConfig ( Ptr < IConfig const > const & _fullConfig , std : : ostream & _stream )
2014-12-28 16:11:01 +08:00
: m_stream ( & _stream ) , m_fullConfig ( _fullConfig ) { }
2015-02-06 05:45:21 +08:00
std : : ostream & stream ( ) const { return * m_stream ; }
2015-12-20 22:42:01 +08:00
Ptr < IConfig const > fullConfig ( ) const { return m_fullConfig ; }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
private :
std : : ostream * m_stream ;
2015-12-20 22:42:01 +08:00
Ptr < IConfig const > m_fullConfig ;
2015-02-06 05:45:21 +08:00
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
struct ReporterPreferences {
ReporterPreferences ( )
2014-12-28 16:11:01 +08:00
: shouldRedirectStdOut ( false )
2015-02-06 05:45:21 +08:00
{ }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
bool shouldRedirectStdOut ;
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
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 ;
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
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 )
2014-12-28 16:11:01 +08:00
: name ( _name ) ,
groupIndex ( _groupIndex ) ,
groupsCounts ( _groupsCount )
2015-02-06 05:45:21 +08:00
{ }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
std : : string name ;
std : : size_t groupIndex ;
std : : size_t groupsCounts ;
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
struct AssertionStats {
AssertionStats ( AssertionResult const & _assertionResult ,
std : : vector < MessageInfo > const & _infoMessages ,
Totals const & _totals )
2014-12-28 16:11:01 +08:00
: assertionResult ( _assertionResult ) ,
infoMessages ( _infoMessages ) ,
totals ( _totals )
{
2015-02-06 05:45:21 +08:00
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 ( ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
infoMessages . push_back ( builder . m_info ) ;
}
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
virtual ~ AssertionStats ( ) ;
2014-12-28 16:11:01 +08:00
2015-06-20 21:47:26 +08:00
# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
2015-02-06 05:45:21 +08:00
AssertionStats ( AssertionStats const & ) = default ;
AssertionStats ( AssertionStats & & ) = default ;
AssertionStats & operator = ( AssertionStats const & ) = default ;
AssertionStats & operator = ( AssertionStats & & ) = default ;
2014-12-28 16:11:01 +08:00
# endif
2015-02-06 05:45:21 +08:00
AssertionResult assertionResult ;
std : : vector < MessageInfo > infoMessages ;
Totals totals ;
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
struct SectionStats {
SectionStats ( SectionInfo const & _sectionInfo ,
Counts const & _assertions ,
double _durationInSeconds ,
bool _missingAssertions )
2014-12-28 16:11:01 +08:00
: sectionInfo ( _sectionInfo ) ,
assertions ( _assertions ) ,
durationInSeconds ( _durationInSeconds ) ,
missingAssertions ( _missingAssertions )
2015-02-06 05:45:21 +08:00
{ }
virtual ~ SectionStats ( ) ;
2015-06-20 21:47:26 +08:00
# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
2015-02-06 05:45:21 +08:00
SectionStats ( SectionStats const & ) = default ;
SectionStats ( SectionStats & & ) = default ;
SectionStats & operator = ( SectionStats const & ) = default ;
SectionStats & operator = ( SectionStats & & ) = default ;
2014-12-28 16:11:01 +08:00
# endif
2015-02-06 05:45:21 +08:00
SectionInfo sectionInfo ;
Counts assertions ;
double durationInSeconds ;
bool missingAssertions ;
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
struct TestCaseStats {
TestCaseStats ( TestCaseInfo const & _testInfo ,
Totals const & _totals ,
std : : string const & _stdOut ,
std : : string const & _stdErr ,
bool _aborting )
2014-12-28 16:11:01 +08:00
: testInfo ( _testInfo ) ,
2015-02-06 05:45:21 +08:00
totals ( _totals ) ,
stdOut ( _stdOut ) ,
stdErr ( _stdErr ) ,
aborting ( _aborting )
{ }
virtual ~ TestCaseStats ( ) ;
2014-12-28 16:11:01 +08:00
2015-06-20 21:47:26 +08:00
# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
2015-02-06 05:45:21 +08:00
TestCaseStats ( TestCaseStats const & ) = default ;
TestCaseStats ( TestCaseStats & & ) = default ;
TestCaseStats & operator = ( TestCaseStats const & ) = default ;
TestCaseStats & operator = ( TestCaseStats & & ) = default ;
2014-12-28 16:11:01 +08:00
# endif
2015-02-06 05:45:21 +08:00
TestCaseInfo testInfo ;
Totals totals ;
std : : string stdOut ;
std : : string stdErr ;
bool aborting ;
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
struct TestGroupStats {
TestGroupStats ( GroupInfo const & _groupInfo ,
Totals const & _totals ,
bool _aborting )
2014-12-28 16:11:01 +08:00
: groupInfo ( _groupInfo ) ,
totals ( _totals ) ,
aborting ( _aborting )
2015-02-06 05:45:21 +08:00
{ }
TestGroupStats ( GroupInfo const & _groupInfo )
2014-12-28 16:11:01 +08:00
: groupInfo ( _groupInfo ) ,
aborting ( false )
2015-02-06 05:45:21 +08:00
{ }
virtual ~ TestGroupStats ( ) ;
2014-12-28 16:11:01 +08:00
2015-06-20 21:47:26 +08:00
# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
2015-02-06 05:45:21 +08:00
TestGroupStats ( TestGroupStats const & ) = default ;
TestGroupStats ( TestGroupStats & & ) = default ;
TestGroupStats & operator = ( TestGroupStats const & ) = default ;
TestGroupStats & operator = ( TestGroupStats & & ) = default ;
2014-12-28 16:11:01 +08:00
# endif
2015-02-06 05:45:21 +08:00
GroupInfo groupInfo ;
Totals totals ;
bool aborting ;
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
struct TestRunStats {
TestRunStats ( TestRunInfo const & _runInfo ,
Totals const & _totals ,
bool _aborting )
2014-12-28 16:11:01 +08:00
: runInfo ( _runInfo ) ,
totals ( _totals ) ,
aborting ( _aborting )
2015-02-06 05:45:21 +08:00
{ }
virtual ~ TestRunStats ( ) ;
2014-12-28 16:11:01 +08:00
2015-06-20 21:47:26 +08:00
# ifndef CATCH_CONFIG_CPP11_GENERATED_METHODS
2015-02-06 05:45:21 +08:00
TestRunStats ( TestRunStats const & _other )
2014-12-28 16:11:01 +08:00
: runInfo ( _other . runInfo ) ,
totals ( _other . totals ) ,
aborting ( _other . aborting )
2015-02-06 05:45:21 +08:00
{ }
2014-12-28 16:11:01 +08:00
# else
2015-02-06 05:45:21 +08:00
TestRunStats ( TestRunStats const & ) = default ;
TestRunStats ( TestRunStats & & ) = default ;
TestRunStats & operator = ( TestRunStats const & ) = default ;
TestRunStats & operator = ( TestRunStats & & ) = default ;
2014-12-28 16:11:01 +08:00
# endif
2015-02-06 05:45:21 +08:00
TestRunInfo runInfo ;
Totals totals ;
bool aborting ;
} ;
2014-12-28 16:11:01 +08:00
2016-06-20 00:25:43 +08:00
class MultipleReporters ;
2015-02-06 05:45:21 +08:00
struct IStreamingReporter : IShared {
virtual ~ IStreamingReporter ( ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
// Implementing class must also provide the following static method:
// static std::string getDescription();
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
virtual ReporterPreferences getPreferences ( ) const = 0 ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
virtual void noMatchingTestCases ( std : : string const & spec ) = 0 ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
virtual void testRunStarting ( TestRunInfo const & testRunInfo ) = 0 ;
virtual void testGroupStarting ( GroupInfo const & groupInfo ) = 0 ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
virtual void testCaseStarting ( TestCaseInfo const & testInfo ) = 0 ;
virtual void sectionStarting ( SectionInfo const & sectionInfo ) = 0 ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
virtual void assertionStarting ( AssertionInfo const & assertionInfo ) = 0 ;
2014-12-28 16:11:01 +08:00
2015-06-20 21:47:26 +08:00
// The return value indicates if the messages buffer should be cleared:
2015-02-06 05:45:21 +08:00
virtual bool assertionEnded ( AssertionStats const & assertionStats ) = 0 ;
2015-12-20 22:42:01 +08:00
2015-02-06 05:45:21 +08: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 ;
2015-06-20 21:47:26 +08:00
virtual void skipTest ( TestCaseInfo const & testInfo ) = 0 ;
2016-06-20 00:25:43 +08:00
virtual MultipleReporters * tryAsMulti ( ) { return CATCH_NULL ; }
2015-02-06 05:45:21 +08:00
} ;
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
struct IReporterFactory : IShared {
2015-02-06 05:45:21 +08:00
virtual ~ IReporterFactory ( ) ;
virtual IStreamingReporter * create ( ReporterConfig const & config ) const = 0 ;
virtual std : : string getDescription ( ) const = 0 ;
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
struct IReporterRegistry {
2015-12-20 22:42:01 +08:00
typedef std : : map < std : : string , Ptr < IReporterFactory > > FactoryMap ;
typedef std : : vector < Ptr < IReporterFactory > > Listeners ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
virtual ~ IReporterRegistry ( ) ;
2015-12-20 22:42:01 +08:00
virtual IStreamingReporter * create ( std : : string const & name , Ptr < IConfig const > const & config ) const = 0 ;
2015-02-06 05:45:21 +08:00
virtual FactoryMap const & getFactories ( ) const = 0 ;
2015-12-20 22:42:01 +08:00
virtual Listeners const & getListeners ( ) const = 0 ;
2015-02-06 05:45:21 +08:00
} ;
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
Ptr < IStreamingReporter > addReporter ( Ptr < IStreamingReporter > const & existingReporter , Ptr < IStreamingReporter > const & additionalReporter ) ;
2014-12-28 16:11:01 +08:00
}
# include <limits>
# include <algorithm>
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
inline std : : size_t listTests ( Config const & config ) {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
TestSpec testSpec = config . testSpec ( ) ;
if ( config . testSpec ( ) . hasFilters ( ) )
2015-06-20 21:47:26 +08:00
Catch : : cout ( ) < < " Matching test cases: \n " ;
2015-02-06 05:45:21 +08:00
else {
2015-06-20 21:47:26 +08:00
Catch : : cout ( ) < < " All available test cases: \n " ;
2015-02-06 05:45:21 +08:00
testSpec = TestSpecParser ( ITagAliasRegistry : : get ( ) ) . parse ( " * " ) . testSpec ( ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
std : : size_t matchedTests = 0 ;
TextAttributes nameAttr , tagsAttr ;
nameAttr . setInitialIndent ( 2 ) . setIndent ( 4 ) ;
tagsAttr . setIndent ( 6 ) ;
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
std : : vector < TestCase > matchedTestCases = filterTests ( getAllTestCasesSorted ( config ) , testSpec , config ) ;
2015-02-06 05:45:21 +08:00
for ( std : : vector < TestCase > : : const_iterator it = matchedTestCases . begin ( ) , itEnd = matchedTestCases . end ( ) ;
2014-12-28 16:11:01 +08:00
it ! = itEnd ;
2015-02-06 05:45:21 +08:00
+ + it ) {
matchedTests + + ;
TestCaseInfo const & testCaseInfo = it - > getTestCaseInfo ( ) ;
Colour : : Code colour = testCaseInfo . isHidden ( )
? Colour : : SecondaryText
: Colour : : None ;
Colour colourGuard ( colour ) ;
2014-12-28 16:11:01 +08:00
2015-06-20 21:47:26 +08:00
Catch : : cout ( ) < < Text ( testCaseInfo . name , nameAttr ) < < std : : endl ;
2015-02-06 05:45:21 +08:00
if ( ! testCaseInfo . tags . empty ( ) )
2015-06-20 21:47:26 +08:00
Catch : : cout ( ) < < Text ( testCaseInfo . tagsAsString , tagsAttr ) < < std : : endl ;
2015-02-06 05:45:21 +08:00
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
if ( ! config . testSpec ( ) . hasFilters ( ) )
2015-06-20 21:47:26 +08:00
Catch : : cout ( ) < < pluralise ( matchedTests , " test case " ) < < " \n " < < std : : endl ;
2015-02-06 05:45:21 +08:00
else
2015-06-20 21:47:26 +08:00
Catch : : cout ( ) < < pluralise ( matchedTests , " matching test case " ) < < " \n " < < std : : endl ;
2015-02-06 05:45:21 +08:00
return matchedTests ;
}
inline std : : size_t listTestsNamesOnly ( Config const & config ) {
TestSpec testSpec = config . testSpec ( ) ;
if ( ! config . testSpec ( ) . hasFilters ( ) )
testSpec = TestSpecParser ( ITagAliasRegistry : : get ( ) ) . parse ( " * " ) . testSpec ( ) ;
std : : size_t matchedTests = 0 ;
2015-12-20 22:42:01 +08:00
std : : vector < TestCase > matchedTestCases = filterTests ( getAllTestCasesSorted ( config ) , testSpec , config ) ;
2015-02-06 05:45:21 +08:00
for ( std : : vector < TestCase > : : const_iterator it = matchedTestCases . begin ( ) , itEnd = matchedTestCases . end ( ) ;
it ! = itEnd ;
+ + it ) {
matchedTests + + ;
TestCaseInfo const & testCaseInfo = it - > getTestCaseInfo ( ) ;
2016-11-17 02:15:54 +08:00
if ( startsWith ( testCaseInfo . name , " # " ) )
Catch : : cout ( ) < < " \" " < < testCaseInfo . name < < " \" " < < std : : endl ;
else
Catch : : cout ( ) < < testCaseInfo . name < < std : : endl ;
2015-02-06 05:45:21 +08:00
}
return matchedTests ;
}
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 ;
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
inline std : : size_t listTags ( Config const & config ) {
TestSpec testSpec = config . testSpec ( ) ;
if ( config . testSpec ( ) . hasFilters ( ) )
2015-06-20 21:47:26 +08:00
Catch : : cout ( ) < < " Tags for matching test cases: \n " ;
2015-02-06 05:45:21 +08:00
else {
2015-06-20 21:47:26 +08:00
Catch : : cout ( ) < < " All available tags: \n " ;
2015-02-06 05:45:21 +08:00
testSpec = TestSpecParser ( ITagAliasRegistry : : get ( ) ) . parse ( " * " ) . testSpec ( ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
std : : map < std : : string , TagInfo > tagCounts ;
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
std : : vector < TestCase > matchedTestCases = filterTests ( getAllTestCasesSorted ( config ) , testSpec , config ) ;
2015-02-06 05:45:21 +08:00
for ( std : : vector < TestCase > : : const_iterator it = matchedTestCases . begin ( ) , itEnd = matchedTestCases . end ( ) ;
it ! = itEnd ;
+ + it ) {
for ( std : : set < std : : string > : : const_iterator tagIt = it - > getTestCaseInfo ( ) . tags . begin ( ) ,
tagItEnd = it - > getTestCaseInfo ( ) . tags . end ( ) ;
tagIt ! = tagItEnd ;
+ + tagIt ) {
std : : string tagName = * tagIt ;
std : : string lcaseTagName = toLower ( tagName ) ;
std : : map < std : : string , TagInfo > : : iterator countIt = tagCounts . find ( lcaseTagName ) ;
if ( countIt = = tagCounts . end ( ) )
countIt = tagCounts . insert ( std : : make_pair ( lcaseTagName , TagInfo ( ) ) ) . first ;
countIt - > second . add ( tagName ) ;
}
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
for ( std : : map < std : : string , TagInfo > : : const_iterator countIt = tagCounts . begin ( ) ,
countItEnd = tagCounts . end ( ) ;
countIt ! = countItEnd ;
+ + countIt ) {
std : : ostringstream oss ;
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 ) ) ;
2015-06-20 21:47:26 +08:00
Catch : : cout ( ) < < oss . str ( ) < < wrapper < < " \n " ;
2015-02-06 05:45:21 +08:00
}
2015-06-20 21:47:26 +08:00
Catch : : cout ( ) < < pluralise ( tagCounts . size ( ) , " tag " ) < < " \n " < < std : : endl ;
2015-02-06 05:45:21 +08:00
return tagCounts . size ( ) ;
}
inline std : : size_t listReporters ( Config const & /*config*/ ) {
2015-06-20 21:47:26 +08:00
Catch : : cout ( ) < < " Available reporters: \n " ;
2015-02-06 05:45:21 +08:00
IReporterRegistry : : FactoryMap const & factories = getRegistryHub ( ) . getReporterRegistry ( ) . getFactories ( ) ;
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 ) ) ;
2015-06-20 21:47:26 +08:00
Catch : : cout ( ) < < " "
2015-02-06 05:45:21 +08:00
< < it - > first
< < " : "
< < std : : string ( maxNameLen - it - > first . size ( ) + 2 , ' ' )
< < wrapper < < " \n " ;
}
2015-06-20 21:47:26 +08:00
Catch : : cout ( ) < < std : : endl ;
2015-02-06 05:45:21 +08:00
return factories . size ( ) ;
}
inline Option < std : : size_t > list ( Config const & config ) {
Option < std : : size_t > listedCount ;
if ( config . listTests ( ) )
listedCount = listedCount . valueOr ( 0 ) + listTests ( config ) ;
if ( config . listTestNamesOnly ( ) )
listedCount = listedCount . valueOr ( 0 ) + listTestsNamesOnly ( config ) ;
if ( config . listTags ( ) )
listedCount = listedCount . valueOr ( 0 ) + listTags ( config ) ;
if ( config . listReporters ( ) )
listedCount = listedCount . valueOr ( 0 ) + listReporters ( config ) ;
return listedCount ;
2014-12-28 16:11:01 +08:00
}
} // end namespace Catch
2015-12-20 22:42:01 +08:00
// #included from: internal/catch_run_context.hpp
2014-12-28 16:11:01 +08:00
# define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED
// #included from: catch_test_case_tracker.hpp
# define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
# include <map>
# include <string>
# include <assert.h>
2015-12-20 22:42:01 +08:00
# include <vector>
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
namespace Catch {
2015-12-20 22:42:01 +08:00
namespace TestCaseTracking {
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
struct ITracker : SharedImpl < > {
virtual ~ ITracker ( ) ;
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
// static queries
virtual std : : string name ( ) const = 0 ;
// dynamic queries
virtual bool isComplete ( ) const = 0 ; // Successfully completed or failed
virtual bool isSuccessfullyCompleted ( ) const = 0 ;
virtual bool isOpen ( ) const = 0 ; // Started but not complete
virtual bool hasChildren ( ) const = 0 ;
virtual ITracker & parent ( ) = 0 ;
// actions
virtual void close ( ) = 0 ; // Successfully complete
virtual void fail ( ) = 0 ;
virtual void markAsNeedingAnotherRun ( ) = 0 ;
virtual void addChild ( Ptr < ITracker > const & child ) = 0 ;
virtual ITracker * findChild ( std : : string const & name ) = 0 ;
virtual void openChild ( ) = 0 ;
2016-06-20 00:25:43 +08:00
// Debug/ checking
virtual bool isSectionTracker ( ) const = 0 ;
virtual bool isIndexTracker ( ) const = 0 ;
2015-12-20 22:42:01 +08:00
} ;
class TrackerContext {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
enum RunState {
NotStarted ,
Executing ,
2015-12-20 22:42:01 +08:00
CompletedCycle
2015-02-06 05:45:21 +08:00
} ;
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
Ptr < ITracker > m_rootTracker ;
ITracker * m_currentTracker ;
RunState m_runState ;
public :
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
static TrackerContext & instance ( ) {
static TrackerContext s_instance ;
return s_instance ;
}
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
TrackerContext ( )
: m_currentTracker ( CATCH_NULL ) ,
m_runState ( NotStarted )
{ }
2015-07-26 16:41:38 +08:00
2015-12-20 22:42:01 +08:00
ITracker & startRun ( ) ;
void endRun ( ) {
m_rootTracker . reset ( ) ;
m_currentTracker = CATCH_NULL ;
m_runState = NotStarted ;
2015-02-06 05:45:21 +08:00
}
2015-07-26 16:41:38 +08:00
2015-12-20 22:42:01 +08:00
void startCycle ( ) {
m_currentTracker = m_rootTracker . get ( ) ;
m_runState = Executing ;
2015-02-06 05:45:21 +08:00
}
2015-12-20 22:42:01 +08:00
void completeCycle ( ) {
m_runState = CompletedCycle ;
2014-12-28 16:11:01 +08:00
}
2015-12-20 22:42:01 +08:00
bool completedCycle ( ) const {
return m_runState = = CompletedCycle ;
}
ITracker & currentTracker ( ) {
return * m_currentTracker ;
}
void setCurrentTracker ( ITracker * tracker ) {
m_currentTracker = tracker ;
}
2015-02-06 05:45:21 +08:00
} ;
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
class TrackerBase : public ITracker {
protected :
enum CycleState {
NotStarted ,
Executing ,
ExecutingChildren ,
NeedsAnotherRun ,
CompletedSuccessfully ,
Failed
} ;
class TrackerHasName {
std : : string m_name ;
public :
TrackerHasName ( std : : string const & name ) : m_name ( name ) { }
bool operator ( ) ( Ptr < ITracker > const & tracker ) {
return tracker - > name ( ) = = m_name ;
2015-07-26 16:41:38 +08:00
}
2015-12-20 22:42:01 +08:00
} ;
typedef std : : vector < Ptr < ITracker > > Children ;
std : : string m_name ;
TrackerContext & m_ctx ;
ITracker * m_parent ;
Children m_children ;
CycleState m_runState ;
2015-02-06 05:45:21 +08:00
public :
2015-12-20 22:42:01 +08:00
TrackerBase ( std : : string const & name , TrackerContext & ctx , ITracker * parent )
: m_name ( name ) ,
m_ctx ( ctx ) ,
m_parent ( parent ) ,
m_runState ( NotStarted )
2015-02-06 05:45:21 +08:00
{ }
2015-12-20 22:42:01 +08:00
virtual ~ TrackerBase ( ) ;
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
virtual std : : string name ( ) const CATCH_OVERRIDE {
return m_name ;
}
virtual bool isComplete ( ) const CATCH_OVERRIDE {
return m_runState = = CompletedSuccessfully | | m_runState = = Failed ;
}
virtual bool isSuccessfullyCompleted ( ) const CATCH_OVERRIDE {
return m_runState = = CompletedSuccessfully ;
}
virtual bool isOpen ( ) const CATCH_OVERRIDE {
return m_runState ! = NotStarted & & ! isComplete ( ) ;
}
virtual bool hasChildren ( ) const CATCH_OVERRIDE {
return ! m_children . empty ( ) ;
}
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
virtual void addChild ( Ptr < ITracker > const & child ) CATCH_OVERRIDE {
m_children . push_back ( child ) ;
}
virtual ITracker * findChild ( std : : string const & name ) CATCH_OVERRIDE {
Children : : const_iterator it = std : : find_if ( m_children . begin ( ) , m_children . end ( ) , TrackerHasName ( name ) ) ;
return ( it ! = m_children . end ( ) )
? it - > get ( )
: CATCH_NULL ;
2015-02-06 05:45:21 +08:00
}
2015-12-20 22:42:01 +08:00
virtual ITracker & parent ( ) CATCH_OVERRIDE {
assert ( m_parent ) ; // Should always be non-null except for root
return * m_parent ;
2015-02-06 05:45:21 +08:00
}
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
virtual void openChild ( ) CATCH_OVERRIDE {
if ( m_runState ! = ExecutingChildren ) {
m_runState = ExecutingChildren ;
if ( m_parent )
m_parent - > openChild ( ) ;
}
2014-12-28 16:11:01 +08:00
}
2016-06-20 00:25:43 +08:00
virtual bool isSectionTracker ( ) const CATCH_OVERRIDE { return false ; }
virtual bool isIndexTracker ( ) const CATCH_OVERRIDE { return false ; }
2015-12-20 22:42:01 +08:00
void open ( ) {
m_runState = Executing ;
moveToThis ( ) ;
if ( m_parent )
m_parent - > openChild ( ) ;
2014-12-28 16:11:01 +08:00
}
2015-12-20 22:42:01 +08:00
virtual void close ( ) CATCH_OVERRIDE {
// Close any still open children (e.g. generators)
while ( & m_ctx . currentTracker ( ) ! = this )
m_ctx . currentTracker ( ) . close ( ) ;
switch ( m_runState ) {
case NotStarted :
case CompletedSuccessfully :
case Failed :
throw std : : logic_error ( " Illogical state " ) ;
case NeedsAnotherRun :
break ; ;
case Executing :
m_runState = CompletedSuccessfully ;
break ;
case ExecutingChildren :
if ( m_children . empty ( ) | | m_children . back ( ) - > isComplete ( ) )
m_runState = CompletedSuccessfully ;
break ;
default :
throw std : : logic_error ( " Unexpected state " ) ;
}
moveToParent ( ) ;
m_ctx . completeCycle ( ) ;
}
virtual void fail ( ) CATCH_OVERRIDE {
m_runState = Failed ;
if ( m_parent )
m_parent - > markAsNeedingAnotherRun ( ) ;
moveToParent ( ) ;
m_ctx . completeCycle ( ) ;
}
virtual void markAsNeedingAnotherRun ( ) CATCH_OVERRIDE {
m_runState = NeedsAnotherRun ;
}
private :
void moveToParent ( ) {
assert ( m_parent ) ;
m_ctx . setCurrentTracker ( m_parent ) ;
}
void moveToThis ( ) {
m_ctx . setCurrentTracker ( this ) ;
}
} ;
class SectionTracker : public TrackerBase {
public :
SectionTracker ( std : : string const & name , TrackerContext & ctx , ITracker * parent )
: TrackerBase ( name , ctx , parent )
{ }
virtual ~ SectionTracker ( ) ;
2016-06-20 00:25:43 +08:00
virtual bool isSectionTracker ( ) const CATCH_OVERRIDE { return true ; }
2015-12-20 22:42:01 +08:00
static SectionTracker & acquire ( TrackerContext & ctx , std : : string const & name ) {
SectionTracker * section = CATCH_NULL ;
ITracker & currentTracker = ctx . currentTracker ( ) ;
if ( ITracker * childTracker = currentTracker . findChild ( name ) ) {
2016-06-20 00:25:43 +08:00
assert ( childTracker ) ;
assert ( childTracker - > isSectionTracker ( ) ) ;
section = static_cast < SectionTracker * > ( childTracker ) ;
2015-02-06 05:45:21 +08:00
}
2015-12-20 22:42:01 +08:00
else {
section = new SectionTracker ( name , ctx , & currentTracker ) ;
currentTracker . addChild ( section ) ;
2015-02-06 05:45:21 +08:00
}
2015-12-20 22:42:01 +08:00
if ( ! ctx . completedCycle ( ) & & ! section - > isComplete ( ) ) {
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
section - > open ( ) ;
}
return * section ;
}
} ;
class IndexTracker : public TrackerBase {
int m_size ;
int m_index ;
public :
IndexTracker ( std : : string const & name , TrackerContext & ctx , ITracker * parent , int size )
: TrackerBase ( name , ctx , parent ) ,
m_size ( size ) ,
m_index ( - 1 )
{ }
virtual ~ IndexTracker ( ) ;
2016-06-20 00:25:43 +08:00
virtual bool isIndexTracker ( ) const CATCH_OVERRIDE { return true ; }
2015-12-20 22:42:01 +08:00
static IndexTracker & acquire ( TrackerContext & ctx , std : : string const & name , int size ) {
IndexTracker * tracker = CATCH_NULL ;
ITracker & currentTracker = ctx . currentTracker ( ) ;
if ( ITracker * childTracker = currentTracker . findChild ( name ) ) {
2016-06-20 00:25:43 +08:00
assert ( childTracker ) ;
assert ( childTracker - > isIndexTracker ( ) ) ;
tracker = static_cast < IndexTracker * > ( childTracker ) ;
2015-12-20 22:42:01 +08:00
}
else {
tracker = new IndexTracker ( name , ctx , & currentTracker , size ) ;
currentTracker . addChild ( tracker ) ;
}
if ( ! ctx . completedCycle ( ) & & ! tracker - > isComplete ( ) ) {
if ( tracker - > m_runState ! = ExecutingChildren & & tracker - > m_runState ! = NeedsAnotherRun )
tracker - > moveNext ( ) ;
tracker - > open ( ) ;
}
return * tracker ;
2015-02-06 05:45:21 +08:00
}
2015-12-20 22:42:01 +08:00
int index ( ) const { return m_index ; }
void moveNext ( ) {
m_index + + ;
m_children . clear ( ) ;
2015-02-06 05:45:21 +08:00
}
2015-12-20 22:42:01 +08:00
virtual void close ( ) CATCH_OVERRIDE {
TrackerBase : : close ( ) ;
if ( m_runState = = CompletedSuccessfully & & m_index < m_size - 1 )
m_runState = Executing ;
}
2015-02-06 05:45:21 +08:00
} ;
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
inline ITracker & TrackerContext : : startRun ( ) {
m_rootTracker = new SectionTracker ( " {root} " , * this , CATCH_NULL ) ;
m_currentTracker = CATCH_NULL ;
m_runState = Executing ;
return * m_rootTracker ;
}
} // namespace TestCaseTracking
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
using TestCaseTracking : : ITracker ;
using TestCaseTracking : : TrackerContext ;
using TestCaseTracking : : SectionTracker ;
using TestCaseTracking : : IndexTracker ;
2014-12-28 16:11:01 +08:00
} // namespace Catch
2015-06-20 21:47:26 +08: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 {
struct FatalConditionHandler {
void reset ( ) { }
} ;
} // namespace Catch
# else // Not Windows - assumed to be POSIX compatible //////////////////////////
# include <signal.h>
namespace Catch {
struct SignalDefs { int id ; const char * name ; } ;
extern SignalDefs signalDefs [ ] ;
SignalDefs signalDefs [ ] = {
{ SIGINT , " SIGINT - Terminal interrupt signal " } ,
{ SIGILL , " SIGILL - Illegal instruction signal " } ,
{ SIGFPE , " SIGFPE - Floating point error signal " } ,
{ SIGSEGV , " SIGSEGV - Segmentation violation signal " } ,
{ SIGTERM , " SIGTERM - Termination request signal " } ,
{ SIGABRT , " SIGABRT - Abort (abnormal termination) signal " }
} ;
struct FatalConditionHandler {
static void handleSignal ( int sig ) {
for ( std : : size_t i = 0 ; i < sizeof ( signalDefs ) / sizeof ( SignalDefs ) ; + + i )
if ( sig = = signalDefs [ i ] . id )
fatal ( signalDefs [ i ] . name , - sig ) ;
fatal ( " <unknown signal> " , - sig ) ;
}
FatalConditionHandler ( ) : m_isSet ( true ) {
for ( std : : size_t i = 0 ; i < sizeof ( signalDefs ) / sizeof ( SignalDefs ) ; + + i )
signal ( signalDefs [ i ] . id , handleSignal ) ;
}
~ FatalConditionHandler ( ) {
reset ( ) ;
}
void reset ( ) {
if ( m_isSet ) {
for ( std : : size_t i = 0 ; i < sizeof ( signalDefs ) / sizeof ( SignalDefs ) ; + + i )
signal ( signalDefs [ i ] . id , SIG_DFL ) ;
m_isSet = false ;
}
}
bool m_isSet ;
} ;
} // namespace Catch
# endif // not Windows
2014-12-28 16:11:01 +08:00
# include <set>
# include <string>
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
class StreamRedirect {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
public :
StreamRedirect ( std : : ostream & stream , std : : string & targetString )
2014-12-28 16:11:01 +08:00
: m_stream ( stream ) ,
m_prevBuf ( stream . rdbuf ( ) ) ,
m_targetString ( targetString )
2015-02-06 05:45:21 +08:00
{
stream . rdbuf ( m_oss . rdbuf ( ) ) ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
~ StreamRedirect ( ) {
m_targetString + = m_oss . str ( ) ;
m_stream . rdbuf ( m_prevBuf ) ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
private :
std : : ostream & m_stream ;
std : : streambuf * m_prevBuf ;
std : : ostringstream m_oss ;
std : : string & m_targetString ;
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
///////////////////////////////////////////////////////////////////////////
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
class RunContext : public IResultCapture , public IRunner {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
RunContext ( RunContext const & ) ;
void operator = ( RunContext const & ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
public :
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
explicit RunContext ( Ptr < IConfig const > const & _config , Ptr < IStreamingReporter > const & reporter )
: m_runInfo ( _config - > name ( ) ) ,
2014-12-28 16:11:01 +08:00
m_context ( getCurrentMutableContext ( ) ) ,
2015-12-20 22:42:01 +08:00
m_activeTestCase ( CATCH_NULL ) ,
m_config ( _config ) ,
m_reporter ( reporter )
2015-02-06 05:45:21 +08:00
{
m_context . setRunner ( this ) ;
m_context . setConfig ( m_config ) ;
m_context . setResultCapture ( this ) ;
m_reporter - > testRunStarting ( m_runInfo ) ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
virtual ~ RunContext ( ) {
m_reporter - > testRunEnded ( TestRunStats ( m_runInfo , m_totals , aborting ( ) ) ) ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
void testGroupStarting ( std : : string const & testSpec , std : : size_t groupIndex , std : : size_t groupsCount ) {
m_reporter - > testGroupStarting ( GroupInfo ( testSpec , groupIndex , groupsCount ) ) ;
}
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 ( ) ) ) ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
Totals runTest ( TestCase const & testCase ) {
Totals prevTotals = m_totals ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
std : : string redirectedCout ;
std : : string redirectedCerr ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
TestCaseInfo testInfo = testCase . getTestCaseInfo ( ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
m_reporter - > testCaseStarting ( testInfo ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
m_activeTestCase = & testCase ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
do {
2015-12-20 22:42:01 +08:00
m_trackerContext . startRun ( ) ;
2015-02-06 05:45:21 +08:00
do {
2015-12-20 22:42:01 +08:00
m_trackerContext . startCycle ( ) ;
m_testCaseTracker = & SectionTracker : : acquire ( m_trackerContext , testInfo . name ) ;
2015-02-06 05:45:21 +08:00
runCurrentTest ( redirectedCout , redirectedCerr ) ;
}
2015-12-20 22:42:01 +08:00
while ( ! m_testCaseTracker - > isSuccessfullyCompleted ( ) & & ! aborting ( ) ) ;
2014-12-28 16:11:01 +08:00
}
2015-12-20 22:42:01 +08:00
// !TBD: deprecated - this will be replaced by indexed trackers
2015-02-06 05:45:21 +08:00
while ( getCurrentContext ( ) . advanceGeneratorsForCurrentTest ( ) & & ! aborting ( ) ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
Totals deltaTotals = m_totals . delta ( prevTotals ) ;
2016-06-20 00:25:43 +08:00
if ( testInfo . expectedToFail ( ) & & deltaTotals . testCases . passed > 0 ) {
deltaTotals . assertions . failed + + ;
deltaTotals . testCases . passed - - ;
deltaTotals . testCases . failed + + ;
}
2015-02-06 05:45:21 +08:00
m_totals . testCases + = deltaTotals . testCases ;
m_reporter - > testCaseEnded ( TestCaseStats ( testInfo ,
deltaTotals ,
redirectedCout ,
redirectedCerr ,
aborting ( ) ) ) ;
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
m_activeTestCase = CATCH_NULL ;
m_testCaseTracker = CATCH_NULL ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
return deltaTotals ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
Ptr < IConfig const > config ( ) const {
return m_config ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
private : // IResultCapture
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
virtual void assertionEnded ( AssertionResult const & result ) {
if ( result . getResultType ( ) = = ResultWas : : Ok ) {
m_totals . assertions . passed + + ;
}
else if ( ! result . isOk ( ) ) {
m_totals . assertions . failed + + ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
if ( m_reporter - > assertionEnded ( AssertionStats ( result , m_messages , m_totals ) ) )
m_messages . clear ( ) ;
// Reset working state
m_lastAssertionInfo = AssertionInfo ( " " , m_lastAssertionInfo . lineInfo , " {Unknown expression after the reported line} " , m_lastAssertionInfo . resultDisposition ) ;
m_lastResult = result ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
virtual bool sectionStarted (
SectionInfo const & sectionInfo ,
Counts & assertions
)
{
std : : ostringstream oss ;
oss < < sectionInfo . name < < " @ " < < sectionInfo . lineInfo ;
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
ITracker & sectionTracker = SectionTracker : : acquire ( m_trackerContext , oss . str ( ) ) ;
if ( ! sectionTracker . isOpen ( ) )
2015-02-06 05:45:21 +08:00
return false ;
2015-12-20 22:42:01 +08:00
m_activeSections . push_back ( & sectionTracker ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
m_lastAssertionInfo . lineInfo = sectionInfo . lineInfo ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
m_reporter - > sectionStarting ( sectionInfo ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
assertions = m_totals . assertions ;
return true ;
}
bool testForMissingAssertions ( Counts & assertions ) {
2015-12-20 22:42:01 +08:00
if ( assertions . total ( ) ! = 0 )
return false ;
if ( ! m_config - > warnAboutMissingAssertions ( ) )
return false ;
if ( m_trackerContext . currentTracker ( ) . hasChildren ( ) )
2015-02-06 05:45:21 +08:00
return false ;
m_totals . assertions . failed + + ;
assertions . failed + + ;
return true ;
2014-12-28 16:11:01 +08:00
}
2015-12-20 22:42:01 +08:00
virtual void sectionEnded ( SectionEndInfo const & endInfo ) {
Counts assertions = m_totals . assertions - endInfo . prevAssertions ;
2015-02-06 05:45:21 +08:00
bool missingAssertions = testForMissingAssertions ( assertions ) ;
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
if ( ! m_activeSections . empty ( ) ) {
m_activeSections . back ( ) - > close ( ) ;
m_activeSections . pop_back ( ) ;
}
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
m_reporter - > sectionEnded ( SectionStats ( endInfo . sectionInfo , assertions , endInfo . durationInSeconds , missingAssertions ) ) ;
2015-02-06 05:45:21 +08:00
m_messages . clear ( ) ;
}
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
virtual void sectionEndedEarly ( SectionEndInfo const & endInfo ) {
if ( m_unfinishedSections . empty ( ) )
m_activeSections . back ( ) - > fail ( ) ;
else
m_activeSections . back ( ) - > close ( ) ;
m_activeSections . pop_back ( ) ;
m_unfinishedSections . push_back ( endInfo ) ;
}
2015-02-06 05:45:21 +08:00
virtual void pushScopedMessage ( MessageInfo const & message ) {
m_messages . push_back ( message ) ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
virtual void popScopedMessage ( MessageInfo const & message ) {
m_messages . erase ( std : : remove ( m_messages . begin ( ) , m_messages . end ( ) , message ) , m_messages . end ( ) ) ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
virtual std : : string getCurrentTestName ( ) const {
return m_activeTestCase
? m_activeTestCase - > getTestCaseInfo ( ) . name
: " " ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
virtual const AssertionResult * getLastResult ( ) const {
return & m_lastResult ;
}
2015-06-20 21:47:26 +08: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 ) ) ;
}
2015-02-06 05:45:21 +08:00
public :
// !TBD We need to do this another way!
bool aborting ( ) const {
return m_totals . assertions . failed = = static_cast < std : : size_t > ( m_config - > abortAfter ( ) ) ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
private :
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
void runCurrentTest ( std : : string & redirectedCout , std : : string & redirectedCerr ) {
TestCaseInfo const & testCaseInfo = m_activeTestCase - > getTestCaseInfo ( ) ;
SectionInfo testCaseSection ( testCaseInfo . lineInfo , testCaseInfo . name , testCaseInfo . description ) ;
m_reporter - > sectionStarting ( testCaseSection ) ;
Counts prevAssertions = m_totals . assertions ;
double duration = 0 ;
try {
m_lastAssertionInfo = AssertionInfo ( " TEST_CASE " , testCaseInfo . lineInfo , " " , ResultDisposition : : Normal ) ;
2015-12-20 22:42:01 +08:00
seedRng ( * m_config ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
Timer timer ;
timer . start ( ) ;
if ( m_reporter - > getPreferences ( ) . shouldRedirectStdOut ) {
2015-06-20 21:47:26 +08:00
StreamRedirect coutRedir ( Catch : : cout ( ) , redirectedCout ) ;
StreamRedirect cerrRedir ( Catch : : cerr ( ) , redirectedCerr ) ;
invokeActiveTestCase ( ) ;
2015-02-06 05:45:21 +08:00
}
else {
2015-06-20 21:47:26 +08:00
invokeActiveTestCase ( ) ;
2015-02-06 05:45:21 +08:00
}
duration = timer . getElapsedSeconds ( ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
catch ( TestFailureException & ) {
// This just means the test was aborted due to failure
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
catch ( . . . ) {
2015-06-20 21:47:26 +08:00
makeUnexpectedResultBuilder ( ) . useActiveException ( ) ;
2015-02-06 05:45:21 +08:00
}
2015-12-20 22:42:01 +08:00
m_testCaseTracker - > close ( ) ;
2015-06-20 21:47:26 +08:00
handleUnfinishedSections ( ) ;
2015-02-06 05:45:21 +08:00
m_messages . clear ( ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
Counts assertions = m_totals . assertions - prevAssertions ;
bool missingAssertions = testForMissingAssertions ( assertions ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
if ( testCaseInfo . okToFail ( ) ) {
std : : swap ( assertions . failedButOk , assertions . failed ) ;
m_totals . assertions . failed - = assertions . failedButOk ;
m_totals . assertions . failedButOk + = assertions . failedButOk ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
SectionStats testCaseSectionStats ( testCaseSection , assertions , duration , missingAssertions ) ;
m_reporter - > sectionEnded ( testCaseSectionStats ) ;
}
2014-12-28 16:11:01 +08:00
2015-06-20 21:47:26 +08:00
void invokeActiveTestCase ( ) {
FatalConditionHandler fatalConditionHandler ; // Handle signals
m_activeTestCase - > invoke ( ) ;
fatalConditionHandler . reset ( ) ;
}
2015-02-06 05:45:21 +08:00
private :
2015-06-20 21:47:26 +08: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.
2015-12-20 22:42:01 +08:00
for ( std : : vector < SectionEndInfo > : : const_reverse_iterator it = m_unfinishedSections . rbegin ( ) ,
2015-06-20 21:47:26 +08:00
itEnd = m_unfinishedSections . rend ( ) ;
it ! = itEnd ;
+ + it )
2015-12-20 22:42:01 +08:00
sectionEnded ( * it ) ;
2015-06-20 21:47:26 +08:00
m_unfinishedSections . clear ( ) ;
}
2015-02-06 05:45:21 +08:00
TestRunInfo m_runInfo ;
IMutableContext & m_context ;
TestCase const * m_activeTestCase ;
2015-12-20 22:42:01 +08:00
ITracker * m_testCaseTracker ;
ITracker * m_currentSectionTracker ;
2015-02-06 05:45:21 +08:00
AssertionResult m_lastResult ;
Ptr < IConfig const > m_config ;
Totals m_totals ;
Ptr < IStreamingReporter > m_reporter ;
std : : vector < MessageInfo > m_messages ;
AssertionInfo m_lastAssertionInfo ;
2015-12-20 22:42:01 +08:00
std : : vector < SectionEndInfo > m_unfinishedSections ;
std : : vector < ITracker * > m_activeSections ;
TrackerContext m_trackerContext ;
2015-02-06 05:45:21 +08:00
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
IResultCapture & getResultCapture ( ) {
if ( IResultCapture * capture = getCurrentContext ( ) . getResultCapture ( ) )
return * capture ;
else
throw std : : logic_error ( " No result capture instance " ) ;
2014-12-28 16:11:01 +08:00
}
} // end namespace Catch
// #included from: internal/catch_version.h
# define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
// Versioning information
struct Version {
Version ( unsigned int _majorVersion ,
unsigned int _minorVersion ,
2015-07-26 16:41:38 +08:00
unsigned int _patchNumber ,
std : : string const & _branchName ,
unsigned int _buildNumber ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
unsigned int const majorVersion ;
unsigned int const minorVersion ;
2015-07-26 16:41:38 +08:00
unsigned int const patchNumber ;
// buildNumber is only used if branchName is not null
std : : string const branchName ;
2015-02-06 05:45:21 +08:00
unsigned int const buildNumber ;
2015-07-26 16:41:38 +08:00
friend std : : ostream & operator < < ( std : : ostream & os , Version const & version ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
private :
void operator = ( Version const & ) ;
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
extern Version libraryVersion ;
2014-12-28 16:11:01 +08:00
}
# include <fstream>
# include <stdlib.h>
# include <limits>
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
Ptr < IStreamingReporter > createReporter ( std : : string const & reporterName , Ptr < Config > const & config ) {
Ptr < IStreamingReporter > reporter = getRegistryHub ( ) . getReporterRegistry ( ) . create ( reporterName , config . get ( ) ) ;
if ( ! reporter ) {
std : : ostringstream oss ;
oss < < " No reporter registered with name: ' " < < reporterName < < " ' " ;
throw std : : domain_error ( oss . str ( ) ) ;
2015-02-06 05:45:21 +08:00
}
2015-12-20 22:42:01 +08:00
return reporter ;
}
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
Ptr < IStreamingReporter > makeReporter ( Ptr < Config > const & config ) {
std : : vector < std : : string > reporters = config - > getReporterNames ( ) ;
if ( reporters . empty ( ) )
reporters . push_back ( " console " ) ;
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
Ptr < IStreamingReporter > reporter ;
for ( std : : vector < std : : string > : : const_iterator it = reporters . begin ( ) , itEnd = reporters . end ( ) ;
it ! = itEnd ;
+ + it )
reporter = addReporter ( reporter , createReporter ( * it , config ) ) ;
return reporter ;
}
Ptr < IStreamingReporter > addListeners ( Ptr < IConfig const > const & config , Ptr < IStreamingReporter > reporters ) {
IReporterRegistry : : Listeners listeners = getRegistryHub ( ) . getReporterRegistry ( ) . getListeners ( ) ;
for ( IReporterRegistry : : Listeners : : const_iterator it = listeners . begin ( ) , itEnd = listeners . end ( ) ;
it ! = itEnd ;
+ + it )
reporters = addReporter ( reporters , ( * it ) - > create ( ReporterConfig ( config ) ) ) ;
return reporters ;
}
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
Totals runTests ( Ptr < Config > const & config ) {
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
Ptr < IConfig const > iconfig = config . get ( ) ;
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
Ptr < IStreamingReporter > reporter = makeReporter ( config ) ;
reporter = addListeners ( iconfig , reporter ) ;
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
RunContext context ( iconfig , reporter ) ;
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
Totals totals ;
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
context . testGroupStarting ( config - > name ( ) , 1 , 1 ) ;
2015-06-20 21:47:26 +08:00
2015-12-20 22:42:01 +08:00
TestSpec testSpec = config - > testSpec ( ) ;
if ( ! testSpec . hasFilters ( ) )
testSpec = TestSpecParser ( ITagAliasRegistry : : get ( ) ) . parse ( " ~[.] " ) . testSpec ( ) ; // All not hidden tests
2015-06-20 21:47:26 +08:00
2015-12-20 22:42:01 +08:00
std : : vector < TestCase > const & allTestCases = getAllTestCasesSorted ( * iconfig ) ;
for ( std : : vector < TestCase > : : const_iterator it = allTestCases . begin ( ) , itEnd = allTestCases . end ( ) ;
it ! = itEnd ;
+ + it ) {
if ( ! context . aborting ( ) & & matchTest ( * it , testSpec , * iconfig ) )
totals + = context . runTest ( * it ) ;
else
reporter - > skipTest ( * it ) ;
2015-02-06 05:45:21 +08:00
}
2015-12-20 22:42:01 +08:00
context . testGroupEnded ( iconfig - > name ( ) , totals , 1 , 1 ) ;
return totals ;
}
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
void applyFilenamesAsTags ( IConfig const & config ) {
std : : vector < TestCase > const & tests = getAllTestCasesSorted ( config ) ;
for ( std : : size_t i = 0 ; i < tests . size ( ) ; + + i ) {
TestCase & test = const_cast < TestCase & > ( tests [ i ] ) ;
std : : set < std : : string > tags = test . tags ;
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
std : : string filename = test . lineInfo . file ;
std : : string : : size_type lastSlash = filename . find_last_of ( " \\ / " ) ;
if ( lastSlash ! = std : : string : : npos )
filename = filename . substr ( lastSlash + 1 ) ;
std : : string : : size_type lastDot = filename . find_last_of ( " . " ) ;
if ( lastDot ! = std : : string : : npos )
filename = filename . substr ( 0 , lastDot ) ;
tags . insert ( " # " + filename ) ;
setTags ( test , tags ) ;
}
}
2014-12-28 16:11:01 +08:00
2015-06-20 21:47:26 +08:00
class Session : NonCopyable {
2015-02-06 05:45:21 +08:00
static bool alreadyInstantiated ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
public :
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
struct OnUnusedOptions { enum DoWhat { Ignore , Fail } ; } ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
Session ( )
: m_cli ( makeCommandLineParser ( ) ) {
if ( alreadyInstantiated ) {
std : : string msg = " Only one instance of Catch::Session can ever be used " ;
2015-06-20 21:47:26 +08:00
Catch : : cerr ( ) < < msg < < std : : endl ;
2015-02-06 05:45:21 +08:00
throw std : : logic_error ( msg ) ;
}
alreadyInstantiated = true ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
~ Session ( ) {
Catch : : cleanUp ( ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
void showHelp ( std : : string const & processName ) {
2015-07-26 16:41:38 +08:00
Catch : : cout ( ) < < " \n Catch v " < < libraryVersion < < " \n " ;
2014-12-28 16:11:01 +08:00
2015-06-20 21:47:26 +08:00
m_cli . usage ( Catch : : cout ( ) , processName ) ;
Catch : : cout ( ) < < " For more detail usage please see the project docs \n " < < std : : endl ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
2016-06-20 00:25:43 +08:00
int applyCommandLine ( int argc , char const * const * const argv , OnUnusedOptions : : DoWhat unusedOptionBehaviour = OnUnusedOptions : : Fail ) {
2015-02-06 05:45:21 +08:00
try {
m_cli . setThrowOnUnrecognisedTokens ( unusedOptionBehaviour = = OnUnusedOptions : : Fail ) ;
2016-06-20 00:25:43 +08:00
m_unusedTokens = m_cli . parseInto ( Clara : : argsToVector ( argc , argv ) , m_configData ) ;
2015-02-06 05:45:21 +08:00
if ( m_configData . showHelp )
showHelp ( m_configData . processName ) ;
m_config . reset ( ) ;
}
catch ( std : : exception & ex ) {
{
Colour colourGuard ( Colour : : Red ) ;
2015-07-26 16:41:38 +08:00
Catch : : cerr ( )
< < " \n Error(s) in input: \n "
< < Text ( ex . what ( ) , TextAttributes ( ) . setIndent ( 2 ) )
< < " \n \n " ;
2015-02-06 05:45:21 +08:00
}
2015-06-20 21:47:26 +08:00
m_cli . usage ( Catch : : cout ( ) , m_configData . processName ) ;
2015-02-06 05:45:21 +08:00
return ( std : : numeric_limits < int > : : max ) ( ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
return 0 ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
void useConfigData ( ConfigData const & _configData ) {
m_configData = _configData ;
m_config . reset ( ) ;
2014-12-28 16:11:01 +08:00
}
2016-06-20 00:25:43 +08:00
int run ( int argc , char const * const * const argv ) {
2015-02-06 05:45:21 +08:00
int returnCode = applyCommandLine ( argc , argv ) ;
if ( returnCode = = 0 )
returnCode = run ( ) ;
return returnCode ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
int run ( ) {
if ( m_configData . showHelp )
return 0 ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
try
2014-12-28 16:11:01 +08:00
{
2015-02-06 05:45:21 +08:00
config ( ) ; // Force config to be constructed
2015-06-20 21:47:26 +08:00
2015-12-20 22:42:01 +08:00
seedRng ( * m_config ) ;
2015-06-20 21:47:26 +08:00
2015-12-20 22:42:01 +08:00
if ( m_configData . filenamesAsTags )
applyFilenamesAsTags ( * m_config ) ;
2015-02-06 05:45:21 +08:00
// Handle list request
if ( Option < std : : size_t > listed = list ( config ( ) ) )
return static_cast < int > ( * listed ) ;
2015-12-20 22:42:01 +08:00
return static_cast < int > ( runTests ( m_config ) . assertions . failed ) ;
2015-02-06 05:45:21 +08:00
}
catch ( std : : exception & ex ) {
2015-06-20 21:47:26 +08:00
Catch : : cerr ( ) < < ex . what ( ) < < std : : endl ;
2015-02-06 05:45:21 +08:00
return ( std : : numeric_limits < int > : : max ) ( ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
Clara : : CommandLine < ConfigData > const & cli ( ) const {
return m_cli ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
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 ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
private :
Clara : : CommandLine < ConfigData > m_cli ;
std : : vector < Clara : : Parser : : Token > m_unusedTokens ;
ConfigData m_configData ;
Ptr < Config > m_config ;
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
bool Session : : alreadyInstantiated = false ;
2014-12-28 16:11:01 +08:00
} // end namespace Catch
// #included from: catch_registry_hub.hpp
# define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED
// #included from: catch_test_case_registry_impl.hpp
# define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
# include <vector>
# include <set>
# include <sstream>
# include <iostream>
2015-06-20 21:47:26 +08:00
# include <algorithm>
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
struct RandomNumberGenerator {
2016-11-17 02:15:54 +08:00
typedef std : : ptrdiff_t result_type ;
2016-06-20 00:25:43 +08:00
result_type operator ( ) ( result_type n ) const { return std : : rand ( ) % n ; }
2017-01-12 05:23:02 +08:00
# ifdef CATCH_CONFIG_CPP11_SHUFFLE
2016-06-20 00:25:43 +08:00
static constexpr result_type min ( ) { return 0 ; }
static constexpr result_type max ( ) { return 1000000 ; }
result_type operator ( ) ( ) const { return std : : rand ( ) % max ( ) ; }
# endif
template < typename V >
static void shuffle ( V & vector ) {
RandomNumberGenerator rng ;
2017-01-12 05:23:02 +08:00
# ifdef CATCH_CONFIG_CPP11_SHUFFLE
2016-06-20 00:25:43 +08:00
std : : shuffle ( vector . begin ( ) , vector . end ( ) , rng ) ;
# else
std : : random_shuffle ( vector . begin ( ) , vector . end ( ) , rng ) ;
# endif
}
2015-12-20 22:42:01 +08: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 :
2016-06-20 00:25:43 +08:00
std : : sort ( sorted . begin ( ) , sorted . end ( ) ) ;
2015-12-20 22:42:01 +08:00
break ;
case RunTests : : InRandomOrder :
{
seedRng ( config ) ;
2016-06-20 00:25:43 +08:00
RandomNumberGenerator : : shuffle ( sorted ) ;
2015-12-20 22:42:01 +08:00
}
break ;
case RunTests : : InDeclarationOrder :
// already in declaration order
break ;
}
return sorted ;
}
bool matchTest ( TestCase const & testCase , TestSpec const & testSpec , IConfig const & config ) {
return testSpec . matches ( testCase ) & & ( config . allowThrows ( ) | | ! testCase . throws ( ) ) ;
}
void enforceNoDuplicateTestCases ( std : : vector < TestCase > const & functions ) {
std : : set < TestCase > seenFunctions ;
for ( std : : vector < TestCase > : : const_iterator it = functions . begin ( ) , itEnd = functions . end ( ) ;
it ! = itEnd ;
+ + it ) {
std : : pair < std : : set < TestCase > : : const_iterator , bool > prev = seenFunctions . insert ( * it ) ;
2016-06-20 00:25:43 +08:00
if ( ! prev . second ) {
std : : ostringstream ss ;
ss < < 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 ;
throw std : : runtime_error ( ss . str ( ) ) ;
2015-12-20 22:42:01 +08:00
}
}
}
std : : vector < TestCase > filterTests ( std : : vector < TestCase > const & testCases , TestSpec const & testSpec , IConfig const & config ) {
std : : vector < TestCase > filtered ;
filtered . reserve ( testCases . size ( ) ) ;
for ( std : : vector < TestCase > : : const_iterator it = testCases . begin ( ) , itEnd = testCases . end ( ) ;
it ! = itEnd ;
+ + it )
if ( matchTest ( * it , testSpec , config ) )
filtered . push_back ( * it ) ;
return filtered ;
}
std : : vector < TestCase > const & getAllTestCasesSorted ( IConfig const & config ) {
return getRegistryHub ( ) . getTestCaseRegistry ( ) . getAllTestsSorted ( config ) ;
}
2015-06-20 21:47:26 +08:00
2015-12-20 22:42:01 +08:00
class TestRegistry : public ITestCaseRegistry {
2015-02-06 05:45:21 +08:00
public :
2015-12-20 22:42:01 +08:00
TestRegistry ( )
: m_currentSortOrder ( RunTests : : InDeclarationOrder ) ,
m_unnamedCount ( 0 )
{ }
2015-02-06 05:45:21 +08:00
virtual ~ TestRegistry ( ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
virtual void registerTest ( TestCase const & testCase ) {
std : : string name = testCase . getTestCaseInfo ( ) . name ;
if ( name = = " " ) {
std : : ostringstream oss ;
oss < < " Anonymous test case " < < + + m_unnamedCount ;
return registerTest ( testCase . withName ( oss . str ( ) ) ) ;
}
2015-12-20 22:42:01 +08:00
m_functions . push_back ( testCase ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
virtual std : : vector < TestCase > const & getAllTests ( ) const {
2015-12-20 22:42:01 +08:00
return m_functions ;
2015-02-06 05:45:21 +08:00
}
2015-12-20 22:42:01 +08:00
virtual std : : vector < TestCase > const & getAllTestsSorted ( IConfig const & config ) const {
if ( m_sortedFunctions . empty ( ) )
enforceNoDuplicateTestCases ( m_functions ) ;
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
if ( m_currentSortOrder ! = config . runOrder ( ) | | m_sortedFunctions . empty ( ) ) {
m_sortedFunctions = sortTests ( config , m_functions ) ;
m_currentSortOrder = config . runOrder ( ) ;
2014-12-28 16:11:01 +08:00
}
2015-12-20 22:42:01 +08:00
return m_sortedFunctions ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
private :
2015-12-20 22:42:01 +08:00
std : : vector < TestCase > m_functions ;
mutable RunTests : : InWhatOrder m_currentSortOrder ;
mutable std : : vector < TestCase > m_sortedFunctions ;
2015-02-06 05:45:21 +08:00
size_t m_unnamedCount ;
2015-12-20 22:42:01 +08:00
std : : ios_base : : Init m_ostreamInit ; // Forces cout/ cerr to be initialised
2015-02-06 05:45:21 +08:00
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
///////////////////////////////////////////////////////////////////////////
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
class FreeFunctionTestCase : public SharedImpl < ITestCase > {
public :
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
FreeFunctionTestCase ( TestFunction fun ) : m_fun ( fun ) { }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
virtual void invoke ( ) const {
m_fun ( ) ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
private :
virtual ~ FreeFunctionTestCase ( ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
TestFunction m_fun ;
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
inline std : : string extractClassName ( std : : string const & classOrQualifiedMethodName ) {
std : : string className = classOrQualifiedMethodName ;
if ( startsWith ( className , " & " ) )
2014-12-28 16:11:01 +08:00
{
2015-02-06 05:45:21 +08: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 ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
return className ;
2014-12-28 16:11:01 +08:00
}
2015-12-20 22:42:01 +08:00
void registerTestCase
( ITestCase * testCase ,
char const * classOrQualifiedMethodName ,
NameAndDesc const & nameAndDesc ,
SourceLineInfo const & lineInfo ) {
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
getMutableRegistryHub ( ) . registerTest
( makeTestCase
( testCase ,
extractClassName ( classOrQualifiedMethodName ) ,
nameAndDesc . name ,
nameAndDesc . description ,
lineInfo ) ) ;
}
void registerTestCaseFunction
( TestFunction function ,
SourceLineInfo const & lineInfo ,
NameAndDesc const & nameAndDesc ) {
2015-02-06 05:45:21 +08:00
registerTestCase ( new FreeFunctionTestCase ( function ) , " " , nameAndDesc , lineInfo ) ;
}
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
///////////////////////////////////////////////////////////////////////////
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
AutoReg : : AutoReg
( TestFunction function ,
SourceLineInfo const & lineInfo ,
NameAndDesc const & nameAndDesc ) {
registerTestCaseFunction ( function , lineInfo , nameAndDesc ) ;
2015-02-06 05:45:21 +08:00
}
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
AutoReg : : ~ AutoReg ( ) { }
2014-12-28 16:11:01 +08:00
} // end namespace Catch
// #included from: catch_reporter_registry.hpp
# define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED
# include <map>
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
class ReporterRegistry : public IReporterRegistry {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
public :
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
virtual ~ ReporterRegistry ( ) CATCH_OVERRIDE { }
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
virtual IStreamingReporter * create ( std : : string const & name , Ptr < IConfig const > const & config ) const CATCH_OVERRIDE {
2015-02-06 05:45:21 +08:00
FactoryMap : : const_iterator it = m_factories . find ( name ) ;
if ( it = = m_factories . end ( ) )
2015-12-20 22:42:01 +08:00
return CATCH_NULL ;
2015-02-06 05:45:21 +08:00
return it - > second - > create ( ReporterConfig ( config ) ) ;
2014-12-28 16:11:01 +08:00
}
2015-12-20 22:42:01 +08:00
void registerReporter ( std : : string const & name , Ptr < IReporterFactory > const & factory ) {
2015-02-06 05:45:21 +08:00
m_factories . insert ( std : : make_pair ( name , factory ) ) ;
}
2015-12-20 22:42:01 +08:00
void registerListener ( Ptr < IReporterFactory > const & factory ) {
m_listeners . push_back ( factory ) ;
}
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
virtual FactoryMap const & getFactories ( ) const CATCH_OVERRIDE {
2015-02-06 05:45:21 +08:00
return m_factories ;
}
2015-12-20 22:42:01 +08:00
virtual Listeners const & getListeners ( ) const CATCH_OVERRIDE {
return m_listeners ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
private :
FactoryMap m_factories ;
2015-12-20 22:42:01 +08:00
Listeners m_listeners ;
2015-02-06 05:45:21 +08:00
} ;
2014-12-28 16:11:01 +08:00
}
// #included from: catch_exception_translator_registry.hpp
# define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED
# ifdef __OBJC__
2015-02-06 05:45:21 +08:00
# import "Foundation / Foundation.h"
2014-12-28 16:11:01 +08:00
# endif
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry {
public :
~ ExceptionTranslatorRegistry ( ) {
deleteAll ( m_translators ) ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
virtual void registerTranslator ( const IExceptionTranslator * translator ) {
m_translators . push_back ( translator ) ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
virtual std : : string translateActiveException ( ) const {
try {
2014-12-28 16:11:01 +08:00
# ifdef __OBJC__
2015-02-06 05:45:21 +08:00
// In Objective-C try objective-c exceptions first
@ try {
2015-12-20 22:42:01 +08:00
return tryTranslators ( ) ;
2015-02-06 05:45:21 +08:00
}
@ catch ( NSException * exception ) {
2015-06-20 21:47:26 +08:00
return Catch : : toString ( [ exception description ] ) ;
2015-02-06 05:45:21 +08:00
}
# else
2015-12-20 22:42:01 +08:00
return tryTranslators ( ) ;
2015-02-06 05:45:21 +08:00
# endif
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
catch ( TestFailureException & ) {
throw ;
}
catch ( std : : exception & ex ) {
return ex . what ( ) ;
}
catch ( std : : string & msg ) {
return msg ;
}
catch ( const char * msg ) {
return msg ;
}
catch ( . . . ) {
2015-12-20 22:42:01 +08:00
return " Unknown exception " ;
2014-12-28 16:11:01 +08:00
}
}
2015-12-20 22:42:01 +08:00
std : : string tryTranslators ( ) const {
if ( m_translators . empty ( ) )
throw ;
else
return m_translators [ 0 ] - > translate ( m_translators . begin ( ) + 1 , m_translators . end ( ) ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
private :
std : : vector < const IExceptionTranslator * > m_translators ;
} ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
namespace {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
class RegistryHub : public IRegistryHub , public IMutableRegistryHub {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
RegistryHub ( RegistryHub const & ) ;
void operator = ( RegistryHub const & ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
public : // IRegistryHub
RegistryHub ( ) {
}
2015-12-20 22:42:01 +08:00
virtual IReporterRegistry const & getReporterRegistry ( ) const CATCH_OVERRIDE {
2015-02-06 05:45:21 +08:00
return m_reporterRegistry ;
}
2015-12-20 22:42:01 +08:00
virtual ITestCaseRegistry const & getTestCaseRegistry ( ) const CATCH_OVERRIDE {
2015-02-06 05:45:21 +08:00
return m_testCaseRegistry ;
}
2015-12-20 22:42:01 +08:00
virtual IExceptionTranslatorRegistry & getExceptionTranslatorRegistry ( ) CATCH_OVERRIDE {
2015-02-06 05:45:21 +08:00
return m_exceptionTranslatorRegistry ;
}
public : // IMutableRegistryHub
2015-12-20 22:42:01 +08:00
virtual void registerReporter ( std : : string const & name , Ptr < IReporterFactory > const & factory ) CATCH_OVERRIDE {
2015-02-06 05:45:21 +08:00
m_reporterRegistry . registerReporter ( name , factory ) ;
}
2015-12-20 22:42:01 +08:00
virtual void registerListener ( Ptr < IReporterFactory > const & factory ) CATCH_OVERRIDE {
m_reporterRegistry . registerListener ( factory ) ;
}
virtual void registerTest ( TestCase const & testInfo ) CATCH_OVERRIDE {
2015-02-06 05:45:21 +08:00
m_testCaseRegistry . registerTest ( testInfo ) ;
}
2015-12-20 22:42:01 +08:00
virtual void registerTranslator ( const IExceptionTranslator * translator ) CATCH_OVERRIDE {
2015-02-06 05:45:21 +08:00
m_exceptionTranslatorRegistry . registerTranslator ( translator ) ;
}
private :
TestRegistry m_testCaseRegistry ;
ReporterRegistry m_reporterRegistry ;
ExceptionTranslatorRegistry m_exceptionTranslatorRegistry ;
} ;
// Single, global, instance
inline RegistryHub * & getTheRegistryHub ( ) {
2015-12-20 22:42:01 +08:00
static RegistryHub * theRegistryHub = CATCH_NULL ;
2015-02-06 05:45:21 +08:00
if ( ! theRegistryHub )
theRegistryHub = new RegistryHub ( ) ;
return theRegistryHub ;
}
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
IRegistryHub & getRegistryHub ( ) {
return * getTheRegistryHub ( ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
IMutableRegistryHub & getMutableRegistryHub ( ) {
return * getTheRegistryHub ( ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
void cleanUp ( ) {
delete getTheRegistryHub ( ) ;
2015-12-20 22:42:01 +08:00
getTheRegistryHub ( ) = CATCH_NULL ;
2015-02-06 05:45:21 +08:00
cleanUpContext ( ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
std : : string translateActiveException ( ) {
return getRegistryHub ( ) . getExceptionTranslatorRegistry ( ) . translateActiveException ( ) ;
2014-12-28 16:11:01 +08:00
}
} // end namespace Catch
// #included from: catch_notimplemented_exception.hpp
# define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED
# include <ostream>
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
NotImplementedException : : NotImplementedException ( SourceLineInfo const & lineInfo )
: m_lineInfo ( lineInfo ) {
std : : ostringstream oss ;
oss < < lineInfo < < " : function " ;
oss < < " not implemented " ;
m_what = oss . str ( ) ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
const char * NotImplementedException : : what ( ) const CATCH_NOEXCEPT {
return m_what . c_str ( ) ;
}
2014-12-28 16:11:01 +08:00
} // end namespace Catch
2015-12-20 22:42:01 +08:00
// #included from: catch_context_impl.hpp
# define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED
// #included from: catch_stream.hpp
# define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED
2014-12-28 16:11:01 +08:00
# include <stdexcept>
# include <cstdio>
2015-06-20 21:47:26 +08:00
# include <iostream>
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
template < typename WriterF , size_t bufferSize = 256 >
class StreamBufImpl : public StreamBufBase {
char data [ bufferSize ] ;
WriterF m_writer ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
public :
StreamBufImpl ( ) {
setp ( data , data + sizeof ( data ) ) ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
~ StreamBufImpl ( ) CATCH_NOEXCEPT {
sync ( ) ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
private :
int overflow ( int c ) {
sync ( ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
if ( c ! = EOF ) {
if ( pbase ( ) = = epptr ( ) )
m_writer ( std : : string ( 1 , static_cast < char > ( c ) ) ) ;
else
sputc ( static_cast < char > ( c ) ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
return 0 ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
int sync ( ) {
if ( pbase ( ) ! = pptr ( ) ) {
m_writer ( std : : string ( pbase ( ) , static_cast < std : : string : : size_type > ( pptr ( ) - pbase ( ) ) ) ) ;
setp ( pbase ( ) , epptr ( ) ) ;
}
return 0 ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
///////////////////////////////////////////////////////////////////////////
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
FileStream : : FileStream ( std : : string const & filename ) {
m_ofs . open ( filename . c_str ( ) ) ;
if ( m_ofs . fail ( ) ) {
std : : ostringstream oss ;
oss < < " Unable to open file: ' " < < filename < < " ' " ;
throw std : : domain_error ( oss . str ( ) ) ;
}
}
std : : ostream & FileStream : : stream ( ) const {
return m_ofs ;
}
2015-02-06 05:45:21 +08:00
struct OutputDebugWriter {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
void operator ( ) ( std : : string const & str ) {
writeToDebugConsole ( str ) ;
}
} ;
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
DebugOutStream : : DebugOutStream ( )
: m_streamBuf ( new StreamBufImpl < OutputDebugWriter > ( ) ) ,
m_os ( m_streamBuf . get ( ) )
2015-02-06 05:45:21 +08:00
{ }
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
std : : ostream & DebugOutStream : : stream ( ) const {
return m_os ;
}
// Store the streambuf from cout up-front because
// cout may get redirected when running tests
CoutStream : : CoutStream ( )
: m_os ( Catch : : cout ( ) . rdbuf ( ) )
2015-02-06 05:45:21 +08:00
{ }
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
std : : ostream & CoutStream : : stream ( ) const {
return m_os ;
2014-12-28 16:11:01 +08:00
}
2015-06-20 21:47:26 +08:00
2015-12-20 22:42:01 +08:00
# ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions
2015-06-20 21:47:26 +08:00
std : : ostream & cout ( ) {
return std : : cout ;
}
std : : ostream & cerr ( ) {
return std : : cerr ;
}
# endif
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
class Context : public IMutableContext {
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
Context ( ) : m_config ( CATCH_NULL ) , m_runner ( CATCH_NULL ) , m_resultCapture ( CATCH_NULL ) { }
2015-02-06 05:45:21 +08:00
Context ( Context const & ) ;
void operator = ( Context const & ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
public : // IContext
virtual IResultCapture * getResultCapture ( ) {
return m_resultCapture ;
}
virtual IRunner * getRunner ( ) {
return m_runner ;
}
virtual size_t getGeneratorIndex ( std : : string const & fileInfo , size_t totalSize ) {
return getGeneratorsForCurrentTest ( )
. getGeneratorInfo ( fileInfo , totalSize )
. getCurrentIndex ( ) ;
}
virtual bool advanceGeneratorsForCurrentTest ( ) {
IGeneratorsForTest * generators = findGeneratorsForCurrentTest ( ) ;
return generators & & generators - > moveNext ( ) ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
virtual Ptr < IConfig const > getConfig ( ) const {
return m_config ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
public : // IMutableContext
virtual void setResultCapture ( IResultCapture * resultCapture ) {
m_resultCapture = resultCapture ;
}
virtual void setRunner ( IRunner * runner ) {
m_runner = runner ;
}
virtual void setConfig ( Ptr < IConfig const > const & config ) {
m_config = config ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
friend IMutableContext & getCurrentMutableContext ( ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
private :
IGeneratorsForTest * findGeneratorsForCurrentTest ( ) {
std : : string testName = getResultCapture ( ) - > getCurrentTestName ( ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
std : : map < std : : string , IGeneratorsForTest * > : : const_iterator it =
2015-06-20 21:47:26 +08:00
m_generatorsByTestName . find ( testName ) ;
2015-02-06 05:45:21 +08:00
return it ! = m_generatorsByTestName . end ( )
? it - > second
2015-12-20 22:42:01 +08:00
: CATCH_NULL ;
2015-02-06 05:45:21 +08:00
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
IGeneratorsForTest & getGeneratorsForCurrentTest ( ) {
IGeneratorsForTest * generators = findGeneratorsForCurrentTest ( ) ;
if ( ! generators ) {
std : : string testName = getResultCapture ( ) - > getCurrentTestName ( ) ;
generators = createGeneratorsForTest ( ) ;
m_generatorsByTestName . insert ( std : : make_pair ( testName , generators ) ) ;
}
return * generators ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
private :
Ptr < IConfig const > m_config ;
IRunner * m_runner ;
IResultCapture * m_resultCapture ;
std : : map < std : : string , IGeneratorsForTest * > m_generatorsByTestName ;
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
namespace {
2015-12-20 22:42:01 +08:00
Context * currentContext = CATCH_NULL ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
IMutableContext & getCurrentMutableContext ( ) {
if ( ! currentContext )
currentContext = new Context ( ) ;
return * currentContext ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
IContext & getCurrentContext ( ) {
return getCurrentMutableContext ( ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
void cleanUpContext ( ) {
delete currentContext ;
2015-12-20 22:42:01 +08:00
currentContext = CATCH_NULL ;
2015-02-06 05:45:21 +08:00
}
2014-12-28 16:11:01 +08:00
}
// #included from: catch_console_colour_impl.hpp
# define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED
2015-06-20 21:47:26 +08:00
namespace Catch {
namespace {
2014-12-28 16:11:01 +08:00
2015-06-20 21:47:26 +08: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 ) /////////////////////////////////////////
2014-12-28 16:11:01 +08:00
# ifndef NOMINMAX
2015-02-06 05:45:21 +08:00
# define NOMINMAX
2014-12-28 16:11:01 +08:00
# endif
# ifdef __AFXDLL
2015-02-06 05:45:21 +08:00
# include <AfxWin.h>
2014-12-28 16:11:01 +08:00
# else
2015-02-06 05:45:21 +08:00
# include <windows.h>
2014-12-28 16:11:01 +08:00
# endif
2015-02-06 05:45:21 +08:00
namespace Catch {
namespace {
2014-12-28 16:11:01 +08:00
2015-06-20 21:47:26 +08:00
class Win32ColourImpl : public IColourImpl {
2015-02-06 05:45:21 +08:00
public :
Win32ColourImpl ( ) : stdoutHandle ( GetStdHandle ( STD_OUTPUT_HANDLE ) )
2014-12-28 16:11:01 +08:00
{
2015-02-06 05:45:21 +08:00
CONSOLE_SCREEN_BUFFER_INFO csbiInfo ;
GetConsoleScreenBufferInfo ( stdoutHandle , & csbiInfo ) ;
2015-12-20 22:42:01 +08:00
originalForegroundAttributes = csbiInfo . wAttributes & ~ ( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY ) ;
originalBackgroundAttributes = csbiInfo . wAttributes & ~ ( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY ) ;
2015-02-06 05:45:21 +08:00
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
virtual void use ( Colour : : Code _colourCode ) {
switch ( _colourCode ) {
2015-12-20 22:42:01 +08:00
case Colour : : None : return setTextAttribute ( originalForegroundAttributes ) ;
2015-02-06 05:45:21 +08: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 ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08: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 ) ;
case Colour : : BrightWhite : return setTextAttribute ( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ) ;
case Colour : : Bright : throw std : : logic_error ( " not a colour " ) ;
}
}
private :
void setTextAttribute ( WORD _textAttribute ) {
2015-12-20 22:42:01 +08:00
SetConsoleTextAttribute ( stdoutHandle , _textAttribute | originalBackgroundAttributes ) ;
2015-02-06 05:45:21 +08:00
}
HANDLE stdoutHandle ;
2015-12-20 22:42:01 +08:00
WORD originalForegroundAttributes ;
WORD originalBackgroundAttributes ;
2015-02-06 05:45:21 +08:00
} ;
2015-06-20 21:47:26 +08:00
IColourImpl * platformColourInstance ( ) {
2015-02-06 05:45:21 +08:00
static Win32ColourImpl s_instance ;
2016-06-20 00:25:43 +08:00
Ptr < IConfig const > config = getCurrentContext ( ) . getConfig ( ) ;
UseColour : : YesOrNo colourMode = config
? config - > useColour ( )
: UseColour : : Auto ;
if ( colourMode = = UseColour : : Auto )
colourMode = ! isDebuggerActive ( )
? UseColour : : Yes
: UseColour : : No ;
return colourMode = = UseColour : : Yes
? & s_instance
: NoColourImpl : : instance ( ) ;
2015-02-06 05:45:21 +08:00
}
2014-12-28 16:11:01 +08:00
} // end anon namespace
} // end namespace Catch
2015-06-20 21:47:26 +08:00
# elif defined( CATCH_CONFIG_COLOUR_ANSI ) //////////////////////////////////////
2014-12-28 16:11:01 +08:00
# include <unistd.h>
2015-02-06 05:45:21 +08:00
namespace Catch {
namespace {
// use POSIX/ ANSI console terminal codes
// Thanks to Adam Strzelecki for original contribution
// (http://github.com/nanoant)
// https://github.com/philsquared/Catch/pull/131
2015-06-20 21:47:26 +08:00
class PosixColourImpl : public IColourImpl {
2015-02-06 05:45:21 +08: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 " ) ;
2017-01-12 05:23:02 +08:00
case Colour : : Blue : return setColour ( " [0;34m " ) ;
2015-02-06 05:45:21 +08:00
case Colour : : Cyan : return setColour ( " [0;36m " ) ;
case Colour : : Yellow : return setColour ( " [0;33m " ) ;
case Colour : : Grey : return setColour ( " [1;30m " ) ;
case Colour : : LightGrey : return setColour ( " [0;37m " ) ;
case Colour : : BrightRed : return setColour ( " [1;31m " ) ;
case Colour : : BrightGreen : return setColour ( " [1;32m " ) ;
case Colour : : BrightWhite : return setColour ( " [1;37m " ) ;
case Colour : : Bright : throw std : : logic_error ( " not a colour " ) ;
}
}
2015-06-20 21:47:26 +08:00
static IColourImpl * instance ( ) {
static PosixColourImpl s_instance ;
return & s_instance ;
}
2015-02-06 05:45:21 +08:00
private :
void setColour ( const char * _escapeCode ) {
2015-06-20 21:47:26 +08:00
Catch : : cout ( ) < < ' \033 ' < < _escapeCode ;
2015-02-06 05:45:21 +08:00
}
} ;
2014-12-28 16:11:01 +08:00
2015-06-20 21:47:26 +08:00
IColourImpl * platformColourInstance ( ) {
Ptr < IConfig const > config = getCurrentContext ( ) . getConfig ( ) ;
2016-06-20 00:25:43 +08:00
UseColour : : YesOrNo colourMode = config
? config - > useColour ( )
: UseColour : : Auto ;
if ( colourMode = = UseColour : : Auto )
colourMode = ( ! isDebuggerActive ( ) & & isatty ( STDOUT_FILENO ) )
? UseColour : : Yes
: UseColour : : No ;
return colourMode = = UseColour : : Yes
2015-06-20 21:47:26 +08:00
? PosixColourImpl : : instance ( )
: NoColourImpl : : instance ( ) ;
2015-02-06 05:45:21 +08:00
}
2014-12-28 16:11:01 +08:00
} // end anon namespace
} // end namespace Catch
2015-06-20 21:47:26 +08:00
# else // not Windows or ANSI ///////////////////////////////////////////////
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-06-20 21:47:26 +08:00
static IColourImpl * platformColourInstance ( ) { return NoColourImpl : : instance ( ) ; }
2014-12-28 16:11:01 +08:00
2015-06-20 21:47:26 +08:00
} // end namespace Catch
# endif // Windows/ ANSI/ None
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08: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 ) ; }
2014-12-28 16:11:01 +08:00
2015-06-20 21:47:26 +08:00
void Colour : : use ( Code _colourCode ) {
2016-06-20 00:25:43 +08:00
static IColourImpl * impl = platformColourInstance ( ) ;
2015-06-20 21:47:26 +08:00
impl - > use ( _colourCode ) ;
2015-02-06 05:45:21 +08:00
}
2014-12-28 16:11:01 +08:00
} // end namespace Catch
// #included from: catch_generators_impl.hpp
# define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED
# include <vector>
# include <string>
# include <map>
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
struct GeneratorInfo : IGeneratorInfo {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
GeneratorInfo ( std : : size_t size )
2014-12-28 16:11:01 +08:00
: m_size ( size ) ,
m_currentIndex ( 0 )
2015-02-06 05:45:21 +08:00
{ }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
bool moveNext ( ) {
if ( + + m_currentIndex = = m_size ) {
m_currentIndex = 0 ;
return false ;
}
return true ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
std : : size_t getCurrentIndex ( ) const {
return m_currentIndex ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
std : : size_t m_size ;
std : : size_t m_currentIndex ;
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
///////////////////////////////////////////////////////////////////////////
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
class GeneratorsForTest : public IGeneratorsForTest {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
public :
~ GeneratorsForTest ( ) {
deleteAll ( m_generatorsInOrder ) ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
IGeneratorInfo & getGeneratorInfo ( std : : string const & fileInfo , std : : size_t size ) {
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 ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
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 ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
return false ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
private :
std : : map < std : : string , IGeneratorInfo * > m_generatorsByName ;
std : : vector < IGeneratorInfo * > m_generatorsInOrder ;
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
IGeneratorsForTest * createGeneratorsForTest ( )
{
return new GeneratorsForTest ( ) ;
}
2014-12-28 16:11:01 +08:00
} // end namespace Catch
// #included from: catch_assertionresult.hpp
# define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
AssertionInfo : : AssertionInfo ( std : : string const & _macroName ,
SourceLineInfo const & _lineInfo ,
std : : string const & _capturedExpression ,
ResultDisposition : : Flags _resultDisposition )
2014-12-28 16:11:01 +08:00
: macroName ( _macroName ) ,
lineInfo ( _lineInfo ) ,
capturedExpression ( _capturedExpression ) ,
resultDisposition ( _resultDisposition )
2015-02-06 05:45:21 +08:00
{ }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
AssertionResult : : AssertionResult ( ) { }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
AssertionResult : : AssertionResult ( AssertionInfo const & info , AssertionResultData const & data )
2014-12-28 16:11:01 +08:00
: m_info ( info ) ,
m_resultData ( data )
2015-02-06 05:45:21 +08:00
{ }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
AssertionResult : : ~ AssertionResult ( ) { }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
// Result was a success
bool AssertionResult : : succeeded ( ) const {
return Catch : : isOk ( m_resultData . resultType ) ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
// Result was a success, or failure is suppressed
bool AssertionResult : : isOk ( ) const {
return Catch : : isOk ( m_resultData . resultType ) | | shouldSuppressFailure ( m_info . resultDisposition ) ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
ResultWas : : OfType AssertionResult : : getResultType ( ) const {
return m_resultData . resultType ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
bool AssertionResult : : hasExpression ( ) const {
return ! m_info . capturedExpression . empty ( ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
bool AssertionResult : : hasMessage ( ) const {
return ! m_resultData . message . empty ( ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
std : : string AssertionResult : : getExpression ( ) const {
if ( isFalseTest ( m_info . resultDisposition ) )
return " ! " + m_info . capturedExpression ;
else
return m_info . capturedExpression ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
std : : string AssertionResult : : getExpressionInMacro ( ) const {
if ( m_info . macroName . empty ( ) )
return m_info . capturedExpression ;
else
return m_info . macroName + " ( " + m_info . capturedExpression + " ) " ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
bool AssertionResult : : hasExpandedExpression ( ) const {
return hasExpression ( ) & & getExpandedExpression ( ) ! = getExpression ( ) ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
std : : string AssertionResult : : getExpandedExpression ( ) const {
return m_resultData . reconstructedExpression ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
std : : string AssertionResult : : getMessage ( ) const {
return m_resultData . message ;
}
SourceLineInfo AssertionResult : : getSourceInfo ( ) const {
return m_info . lineInfo ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
std : : string AssertionResult : : getTestMacroName ( ) const {
return m_info . macroName ;
}
2014-12-28 16:11:01 +08:00
} // end namespace Catch
// #included from: catch_test_case_info.hpp
# define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
inline TestCaseInfo : : SpecialProperties parseSpecialTag ( std : : string const & tag ) {
2015-06-20 21:47:26 +08:00
if ( startsWith ( tag , " . " ) | |
2014-12-28 16:11:01 +08:00
tag = = " hide " | |
tag = = " !hide " )
2015-02-06 05:45:21 +08:00
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-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
inline bool isReservedTag ( std : : string const & tag ) {
return parseSpecialTag ( tag ) = = TestCaseInfo : : None & & tag . size ( ) > 0 & & ! isalnum ( tag [ 0 ] ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
inline void enforceNotReservedTag ( std : : string const & tag , SourceLineInfo const & _lineInfo ) {
if ( isReservedTag ( tag ) ) {
{
Colour colourGuard ( Colour : : Red ) ;
2015-06-20 21:47:26 +08:00
Catch : : cerr ( )
2014-12-28 16:11:01 +08:00
< < " Tag name [ " < < tag < < " ] not allowed. \n "
< < " Tag names starting with non alpha-numeric characters are reserved \n " ;
2015-02-06 05:45:21 +08:00
}
{
Colour colourGuard ( Colour : : FileName ) ;
2015-06-20 21:47:26 +08:00
Catch : : cerr ( ) < < _lineInfo < < std : : endl ;
2015-02-06 05:45:21 +08:00
}
exit ( 1 ) ;
2014-12-28 16:11:01 +08:00
}
}
2015-02-06 05:45:21 +08:00
TestCase makeTestCase ( ITestCase * _testCase ,
std : : string const & _className ,
std : : string const & _name ,
std : : string const & _descOrTags ,
SourceLineInfo const & _lineInfo )
2014-12-28 16:11:01 +08:00
{
2015-02-06 05:45:21 +08:00
bool isHidden ( startsWith ( _name , " ./ " ) ) ; // Legacy support
// Parse out tags
std : : set < std : : string > tags ;
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-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
else {
if ( c = = ' ] ' ) {
2015-06-20 21:47:26 +08:00
TestCaseInfo : : SpecialProperties prop = parseSpecialTag ( tag ) ;
if ( prop = = TestCaseInfo : : IsHidden )
2015-02-06 05:45:21 +08:00
isHidden = true ;
2015-06-20 21:47:26 +08:00
else if ( prop = = TestCaseInfo : : None )
enforceNotReservedTag ( tag , _lineInfo ) ;
tags . insert ( tag ) ;
2015-02-06 05:45:21 +08:00
tag . clear ( ) ;
2015-06-20 21:47:26 +08:00
inTag = false ;
2014-12-28 16:11:01 +08:00
}
else
2015-02-06 05:45:21 +08:00
tag + = c ;
2014-12-28 16:11:01 +08:00
}
}
2015-02-06 05:45:21 +08:00
if ( isHidden ) {
tags . insert ( " hide " ) ;
tags . insert ( " . " ) ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
TestCaseInfo info ( _name , _className , desc , tags , _lineInfo ) ;
return TestCase ( _testCase , info ) ;
}
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08: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 ( ) ;
}
2015-02-06 05:45:21 +08:00
TestCaseInfo : : TestCaseInfo ( std : : string const & _name ,
std : : string const & _className ,
std : : string const & _description ,
std : : set < std : : string > const & _tags ,
SourceLineInfo const & _lineInfo )
2014-12-28 16:11:01 +08:00
: name ( _name ) ,
className ( _className ) ,
description ( _description ) ,
lineInfo ( _lineInfo ) ,
properties ( None )
{
2015-12-20 22:42:01 +08:00
setTags ( * this , _tags ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
TestCaseInfo : : TestCaseInfo ( TestCaseInfo const & other )
2014-12-28 16:11:01 +08:00
: name ( other . name ) ,
className ( other . className ) ,
description ( other . description ) ,
tags ( other . tags ) ,
lcaseTags ( other . lcaseTags ) ,
tagsAsString ( other . tagsAsString ) ,
lineInfo ( other . lineInfo ) ,
properties ( other . properties )
2015-02-06 05:45:21 +08:00
{ }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08: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 ;
}
TestCase : : TestCase ( ITestCase * testCase , TestCaseInfo const & info ) : TestCaseInfo ( info ) , test ( testCase ) { }
TestCase : : TestCase ( TestCase const & other )
2014-12-28 16:11:01 +08:00
: TestCaseInfo ( other ) ,
test ( other . test )
2015-02-06 05:45:21 +08:00
{ }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
TestCase TestCase : : withName ( std : : string const & _newName ) const {
TestCase other ( * this ) ;
other . name = _newName ;
return other ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08: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 ) ;
std : : swap ( TestCaseInfo : : properties , static_cast < TestCaseInfo & > ( other ) . properties ) ;
std : : swap ( lineInfo , other . lineInfo ) ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
void TestCase : : invoke ( ) const {
test - > invoke ( ) ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
bool TestCase : : operator = = ( TestCase const & other ) const {
return test . get ( ) = = other . test . get ( ) & &
name = = other . name & &
className = = other . className ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
bool TestCase : : operator < ( TestCase const & other ) const {
return name < other . name ;
}
TestCase & TestCase : : operator = ( TestCase const & other ) {
TestCase temp ( other ) ;
swap ( temp ) ;
return * this ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
TestCaseInfo const & TestCase : : getTestCaseInfo ( ) const
{
return * this ;
}
2014-12-28 16:11:01 +08:00
} // end namespace Catch
// #included from: catch_version.hpp
# define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-07-26 16:41:38 +08: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 ;
}
2017-01-12 05:23:02 +08:00
Version libraryVersion ( 1 , 6 , 0 , " " , 0 ) ;
2015-07-26 16:41:38 +08:00
2014-12-28 16:11:01 +08:00
}
// #included from: catch_message.hpp
# define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
MessageInfo : : MessageInfo ( std : : string const & _macroName ,
SourceLineInfo const & _lineInfo ,
ResultWas : : OfType _type )
2014-12-28 16:11:01 +08:00
: macroName ( _macroName ) ,
lineInfo ( _lineInfo ) ,
type ( _type ) ,
sequence ( + + globalCount )
2015-02-06 05:45:21 +08:00
{ }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
// This may need protecting if threading support is added
unsigned int MessageInfo : : globalCount = 0 ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
////////////////////////////////////////////////////////////////////////////
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
ScopedMessage : : ScopedMessage ( MessageBuilder const & builder )
2014-12-28 16:11:01 +08:00
: m_info ( builder . m_info )
2015-02-06 05:45:21 +08:00
{
m_info . message = builder . m_stream . str ( ) ;
getResultCapture ( ) . pushScopedMessage ( m_info ) ;
}
ScopedMessage : : ScopedMessage ( ScopedMessage const & other )
2014-12-28 16:11:01 +08:00
: m_info ( other . m_info )
2015-02-06 05:45:21 +08:00
{ }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
ScopedMessage : : ~ ScopedMessage ( ) {
getResultCapture ( ) . popScopedMessage ( m_info ) ;
}
2014-12-28 16:11:01 +08:00
} // end namespace Catch
// #included from: catch_legacy_reporter_adapter.hpp
# 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
{
2015-02-06 05:45:21 +08: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 ;
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
class LegacyReporterAdapter : public SharedImpl < IStreamingReporter >
{
public :
LegacyReporterAdapter ( Ptr < IReporter > const & legacyReporter ) ;
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 & ) ;
virtual bool assertionEnded ( AssertionStats const & assertionStats ) ;
virtual void sectionEnded ( SectionStats const & sectionStats ) ;
virtual void testCaseEnded ( TestCaseStats const & testCaseStats ) ;
virtual void testGroupEnded ( TestGroupStats const & testGroupStats ) ;
virtual void testRunEnded ( TestRunStats const & testRunStats ) ;
2015-06-20 21:47:26 +08:00
virtual void skipTest ( TestCaseInfo const & ) ;
2015-02-06 05:45:21 +08:00
private :
Ptr < IReporter > m_legacyReporter ;
} ;
2014-12-28 16:11:01 +08:00
}
namespace Catch
{
2015-02-06 05:45:21 +08:00
LegacyReporterAdapter : : LegacyReporterAdapter ( Ptr < IReporter > const & legacyReporter )
2014-12-28 16:11:01 +08:00
: m_legacyReporter ( legacyReporter )
2015-02-06 05:45:21 +08:00
{ }
LegacyReporterAdapter : : ~ LegacyReporterAdapter ( ) { }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
ReporterPreferences LegacyReporterAdapter : : getPreferences ( ) const {
ReporterPreferences prefs ;
prefs . shouldRedirectStdOut = m_legacyReporter - > shouldRedirectStdout ( ) ;
return prefs ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
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
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
bool LegacyReporterAdapter : : assertionEnded ( AssertionStats const & assertionStats ) {
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 ) {
ResultBuilder rb ( it - > macroName . c_str ( ) , it - > lineInfo , " " , ResultDisposition : : Normal ) ;
rb < < it - > message ;
rb . setResultType ( ResultWas : : Info ) ;
AssertionResult result = rb . build ( ) ;
m_legacyReporter - > Result ( result ) ;
}
2014-12-28 16:11:01 +08:00
}
}
2015-02-06 05:45:21 +08:00
m_legacyReporter - > Result ( assertionStats . assertionResult ) ;
return true ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
void LegacyReporterAdapter : : sectionEnded ( SectionStats const & sectionStats ) {
if ( sectionStats . missingAssertions )
m_legacyReporter - > NoAssertionsInSection ( sectionStats . sectionInfo . name ) ;
m_legacyReporter - > EndSection ( sectionStats . sectionInfo . name , sectionStats . assertions ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
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-28 16:11:01 +08:00
}
2015-06-20 21:47:26 +08:00
void LegacyReporterAdapter : : skipTest ( TestCaseInfo const & ) {
}
2014-12-28 16:11:01 +08:00
}
// #included from: catch_timer.hpp
# ifdef __clang__
2015-02-06 05:45:21 +08:00
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wc++11-long-long"
2014-12-28 16:11:01 +08:00
# endif
# ifdef CATCH_PLATFORM_WINDOWS
2015-02-06 05:45:21 +08:00
# include <windows.h>
2014-12-28 16:11:01 +08:00
# else
2015-02-06 05:45:21 +08:00
# include <sys/time.h>
2014-12-28 16:11:01 +08:00
# endif
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
namespace {
2014-12-28 16:11:01 +08:00
# ifdef CATCH_PLATFORM_WINDOWS
2015-02-06 05:45:21 +08:00
uint64_t getCurrentTicks ( ) {
static uint64_t hz = 0 , hzo = 0 ;
if ( ! hz ) {
2015-06-20 21:47:26 +08:00
QueryPerformanceFrequency ( reinterpret_cast < LARGE_INTEGER * > ( & hz ) ) ;
QueryPerformanceCounter ( reinterpret_cast < LARGE_INTEGER * > ( & hzo ) ) ;
2015-02-06 05:45:21 +08:00
}
uint64_t t ;
2015-06-20 21:47:26 +08:00
QueryPerformanceCounter ( reinterpret_cast < LARGE_INTEGER * > ( & t ) ) ;
2015-02-06 05:45:21 +08:00
return ( ( t - hzo ) * 1000000 ) / hz ;
}
2014-12-28 16:11:01 +08:00
# else
2015-02-06 05:45:21 +08:00
uint64_t getCurrentTicks ( ) {
timeval t ;
2015-12-20 22:42:01 +08:00
gettimeofday ( & t , CATCH_NULL ) ;
2015-02-06 05:45:21 +08:00
return static_cast < uint64_t > ( t . tv_sec ) * 1000000ull + static_cast < uint64_t > ( t . tv_usec ) ;
}
2014-12-28 16:11:01 +08:00
# endif
2015-02-06 05:45:21 +08:00
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
void Timer : : start ( ) {
m_ticks = getCurrentTicks ( ) ;
}
2015-06-20 21:47:26 +08:00
unsigned int Timer : : getElapsedMicroseconds ( ) const {
2015-02-06 05:45:21 +08:00
return static_cast < unsigned int > ( getCurrentTicks ( ) - m_ticks ) ;
}
unsigned int Timer : : getElapsedMilliseconds ( ) const {
2015-06-20 21:47:26 +08:00
return static_cast < unsigned int > ( getElapsedMicroseconds ( ) / 1000 ) ;
2015-02-06 05:45:21 +08:00
}
double Timer : : getElapsedSeconds ( ) const {
2015-06-20 21:47:26 +08:00
return getElapsedMicroseconds ( ) / 1000000.0 ;
2015-02-06 05:45:21 +08:00
}
2014-12-28 16:11:01 +08:00
} // namespace Catch
# ifdef __clang__
2015-02-06 05:45:21 +08:00
# pragma clang diagnostic pop
2014-12-28 16:11:01 +08:00
# endif
// #included from: catch_common.hpp
# define TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
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 ;
}
2016-11-17 02:15:54 +08:00
char toLowerCh ( char c ) {
return static_cast < char > ( : : tolower ( c ) ) ;
}
2015-02-06 05:45:21 +08:00
void toLowerInPlace ( std : : string & s ) {
2016-11-17 02:15:54 +08:00
std : : transform ( s . begin ( ) , s . end ( ) , s . begin ( ) , toLowerCh ) ;
2015-02-06 05:45:21 +08:00
}
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 ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
return start ! = std : : string : : npos ? str . substr ( start , 1 + end - start ) : " " ;
}
2014-12-28 16:11:01 +08:00
2015-06-20 21:47:26 +08: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 ;
}
2015-02-06 05:45:21 +08:00
pluralise : : pluralise ( std : : size_t count , std : : string const & label )
2014-12-28 16:11:01 +08:00
: m_count ( count ) ,
m_label ( label )
2015-02-06 05:45:21 +08:00
{ }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
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 ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
SourceLineInfo : : SourceLineInfo ( ) : line ( 0 ) { }
SourceLineInfo : : SourceLineInfo ( char const * _file , std : : size_t _line )
2014-12-28 16:11:01 +08:00
: file ( _file ) ,
line ( _line )
2015-02-06 05:45:21 +08:00
{ }
SourceLineInfo : : SourceLineInfo ( SourceLineInfo const & other )
2014-12-28 16:11:01 +08:00
: file ( other . file ) ,
line ( other . line )
2015-02-06 05:45:21 +08:00
{ }
bool SourceLineInfo : : empty ( ) const {
return file . empty ( ) ;
}
bool SourceLineInfo : : operator = = ( SourceLineInfo const & other ) const {
return line = = other . line & & file = = other . file ;
}
2015-06-20 21:47:26 +08:00
bool SourceLineInfo : : operator < ( SourceLineInfo const & other ) const {
return line < other . line | | ( line = = other . line & & file < other . file ) ;
}
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
void seedRng ( IConfig const & config ) {
if ( config . rngSeed ( ) ! = 0 )
std : : srand ( config . rngSeed ( ) ) ;
}
unsigned int rngSeed ( ) {
return getCurrentContext ( ) . getConfig ( ) - > rngSeed ( ) ;
}
2015-02-06 05:45:21 +08:00
std : : ostream & operator < < ( std : : ostream & os , SourceLineInfo const & info ) {
2014-12-28 16:11:01 +08:00
# ifndef __GNUG__
2015-02-06 05:45:21 +08:00
os < < info . file < < " ( " < < info . line < < " ) " ;
2014-12-28 16:11:01 +08:00
# else
2015-02-06 05:45:21 +08:00
os < < info . file < < " : " < < info . line ;
2014-12-28 16:11:01 +08:00
# endif
2015-02-06 05:45:21 +08:00
return os ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
void throwLogicError ( std : : string const & message , SourceLineInfo const & locationInfo ) {
std : : ostringstream oss ;
oss < < locationInfo < < " : Internal Catch error: ' " < < message < < " ' " ;
if ( alwaysTrue ( ) )
throw std : : logic_error ( oss . str ( ) ) ;
2014-12-28 16:11:01 +08:00
}
}
// #included from: catch_section.hpp
# define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
SectionInfo : : SectionInfo
( SourceLineInfo const & _lineInfo ,
std : : string const & _name ,
std : : string const & _description )
2014-12-28 16:11:01 +08:00
: name ( _name ) ,
description ( _description ) ,
lineInfo ( _lineInfo )
2015-02-06 05:45:21 +08:00
{ }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
Section : : Section ( SectionInfo const & info )
2014-12-28 16:11:01 +08:00
: m_info ( info ) ,
m_sectionIncluded ( getResultCapture ( ) . sectionStarted ( m_info , m_assertions ) )
{
2015-02-06 05:45:21 +08:00
m_timer . start ( ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
Section : : ~ Section ( ) {
2015-12-20 22:42:01 +08:00
if ( m_sectionIncluded ) {
SectionEndInfo endInfo ( m_info , m_assertions , m_timer . getElapsedSeconds ( ) ) ;
if ( std : : uncaught_exception ( ) )
getResultCapture ( ) . sectionEndedEarly ( endInfo ) ;
else
getResultCapture ( ) . sectionEnded ( endInfo ) ;
}
2015-02-06 05:45:21 +08:00
}
// This indicates whether the section should be executed or not
Section : : operator bool ( ) const {
return m_sectionIncluded ;
}
2014-12-28 16:11:01 +08:00
} // end namespace Catch
// #included from: catch_debugger.hpp
# define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED
# include <iostream>
# ifdef CATCH_PLATFORM_MAC
2015-02-06 05:45:21 +08:00
# include <assert.h>
# include <stdbool.h>
# include <sys/types.h>
# include <unistd.h>
# include <sys/sysctl.h>
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
// The following function is taken directly from the following technical note:
// http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
// Returns true if the current process is being debugged (either
// running under the debugger or has a debugger attached post facto).
bool isDebuggerActive ( ) {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
int mib [ 4 ] ;
struct kinfo_proc info ;
size_t size ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
// Initialize the flags so that, if sysctl fails for some bizarre
// reason, we get a predictable result.
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
info . kp_proc . p_flag = 0 ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
// Initialize mib, which tells sysctl the info we want, in this case
// we're looking for information about a specific process ID.
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
mib [ 0 ] = CTL_KERN ;
mib [ 1 ] = KERN_PROC ;
mib [ 2 ] = KERN_PROC_PID ;
mib [ 3 ] = getpid ( ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
// Call sysctl.
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
size = sizeof ( info ) ;
2015-12-20 22:42:01 +08:00
if ( sysctl ( mib , sizeof ( mib ) / sizeof ( * mib ) , & info , & size , CATCH_NULL , 0 ) ! = 0 ) {
2015-06-20 21:47:26 +08:00
Catch : : cerr ( ) < < " \n ** Call to sysctl failed - unable to determine if debugger is active ** \n " < < std : : endl ;
2015-02-06 05:45:21 +08:00
return false ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
// We're being debugged if the P_TRACED flag is set.
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
return ( ( info . kp_proc . p_flag & P_TRACED ) ! = 0 ) ;
}
} // namespace Catch
2014-12-28 16:11:01 +08:00
# elif defined(_MSC_VER)
2015-02-06 05:45:21 +08:00
extern " C " __declspec ( dllimport ) int __stdcall IsDebuggerPresent ( ) ;
namespace Catch {
bool isDebuggerActive ( ) {
return IsDebuggerPresent ( ) ! = 0 ;
}
}
2014-12-28 16:11:01 +08:00
# elif defined(__MINGW32__)
2015-02-06 05:45:21 +08:00
extern " C " __declspec ( dllimport ) int __stdcall IsDebuggerPresent ( ) ;
namespace Catch {
bool isDebuggerActive ( ) {
return IsDebuggerPresent ( ) ! = 0 ;
}
}
2014-12-28 16:11:01 +08:00
# else
2015-02-06 05:45:21 +08:00
namespace Catch {
inline bool isDebuggerActive ( ) { return false ; }
}
2014-12-28 16:11:01 +08:00
# endif // Platform
# ifdef CATCH_PLATFORM_WINDOWS
2015-02-06 05:45:21 +08:00
extern " C " __declspec ( dllimport ) void __stdcall OutputDebugStringA ( const char * ) ;
namespace Catch {
void writeToDebugConsole ( std : : string const & text ) {
: : OutputDebugStringA ( text . c_str ( ) ) ;
}
}
2014-12-28 16:11:01 +08:00
# else
2015-02-06 05:45:21 +08:00
namespace Catch {
void writeToDebugConsole ( std : : string const & text ) {
// !TBD: Need a version for Mac/ XCode and other IDEs
2015-06-20 21:47:26 +08:00
Catch : : cout ( ) < < text ;
2015-02-06 05:45:21 +08:00
}
}
2014-12-28 16:11:01 +08:00
# endif // Platform
// #included from: catch_tostring.hpp
# define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
namespace Detail {
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
const std : : string unprintableString = " {?} " ;
2015-06-20 21:47:26 +08:00
2015-02-06 05:45:21 +08:00
namespace {
2015-12-20 22:42:01 +08:00
const int hexThreshold = 255 ;
2015-02-06 05:45:21 +08:00
struct Endianness {
enum Arch { Big , Little } ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
static Arch which ( ) {
union _ {
int asInt ;
char asChar [ sizeof ( int ) ] ;
} u ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
u . asInt = 1 ;
return ( u . asChar [ sizeof ( int ) - 1 ] = = 1 ) ? Big : Little ;
}
} ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
std : : string rawMemoryToString ( const void * object , std : : size_t size )
2014-12-28 16:11:01 +08:00
{
2015-02-06 05:45:21 +08:00
// 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 ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
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-12-28 16:11:01 +08:00
}
}
2015-02-06 05:45:21 +08:00
std : : string toString ( std : : string const & value ) {
2014-12-28 16:11:01 +08:00
std : : string s = value ;
2015-02-06 05:45:21 +08:00
if ( getCurrentContext ( ) . getConfig ( ) - > showInvisibles ( ) ) {
for ( size_t i = 0 ; i < s . size ( ) ; + + i ) {
2014-12-28 16:11:01 +08:00
std : : string subs ;
2015-02-06 05:45:21 +08:00
switch ( s [ i ] ) {
case ' \n ' : subs = " \\ n " ; break ;
case ' \t ' : subs = " \\ t " ; break ;
default : break ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
if ( ! subs . empty ( ) ) {
s = s . substr ( 0 , i ) + subs + s . substr ( i + 1 ) ;
2014-12-28 16:11:01 +08:00
+ + i ;
}
}
}
return " \" " + s + " \" " ;
}
2015-02-06 05:45:21 +08:00
std : : string toString ( std : : wstring const & value ) {
2014-12-28 16:11:01 +08:00
std : : string s ;
s . reserve ( value . size ( ) ) ;
2015-02-06 05:45:21 +08:00
for ( size_t i = 0 ; i < value . size ( ) ; + + i )
2014-12-28 16:11:01 +08:00
s + = value [ i ] < = 0xff ? static_cast < char > ( value [ i ] ) : ' ? ' ;
2015-06-20 21:47:26 +08:00
return Catch : : toString ( s ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
std : : string toString ( const char * const value ) {
2014-12-28 16:11:01 +08:00
return value ? Catch : : toString ( std : : string ( value ) ) : std : : string ( " {null string} " ) ;
}
2015-02-06 05:45:21 +08:00
std : : string toString ( char * const value ) {
2014-12-28 16:11:01 +08:00
return Catch : : toString ( static_cast < const char * > ( value ) ) ;
}
std : : string toString ( const wchar_t * const value )
{
2015-02-06 05:45:21 +08:00
return value ? Catch : : toString ( std : : wstring ( value ) ) : std : : string ( " {null string} " ) ;
2014-12-28 16:11:01 +08:00
}
std : : string toString ( wchar_t * const value )
{
2015-02-06 05:45:21 +08:00
return Catch : : toString ( static_cast < const wchar_t * > ( value ) ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
std : : string toString ( int value ) {
2014-12-28 16:11:01 +08:00
std : : ostringstream oss ;
oss < < value ;
2015-12-20 22:42:01 +08:00
if ( value > Detail : : hexThreshold )
2015-06-20 21:47:26 +08:00
oss < < " (0x " < < std : : hex < < value < < " ) " ;
2014-12-28 16:11:01 +08:00
return oss . str ( ) ;
}
2015-02-06 05:45:21 +08:00
std : : string toString ( unsigned long value ) {
2014-12-28 16:11:01 +08:00
std : : ostringstream oss ;
2015-06-20 21:47:26 +08:00
oss < < value ;
2015-12-20 22:42:01 +08:00
if ( value > Detail : : hexThreshold )
2015-06-20 21:47:26 +08:00
oss < < " (0x " < < std : : hex < < value < < " ) " ;
2014-12-28 16:11:01 +08:00
return oss . str ( ) ;
}
2015-02-06 05:45:21 +08:00
std : : string toString ( unsigned int value ) {
2015-06-20 21:47:26 +08:00
return Catch : : toString ( static_cast < unsigned long > ( value ) ) ;
2014-12-28 16:11:01 +08:00
}
template < typename T >
2015-02-06 05:45:21 +08:00
std : : string fpToString ( T value , int precision ) {
2014-12-28 16:11:01 +08:00
std : : ostringstream oss ;
oss < < std : : setprecision ( precision )
< < std : : fixed
< < value ;
std : : string d = oss . str ( ) ;
std : : size_t i = d . find_last_not_of ( ' 0 ' ) ;
2015-02-06 05:45:21 +08:00
if ( i ! = std : : string : : npos & & i ! = d . size ( ) - 1 ) {
if ( d [ i ] = = ' . ' )
2014-12-28 16:11:01 +08:00
i + + ;
2015-02-06 05:45:21 +08:00
d = d . substr ( 0 , i + 1 ) ;
2014-12-28 16:11:01 +08:00
}
return d ;
}
2015-02-06 05:45:21 +08:00
std : : string toString ( const double value ) {
2014-12-28 16:11:01 +08:00
return fpToString ( value , 10 ) ;
}
2015-02-06 05:45:21 +08:00
std : : string toString ( const float value ) {
2014-12-28 16:11:01 +08:00
return fpToString ( value , 5 ) + " f " ;
}
2015-02-06 05:45:21 +08:00
std : : string toString ( bool value ) {
2014-12-28 16:11:01 +08:00
return value ? " true " : " false " ;
}
2015-02-06 05:45:21 +08:00
std : : string toString ( char value ) {
2014-12-28 16:11:01 +08:00
return value < ' '
2015-02-06 05:45:21 +08:00
? toString ( static_cast < unsigned int > ( value ) )
: Detail : : makeString ( value ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
std : : string toString ( signed char value ) {
2014-12-28 16:11:01 +08:00
return toString ( static_cast < char > ( value ) ) ;
}
2015-02-06 05:45:21 +08:00
std : : string toString ( unsigned char value ) {
2014-12-28 16:11:01 +08:00
return toString ( static_cast < char > ( value ) ) ;
}
2015-12-20 22:42:01 +08: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-12-28 16:11:01 +08:00
# ifdef CATCH_CONFIG_CPP11_NULLPTR
2015-02-06 05:45:21 +08:00
std : : string toString ( std : : nullptr_t ) {
2014-12-28 16:11:01 +08:00
return " nullptr " ;
}
# endif
# ifdef __OBJC__
2015-02-06 05:45:21 +08:00
std : : string toString ( NSString const * const & nsstring ) {
if ( ! nsstring )
return " nil " ;
return " @ " + toString ( [ nsstring UTF8String ] ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
std : : string toString ( NSString * CATCH_ARC_STRONG const & nsstring ) {
if ( ! nsstring )
return " nil " ;
return " @ " + toString ( [ nsstring UTF8String ] ) ;
}
std : : string toString ( NSObject * const & nsObject ) {
return toString ( [ nsObject description ] ) ;
2014-12-28 16:11:01 +08:00
}
# endif
} // end namespace Catch
// #included from: catch_result_builder.hpp
# define TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
std : : string capturedExpressionWithSecondArgument ( std : : string const & capturedExpression , std : : string const & secondArg ) {
return secondArg . empty ( ) | | secondArg = = " \" \" "
? capturedExpression
: capturedExpression + " , " + secondArg ;
}
2015-02-06 05:45:21 +08:00
ResultBuilder : : ResultBuilder ( char const * macroName ,
SourceLineInfo const & lineInfo ,
char const * capturedExpression ,
2015-12-20 22:42:01 +08:00
ResultDisposition : : Flags resultDisposition ,
char const * secondArg )
: m_assertionInfo ( macroName , lineInfo , capturedExpressionWithSecondArgument ( capturedExpression , secondArg ) , resultDisposition ) ,
2014-12-28 16:11:01 +08:00
m_shouldDebugBreak ( false ) ,
m_shouldThrow ( false )
2015-02-06 05:45:21 +08:00
{ }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
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 ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
void ResultBuilder : : endExpression ( ) {
m_exprComponents . testFalse = isFalseTest ( m_assertionInfo . resultDisposition ) ;
captureExpression ( ) ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
void ResultBuilder : : useActiveException ( ResultDisposition : : Flags resultDisposition ) {
m_assertionInfo . resultDisposition = resultDisposition ;
m_stream . oss < < Catch : : translateActiveException ( ) ;
captureResult ( ResultWas : : ThrewException ) ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
void ResultBuilder : : captureResult ( ResultWas : : OfType resultType ) {
setResultType ( resultType ) ;
captureExpression ( ) ;
}
2015-12-20 22:42:01 +08:00
void ResultBuilder : : captureExpectedException ( std : : string const & expectedMessage ) {
if ( expectedMessage . empty ( ) )
captureExpectedException ( Matchers : : Impl : : Generic : : AllOf < std : : string > ( ) ) ;
else
captureExpectedException ( Matchers : : Equals ( expectedMessage ) ) ;
}
void ResultBuilder : : captureExpectedException ( Matchers : : Impl : : Matcher < std : : string > const & matcher ) {
assert ( m_exprComponents . testFalse = = false ) ;
AssertionResultData data = m_data ;
data . resultType = ResultWas : : Ok ;
data . reconstructedExpression = m_assertionInfo . capturedExpression ;
std : : string actualMessage = Catch : : translateActiveException ( ) ;
if ( ! matcher . match ( actualMessage ) ) {
data . resultType = ResultWas : : ExpressionFailed ;
data . reconstructedExpression = actualMessage ;
}
AssertionResult result ( m_assertionInfo , data ) ;
handleResult ( result ) ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
void ResultBuilder : : captureExpression ( ) {
AssertionResult result = build ( ) ;
2015-12-20 22:42:01 +08:00
handleResult ( result ) ;
}
void ResultBuilder : : handleResult ( AssertionResult const & result )
{
2015-02-06 05:45:21 +08:00
getResultCapture ( ) . assertionEnded ( result ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
if ( ! result . isOk ( ) ) {
if ( getCurrentContext ( ) . getConfig ( ) - > shouldDebugBreak ( ) )
m_shouldDebugBreak = true ;
2015-06-20 21:47:26 +08:00
if ( getCurrentContext ( ) . getRunner ( ) - > aborting ( ) | | ( m_assertionInfo . resultDisposition & ResultDisposition : : Normal ) )
2015-02-06 05:45:21 +08:00
m_shouldThrow = true ;
2014-12-28 16:11:01 +08:00
}
}
2015-02-06 05:45:21 +08:00
void ResultBuilder : : react ( ) {
if ( m_shouldThrow )
throw Catch : : TestFailureException ( ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
bool ResultBuilder : : shouldDebugBreak ( ) const { return m_shouldDebugBreak ; }
bool ResultBuilder : : allowThrows ( ) const { return getCurrentContext ( ) . getConfig ( ) - > allowThrows ( ) ; }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
AssertionResult ResultBuilder : : build ( ) const
{
assert ( m_data . resultType ! = ResultWas : : Unknown ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
AssertionResultData data = m_data ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
// 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 ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
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 + " ) " ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
return AssertionResult ( m_assertionInfo , data ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
std : : string ResultBuilder : : reconstructExpression ( ) const {
if ( m_exprComponents . op = = " " )
2017-01-12 05:23:02 +08:00
return m_exprComponents . lhs . empty ( ) ? m_assertionInfo . capturedExpression : m_exprComponents . lhs ;
2015-02-06 05:45:21 +08:00
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 & &
2014-12-28 16:11:01 +08:00
m_exprComponents . lhs . find ( " \n " ) = = std : : string : : npos & &
m_exprComponents . rhs . find ( " \n " ) = = std : : string : : npos )
2015-02-06 05:45:21 +08:00
return m_exprComponents . lhs + " " + m_exprComponents . op + " " + m_exprComponents . rhs ;
else
return m_exprComponents . lhs + " \n " + m_exprComponents . op + " \n " + m_exprComponents . rhs ;
2014-12-28 16:11:01 +08:00
}
else
2015-02-06 05:45:21 +08:00
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} " ;
2014-12-28 16:11:01 +08:00
}
} // end namespace Catch
// #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>
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
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 ;
} ;
2014-12-28 16:11:01 +08:00
} // end namespace Catch
# include <map>
# include <iostream>
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
TagAliasRegistry : : ~ TagAliasRegistry ( ) { }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
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 > ( ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
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 ( ) ) ;
}
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
return expandedTestSpec ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
void TagAliasRegistry : : add ( char const * alias , char const * tag , SourceLineInfo const & lineInfo ) {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
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 ( ) ) ;
}
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
TagAliasRegistry & TagAliasRegistry : : get ( ) {
static TagAliasRegistry instance ;
return instance ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
ITagAliasRegistry : : ~ ITagAliasRegistry ( ) { }
ITagAliasRegistry const & ITagAliasRegistry : : get ( ) { return TagAliasRegistry : : get ( ) ; }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
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 ) ;
2015-06-20 21:47:26 +08:00
Catch : : cerr ( ) < < ex . what ( ) < < std : : endl ;
2015-02-06 05:45:21 +08:00
exit ( 1 ) ;
}
2014-12-28 16:11:01 +08:00
}
} // end namespace Catch
2015-12-20 22:42:01 +08: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 ) ;
}
2016-06-20 00:25:43 +08:00
virtual MultipleReporters * tryAsMulti ( ) CATCH_OVERRIDE {
return this ;
}
2015-12-20 22:42:01 +08:00
} ;
Ptr < IStreamingReporter > addReporter ( Ptr < IStreamingReporter > const & existingReporter , Ptr < IStreamingReporter > const & additionalReporter ) {
Ptr < IStreamingReporter > resultingReporter ;
if ( existingReporter ) {
2016-06-20 00:25:43 +08:00
MultipleReporters * multi = existingReporter - > tryAsMulti ( ) ;
2015-12-20 22:42:01 +08:00
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
2014-12-28 16:11:01 +08:00
// #included from: ../reporters/catch_reporter_xml.hpp
# define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED
// #included from: catch_reporter_bases.hpp
# define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED
2015-06-20 21:47:26 +08:00
# include <cstring>
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
struct StreamingReporterBase : SharedImpl < IStreamingReporter > {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
StreamingReporterBase ( ReporterConfig const & _config )
2014-12-28 16:11:01 +08:00
: m_config ( _config . fullConfig ( ) ) ,
stream ( _config . stream ( ) )
2015-12-20 22:42:01 +08:00
{
m_reporterPrefs . shouldRedirectStdOut = false ;
}
virtual ReporterPreferences getPreferences ( ) const CATCH_OVERRIDE {
return m_reporterPrefs ;
}
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
virtual ~ StreamingReporterBase ( ) CATCH_OVERRIDE ;
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
virtual void noMatchingTestCases ( std : : string const & ) CATCH_OVERRIDE { }
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
virtual void testRunStarting ( TestRunInfo const & _testRunInfo ) CATCH_OVERRIDE {
2015-02-06 05:45:21 +08:00
currentTestRunInfo = _testRunInfo ;
}
2015-12-20 22:42:01 +08:00
virtual void testGroupStarting ( GroupInfo const & _groupInfo ) CATCH_OVERRIDE {
2015-02-06 05:45:21 +08:00
currentGroupInfo = _groupInfo ;
}
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
virtual void testCaseStarting ( TestCaseInfo const & _testInfo ) CATCH_OVERRIDE {
2015-02-06 05:45:21 +08:00
currentTestCaseInfo = _testInfo ;
}
2015-12-20 22:42:01 +08:00
virtual void sectionStarting ( SectionInfo const & _sectionInfo ) CATCH_OVERRIDE {
2015-02-06 05:45:21 +08:00
m_sectionStack . push_back ( _sectionInfo ) ;
}
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
virtual void sectionEnded ( SectionStats const & /* _sectionStats */ ) CATCH_OVERRIDE {
2015-02-06 05:45:21 +08:00
m_sectionStack . pop_back ( ) ;
}
2015-12-20 22:42:01 +08:00
virtual void testCaseEnded ( TestCaseStats const & /* _testCaseStats */ ) CATCH_OVERRIDE {
2015-02-06 05:45:21 +08:00
currentTestCaseInfo . reset ( ) ;
}
2015-12-20 22:42:01 +08:00
virtual void testGroupEnded ( TestGroupStats const & /* _testGroupStats */ ) CATCH_OVERRIDE {
2015-02-06 05:45:21 +08:00
currentGroupInfo . reset ( ) ;
}
2015-12-20 22:42:01 +08:00
virtual void testRunEnded ( TestRunStats const & /* _testRunStats */ ) CATCH_OVERRIDE {
2015-02-06 05:45:21 +08:00
currentTestCaseInfo . reset ( ) ;
currentGroupInfo . reset ( ) ;
currentTestRunInfo . reset ( ) ;
}
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
virtual void skipTest ( TestCaseInfo const & ) CATCH_OVERRIDE {
2015-06-20 21:47:26 +08:00
// Don't do anything with this by default.
// It can optionally be overridden in the derived class.
}
2015-12-20 22:42:01 +08:00
Ptr < IConfig const > m_config ;
2015-02-06 05:45:21 +08:00
std : : ostream & stream ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
LazyStat < TestRunInfo > currentTestRunInfo ;
LazyStat < GroupInfo > currentGroupInfo ;
LazyStat < TestCaseInfo > currentTestCaseInfo ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
std : : vector < SectionInfo > m_sectionStack ;
2015-12-20 22:42:01 +08:00
ReporterPreferences m_reporterPrefs ;
2015-02-06 05:45:21 +08:00
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
struct CumulativeReporterBase : SharedImpl < IStreamingReporter > {
template < typename T , typename ChildNodeT >
struct Node : SharedImpl < > {
explicit Node ( T const & _value ) : value ( _value ) { }
virtual ~ Node ( ) { }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
typedef std : : vector < Ptr < ChildNodeT > > ChildNodes ;
T value ;
ChildNodes children ;
} ;
struct SectionNode : SharedImpl < > {
explicit SectionNode ( SectionStats const & _stats ) : stats ( _stats ) { }
virtual ~ SectionNode ( ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
bool operator = = ( SectionNode const & other ) const {
return stats . sectionInfo . lineInfo = = other . stats . sectionInfo . lineInfo ;
}
bool operator = = ( Ptr < SectionNode > const & other ) const {
return operator = = ( * other ) ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
SectionStats stats ;
typedef std : : vector < Ptr < SectionNode > > ChildSections ;
typedef std : : vector < AssertionStats > Assertions ;
ChildSections childSections ;
Assertions assertions ;
std : : string stdOut ;
std : : string stdErr ;
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
struct BySectionInfo {
BySectionInfo ( SectionInfo const & other ) : m_other ( other ) { }
BySectionInfo ( BySectionInfo const & other ) : m_other ( other . m_other ) { }
bool operator ( ) ( Ptr < SectionNode > const & node ) const {
return node - > stats . sectionInfo . lineInfo = = m_other . lineInfo ;
}
private :
void operator = ( BySectionInfo const & ) ;
SectionInfo const & m_other ;
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
typedef Node < TestCaseStats , SectionNode > TestCaseNode ;
typedef Node < TestGroupStats , TestCaseNode > TestGroupNode ;
typedef Node < TestRunStats , TestGroupNode > TestRunNode ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
CumulativeReporterBase ( ReporterConfig const & _config )
2014-12-28 16:11:01 +08:00
: m_config ( _config . fullConfig ( ) ) ,
stream ( _config . stream ( ) )
2015-12-20 22:42:01 +08:00
{
m_reporterPrefs . shouldRedirectStdOut = false ;
}
2015-02-06 05:45:21 +08:00
~ CumulativeReporterBase ( ) ;
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
virtual ReporterPreferences getPreferences ( ) const CATCH_OVERRIDE {
return m_reporterPrefs ;
}
virtual void testRunStarting ( TestRunInfo const & ) CATCH_OVERRIDE { }
virtual void testGroupStarting ( GroupInfo const & ) CATCH_OVERRIDE { }
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
virtual void testCaseStarting ( TestCaseInfo const & ) CATCH_OVERRIDE { }
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
virtual void sectionStarting ( SectionInfo const & sectionInfo ) CATCH_OVERRIDE {
2015-02-06 05:45:21 +08: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 ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
else {
SectionNode & parentNode = * m_sectionStack . back ( ) ;
SectionNode : : ChildSections : : const_iterator it =
std : : find_if ( parentNode . childSections . begin ( ) ,
parentNode . childSections . end ( ) ,
BySectionInfo ( sectionInfo ) ) ;
if ( it = = parentNode . childSections . end ( ) ) {
node = new SectionNode ( incompleteStats ) ;
parentNode . childSections . push_back ( node ) ;
}
else
node = * it ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
m_sectionStack . push_back ( node ) ;
m_deepestSection = node ;
2014-12-28 16:11:01 +08:00
}
2015-12-20 22:42:01 +08:00
virtual void assertionStarting ( AssertionInfo const & ) CATCH_OVERRIDE { }
2014-12-28 16:11:01 +08:00
2016-06-20 00:25:43 +08:00
virtual bool assertionEnded ( AssertionStats const & assertionStats ) CATCH_OVERRIDE {
2015-02-06 05:45:21 +08:00
assert ( ! m_sectionStack . empty ( ) ) ;
SectionNode & sectionNode = * m_sectionStack . back ( ) ;
sectionNode . assertions . push_back ( assertionStats ) ;
return true ;
}
2015-12-20 22:42:01 +08:00
virtual void sectionEnded ( SectionStats const & sectionStats ) CATCH_OVERRIDE {
2015-02-06 05:45:21 +08:00
assert ( ! m_sectionStack . empty ( ) ) ;
SectionNode & node = * m_sectionStack . back ( ) ;
node . stats = sectionStats ;
m_sectionStack . pop_back ( ) ;
}
2015-12-20 22:42:01 +08:00
virtual void testCaseEnded ( TestCaseStats const & testCaseStats ) CATCH_OVERRIDE {
2015-02-06 05:45:21 +08: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-12-20 22:42:01 +08:00
virtual void testGroupEnded ( TestGroupStats const & testGroupStats ) CATCH_OVERRIDE {
2015-02-06 05:45:21 +08:00
Ptr < TestGroupNode > node = new TestGroupNode ( testGroupStats ) ;
node - > children . swap ( m_testCases ) ;
m_testGroups . push_back ( node ) ;
}
2015-12-20 22:42:01 +08:00
virtual void testRunEnded ( TestRunStats const & testRunStats ) CATCH_OVERRIDE {
2015-02-06 05:45:21 +08:00
Ptr < TestRunNode > node = new TestRunNode ( testRunStats ) ;
node - > children . swap ( m_testGroups ) ;
m_testRuns . push_back ( node ) ;
testRunEndedCumulative ( ) ;
}
virtual void testRunEndedCumulative ( ) = 0 ;
2015-12-20 22:42:01 +08:00
virtual void skipTest ( TestCaseInfo const & ) CATCH_OVERRIDE { }
2015-06-20 21:47:26 +08:00
2015-12-20 22:42:01 +08:00
Ptr < IConfig const > m_config ;
2015-02-06 05:45:21 +08:00
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 ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
std : : vector < Ptr < TestRunNode > > m_testRuns ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
Ptr < SectionNode > m_rootSection ;
Ptr < SectionNode > m_deepestSection ;
std : : vector < Ptr < SectionNode > > m_sectionStack ;
2015-12-20 22:42:01 +08:00
ReporterPreferences m_reporterPrefs ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
} ;
2014-12-28 16:11:01 +08:00
2015-06-20 21:47:26 +08: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-12-20 22:42:01 +08:00
struct TestEventListenerBase : StreamingReporterBase {
TestEventListenerBase ( ReporterConfig const & _config )
: StreamingReporterBase ( _config )
{ }
virtual void assertionStarting ( AssertionInfo const & ) CATCH_OVERRIDE { }
virtual bool assertionEnded ( AssertionStats const & ) CATCH_OVERRIDE {
return false ;
}
} ;
2014-12-28 16:11:01 +08:00
} // end namespace Catch
// #included from: ../internal/catch_reporter_registrars.hpp
# define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
template < typename T >
class LegacyReporterRegistrar {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
class ReporterFactory : public IReporterFactory {
virtual IStreamingReporter * create ( ReporterConfig const & config ) const {
return new LegacyReporterAdapter ( new T ( config ) ) ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
virtual std : : string getDescription ( ) const {
return T : : getDescription ( ) ;
}
} ;
public :
LegacyReporterRegistrar ( std : : string const & name ) {
getMutableRegistryHub ( ) . registerReporter ( name , new ReporterFactory ( ) ) ;
2014-12-28 16:11:01 +08:00
}
} ;
2015-02-06 05:45:21 +08:00
template < typename T >
class ReporterRegistrar {
2015-12-20 22:42:01 +08:00
class ReporterFactory : public SharedImpl < IReporterFactory > {
2015-02-06 05:45:21 +08: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.
virtual IStreamingReporter * create ( ReporterConfig const & config ) const {
return new T ( config ) ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
virtual std : : string getDescription ( ) const {
return T : : getDescription ( ) ;
}
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
public :
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
ReporterRegistrar ( std : : string const & name ) {
getMutableRegistryHub ( ) . registerReporter ( name , new ReporterFactory ( ) ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
} ;
2015-12-20 22:42:01 +08: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 ( ) ) ;
}
} ;
2015-02-06 05:45:21 +08:00
}
2014-12-28 16:11:01 +08:00
# define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \
namespace { Catch : : LegacyReporterRegistrar < reporterType > catch_internal_RegistrarFor # # reporterType ( name ) ; }
2015-12-20 22:42:01 +08:00
2014-12-28 16:11:01 +08:00
# define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \
namespace { Catch : : ReporterRegistrar < reporterType > catch_internal_RegistrarFor # # reporterType ( name ) ; }
2015-12-20 22:42:01 +08:00
# define INTERNAL_CATCH_REGISTER_LISTENER( listenerType ) \
namespace { Catch : : ListenerRegistrar < listenerType > catch_internal_RegistrarFor # # listenerType ; }
2014-12-28 16:11:01 +08:00
// #included from: ../internal/catch_xmlwriter.hpp
# define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED
# include <sstream>
# include <string>
# include <vector>
2015-12-20 22:42:01 +08:00
# include <iomanip>
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08: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 :
2016-11-17 02:15:54 +08:00
// Escape control chars - based on contribution by @espenalb in PR #465 and
// by @mrpi PR #588
2017-01-12 05:23:02 +08:00
if ( ( c > = 0 & & c < ' \x09 ' ) | | ( c > ' \x0D ' & & c < ' \x20 ' ) | | c = = ' \x7F ' )
2016-11-17 02:15:54 +08:00
os < < " &#x " < < std : : uppercase < < std : : hex < < std : : setfill ( ' 0 ' ) < < std : : setw ( 2 ) < < static_cast < int > ( c ) < < ' ; ' ;
2015-12-20 22:42:01 +08:00
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 ;
} ;
2015-02-06 05:45:21 +08:00
class XmlWriter {
public :
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
class ScopedElement {
public :
ScopedElement ( XmlWriter * writer )
2014-12-28 16:11:01 +08:00
: m_writer ( writer )
2015-02-06 05:45:21 +08:00
{ }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
ScopedElement ( ScopedElement const & other )
: m_writer ( other . m_writer ) {
2015-12-20 22:42:01 +08:00
other . m_writer = CATCH_NULL ;
2015-02-06 05:45:21 +08:00
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
~ ScopedElement ( ) {
if ( m_writer )
m_writer - > endElement ( ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
ScopedElement & writeText ( std : : string const & text , bool indent = true ) {
m_writer - > writeText ( text , indent ) ;
return * this ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
template < typename T >
ScopedElement & writeAttribute ( std : : string const & name , T const & attribute ) {
m_writer - > writeAttribute ( name , attribute ) ;
return * this ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
private :
mutable XmlWriter * m_writer ;
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
XmlWriter ( )
2014-12-28 16:11:01 +08:00
: m_tagIsOpen ( false ) ,
m_needsNewline ( false ) ,
2015-06-20 21:47:26 +08:00
m_os ( & Catch : : cout ( ) )
2016-11-17 02:15:54 +08:00
{
// We encode control characters, which requires
// XML 1.1
// see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0
* m_os < < " <?xml version= \" 1.1 \" encoding= \" UTF-8 \" ?> \n " ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
XmlWriter ( std : : ostream & os )
2014-12-28 16:11:01 +08:00
: m_tagIsOpen ( false ) ,
m_needsNewline ( false ) ,
m_os ( & os )
2016-11-17 02:15:54 +08:00
{
* m_os < < " <?xml version= \" 1.1 \" encoding= \" UTF-8 \" ?> \n " ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
~ XmlWriter ( ) {
while ( ! m_tags . empty ( ) )
endElement ( ) ;
}
XmlWriter & startElement ( std : : string const & name ) {
ensureTagClosed ( ) ;
newlineIfNecessary ( ) ;
stream ( ) < < m_indent < < " < " < < name ;
m_tags . push_back ( name ) ;
m_indent + = " " ;
m_tagIsOpen = true ;
return * this ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
ScopedElement scopedElement ( std : : string const & name ) {
ScopedElement scoped ( this ) ;
startElement ( name ) ;
return scoped ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
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 ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
XmlWriter & writeAttribute ( std : : string const & name , std : : string const & attribute ) {
2015-12-20 22:42:01 +08:00
if ( ! name . empty ( ) & & ! attribute . empty ( ) )
stream ( ) < < " " < < name < < " = \" " < < XmlEncode ( attribute , XmlEncode : : ForAttributes ) < < " \" " ;
2015-02-06 05:45:21 +08:00
return * this ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
XmlWriter & writeAttribute ( std : : string const & name , bool attribute ) {
stream ( ) < < " " < < name < < " = \" " < < ( attribute ? " true " : " false " ) < < " \" " ;
return * this ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
template < typename T >
XmlWriter & writeAttribute ( std : : string const & name , T const & attribute ) {
2015-12-20 22:42:01 +08:00
std : : ostringstream oss ;
oss < < attribute ;
return writeAttribute ( name , oss . str ( ) ) ;
2015-02-06 05:45:21 +08:00
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
XmlWriter & writeText ( std : : string const & text , bool indent = true ) {
if ( ! text . empty ( ) ) {
bool tagWasOpen = m_tagIsOpen ;
ensureTagClosed ( ) ;
if ( tagWasOpen & & indent )
stream ( ) < < m_indent ;
2015-12-20 22:42:01 +08:00
stream ( ) < < XmlEncode ( text ) ;
2015-02-06 05:45:21 +08:00
m_needsNewline = true ;
}
return * this ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
XmlWriter & writeComment ( std : : string const & text ) {
2014-12-28 16:11:01 +08:00
ensureTagClosed ( ) ;
2015-02-06 05:45:21 +08:00
stream ( ) < < m_indent < < " <!-- " < < text < < " --> " ;
2014-12-28 16:11:01 +08:00
m_needsNewline = true ;
2015-02-06 05:45:21 +08:00
return * this ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
XmlWriter & writeBlankLine ( ) {
ensureTagClosed ( ) ;
stream ( ) < < " \n " ;
return * this ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
void setStream ( std : : ostream & os ) {
m_os = & os ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
private :
XmlWriter ( XmlWriter const & ) ;
void operator = ( XmlWriter const & ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
std : : ostream & stream ( ) {
return * m_os ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
void ensureTagClosed ( ) {
if ( m_tagIsOpen ) {
stream ( ) < < " > \n " ;
m_tagIsOpen = false ;
}
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
void newlineIfNecessary ( ) {
if ( m_needsNewline ) {
stream ( ) < < " \n " ;
m_needsNewline = false ;
}
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
bool m_tagIsOpen ;
bool m_needsNewline ;
std : : vector < std : : string > m_tags ;
std : : string m_indent ;
std : : ostream * m_os ;
} ;
2014-12-28 16:11:01 +08:00
}
2015-12-20 22:42:01 +08: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
2015-02-06 05:45:21 +08:00
namespace Catch {
2015-06-20 21:47:26 +08:00
class XmlReporter : public StreamingReporterBase {
2015-02-06 05:45:21 +08:00
public :
2015-06-20 21:47:26 +08:00
XmlReporter ( ReporterConfig const & _config )
: StreamingReporterBase ( _config ) ,
2016-12-22 16:37:15 +08:00
m_xml ( _config . stream ( ) ) ,
2015-06-20 21:47:26 +08:00
m_sectionDepth ( 0 )
2015-12-20 22:42:01 +08:00
{
m_reporterPrefs . shouldRedirectStdOut = true ;
}
2015-06-20 21:47:26 +08:00
2015-12-20 22:42:01 +08:00
virtual ~ XmlReporter ( ) CATCH_OVERRIDE ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
static std : : string getDescription ( ) {
return " Reports test results as an XML document " ;
}
2014-12-28 16:11:01 +08:00
2015-06-20 21:47:26 +08:00
public : // StreamingReporterBase
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
virtual void noMatchingTestCases ( std : : string const & s ) CATCH_OVERRIDE {
2015-06-20 21:47:26 +08:00
StreamingReporterBase : : noMatchingTestCases ( s ) ;
2015-02-06 05:45:21 +08:00
}
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
virtual void testRunStarting ( TestRunInfo const & testInfo ) CATCH_OVERRIDE {
2015-06-20 21:47:26 +08:00
StreamingReporterBase : : testRunStarting ( testInfo ) ;
m_xml . startElement ( " Catch " ) ;
if ( ! m_config - > name ( ) . empty ( ) )
m_xml . writeAttribute ( " name " , m_config - > name ( ) ) ;
2015-02-06 05:45:21 +08:00
}
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
virtual void testGroupStarting ( GroupInfo const & groupInfo ) CATCH_OVERRIDE {
2015-06-20 21:47:26 +08:00
StreamingReporterBase : : testGroupStarting ( groupInfo ) ;
2015-02-06 05:45:21 +08:00
m_xml . startElement ( " Group " )
2015-06-20 21:47:26 +08:00
. writeAttribute ( " name " , groupInfo . name ) ;
2014-12-28 16:11:01 +08:00
}
2015-12-20 22:42:01 +08:00
virtual void testCaseStarting ( TestCaseInfo const & testInfo ) CATCH_OVERRIDE {
2015-06-20 21:47:26 +08:00
StreamingReporterBase : : testCaseStarting ( testInfo ) ;
2016-11-17 02:15:54 +08:00
m_xml . startElement ( " TestCase " ) . writeAttribute ( " name " , testInfo . name ) ;
2015-06-20 21:47:26 +08:00
if ( m_config - > showDurations ( ) = = ShowDurations : : Always )
m_testCaseTimer . start ( ) ;
2014-12-28 16:11:01 +08:00
}
2015-12-20 22:42:01 +08:00
virtual void sectionStarting ( SectionInfo const & sectionInfo ) CATCH_OVERRIDE {
2015-06-20 21:47:26 +08:00
StreamingReporterBase : : sectionStarting ( sectionInfo ) ;
2015-02-06 05:45:21 +08:00
if ( m_sectionDepth + + > 0 ) {
m_xml . startElement ( " Section " )
2015-06-20 21:47:26 +08:00
. writeAttribute ( " name " , trim ( sectionInfo . name ) )
. writeAttribute ( " description " , sectionInfo . description ) ;
2015-02-06 05:45:21 +08:00
}
2014-12-28 16:11:01 +08:00
}
2015-12-20 22:42:01 +08:00
virtual void assertionStarting ( AssertionInfo const & ) CATCH_OVERRIDE { }
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
virtual bool assertionEnded ( AssertionStats const & assertionStats ) CATCH_OVERRIDE {
2015-06-20 21:47:26 +08:00
const AssertionResult & assertionResult = assertionStats . assertionResult ;
2014-12-28 16:11:01 +08:00
2015-06-20 21:47:26 +08: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 ;
2015-02-06 05:45:21 +08:00
2015-06-20 21:47:26 +08:00
// Print the expression if there is one.
2015-02-06 05:45:21 +08:00
if ( assertionResult . hasExpression ( ) ) {
m_xml . startElement ( " Expression " )
. writeAttribute ( " success " , assertionResult . succeeded ( ) )
2015-06-20 21:47:26 +08:00
. writeAttribute ( " type " , assertionResult . getTestMacroName ( ) )
2015-02-06 05:45:21 +08:00
. writeAttribute ( " filename " , assertionResult . getSourceInfo ( ) . file )
. writeAttribute ( " line " , assertionResult . getSourceInfo ( ) . line ) ;
m_xml . scopedElement ( " Original " )
. writeText ( assertionResult . getExpression ( ) ) ;
m_xml . scopedElement ( " Expanded " )
. writeText ( assertionResult . getExpandedExpression ( ) ) ;
}
2015-06-20 21:47:26 +08:00
// And... Print a result applicable to each result type.
2015-02-06 05:45:21 +08:00
switch ( assertionResult . getResultType ( ) ) {
case ResultWas : : ThrewException :
m_xml . scopedElement ( " Exception " )
. writeAttribute ( " filename " , assertionResult . getSourceInfo ( ) . file )
. writeAttribute ( " line " , assertionResult . getSourceInfo ( ) . line )
. writeText ( assertionResult . getMessage ( ) ) ;
2015-06-20 21:47:26 +08:00
break ;
case ResultWas : : FatalErrorCondition :
2016-11-17 02:15:54 +08:00
m_xml . scopedElement ( " FatalErrorCondition " )
2015-06-20 21:47:26 +08:00
. writeAttribute ( " filename " , assertionResult . getSourceInfo ( ) . file )
. writeAttribute ( " line " , assertionResult . getSourceInfo ( ) . line )
. writeText ( assertionResult . getMessage ( ) ) ;
2015-02-06 05:45:21 +08:00
break ;
case ResultWas : : Info :
m_xml . scopedElement ( " Info " )
. writeText ( assertionResult . getMessage ( ) ) ;
break ;
case ResultWas : : Warning :
2015-06-20 21:47:26 +08:00
// Warning will already have been written
2015-02-06 05:45:21 +08:00
break ;
case ResultWas : : ExplicitFailure :
m_xml . scopedElement ( " Failure " )
. writeText ( assertionResult . getMessage ( ) ) ;
break ;
2015-06-20 21:47:26 +08:00
default :
2015-02-06 05:45:21 +08:00
break ;
}
2015-06-20 21:47:26 +08:00
2015-02-06 05:45:21 +08:00
if ( assertionResult . hasExpression ( ) )
m_xml . endElement ( ) ;
2015-06-20 21:47:26 +08:00
return true ;
}
2015-12-20 22:42:01 +08:00
virtual void sectionEnded ( SectionStats const & sectionStats ) CATCH_OVERRIDE {
2015-06-20 21:47:26 +08: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 ( ) ;
}
}
2015-12-20 22:42:01 +08:00
virtual void testCaseEnded ( TestCaseStats const & testCaseStats ) CATCH_OVERRIDE {
2015-06-20 21:47:26 +08: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 ( ) ;
2014-12-28 16:11:01 +08:00
}
2015-12-20 22:42:01 +08:00
virtual void testGroupEnded ( TestGroupStats const & testGroupStats ) CATCH_OVERRIDE {
2015-06-20 21:47:26 +08: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-02-06 05:45:21 +08:00
}
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
virtual void testRunEnded ( TestRunStats const & testRunStats ) CATCH_OVERRIDE {
2015-06-20 21:47:26 +08: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 ) ;
2015-02-06 05:45:21 +08:00
m_xml . endElement ( ) ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
private :
2015-06-20 21:47:26 +08:00
Timer m_testCaseTimer ;
2015-02-06 05:45:21 +08:00
XmlWriter m_xml ;
int m_sectionDepth ;
} ;
2014-12-28 16:11:01 +08:00
2015-06-20 21:47:26 +08:00
INTERNAL_CATCH_REGISTER_REPORTER ( " xml " , XmlReporter )
2014-12-28 16:11:01 +08:00
} // end namespace Catch
// #included from: ../reporters/catch_reporter_junit.hpp
# define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED
# include <assert.h>
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
class JunitReporter : public CumulativeReporterBase {
public :
JunitReporter ( ReporterConfig const & _config )
2014-12-28 16:11:01 +08:00
: CumulativeReporterBase ( _config ) ,
xml ( _config . stream ( ) )
2015-12-20 22:42:01 +08:00
{
m_reporterPrefs . shouldRedirectStdOut = true ;
}
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
virtual ~ JunitReporter ( ) CATCH_OVERRIDE ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
static std : : string getDescription ( ) {
return " Reports test results in an XML format that looks like Ant's junitreport target " ;
}
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
virtual void noMatchingTestCases ( std : : string const & /*spec*/ ) CATCH_OVERRIDE { }
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
virtual void testRunStarting ( TestRunInfo const & runInfo ) CATCH_OVERRIDE {
2015-02-06 05:45:21 +08:00
CumulativeReporterBase : : testRunStarting ( runInfo ) ;
xml . startElement ( " testsuites " ) ;
}
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
virtual void testGroupStarting ( GroupInfo const & groupInfo ) CATCH_OVERRIDE {
2015-02-06 05:45:21 +08:00
suiteTimer . start ( ) ;
stdOutForSuite . str ( " " ) ;
stdErrForSuite . str ( " " ) ;
unexpectedExceptions = 0 ;
CumulativeReporterBase : : testGroupStarting ( groupInfo ) ;
}
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
virtual bool assertionEnded ( AssertionStats const & assertionStats ) CATCH_OVERRIDE {
2015-02-06 05:45:21 +08:00
if ( assertionStats . assertionResult . getResultType ( ) = = ResultWas : : ThrewException )
unexpectedExceptions + + ;
return CumulativeReporterBase : : assertionEnded ( assertionStats ) ;
}
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
virtual void testCaseEnded ( TestCaseStats const & testCaseStats ) CATCH_OVERRIDE {
2015-02-06 05:45:21 +08:00
stdOutForSuite < < testCaseStats . stdOut ;
stdErrForSuite < < testCaseStats . stdErr ;
CumulativeReporterBase : : testCaseEnded ( testCaseStats ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
2015-12-20 22:42:01 +08:00
virtual void testGroupEnded ( TestGroupStats const & testGroupStats ) CATCH_OVERRIDE {
2015-02-06 05:45:21 +08:00
double suiteTime = suiteTimer . getElapsedSeconds ( ) ;
CumulativeReporterBase : : testGroupEnded ( testGroupStats ) ;
writeGroup ( * m_testGroups . back ( ) , suiteTime ) ;
2014-12-28 16:11:01 +08:00
}
2015-12-20 22:42:01 +08:00
virtual void testRunEndedCumulative ( ) CATCH_OVERRIDE {
2015-02-06 05:45:21 +08:00
xml . endElement ( ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
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 " , " " ) ;
else
xml . writeAttribute ( " time " , suiteTime ) ;
xml . writeAttribute ( " timestamp " , " tbd " ) ; // !TBD
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
// 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 ) ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
void writeTestCase ( TestCaseNode const & testCaseNode ) {
TestCaseStats const & stats = testCaseNode . value ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
// 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 ( ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
std : : string className = stats . testInfo . className ;
if ( className . empty ( ) ) {
if ( rootSection . childSections . empty ( ) )
className = " global " ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
writeSection ( className , " " , rootSection ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08: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 ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
if ( ! sectionNode . assertions . empty ( ) | |
2014-12-28 16:11:01 +08:00
! sectionNode . stdOut . empty ( ) | |
2015-02-06 05:45:21 +08:00
! 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 ) ;
}
2015-06-20 21:47:26 +08:00
xml . writeAttribute ( " time " , Catch : : toString ( sectionNode . stats . durationInSeconds ) ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
writeAssertions ( sectionNode ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08: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 ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
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 ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08: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 ( ) ) {
case ResultWas : : ThrewException :
2015-06-20 21:47:26 +08:00
case ResultWas : : FatalErrorCondition :
2015-02-06 05:45:21 +08:00
elementName = " error " ;
break ;
case ResultWas : : ExplicitFailure :
elementName = " failure " ;
break ;
case ResultWas : : ExpressionFailed :
elementName = " failure " ;
break ;
case ResultWas : : DidntThrowException :
elementName = " failure " ;
break ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
// We should never see these here:
case ResultWas : : Info :
case ResultWas : : Warning :
case ResultWas : : Ok :
case ResultWas : : Unknown :
case ResultWas : : FailureBit :
case ResultWas : : Exception :
elementName = " internalError " ;
break ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
XmlWriter : : ScopedElement e = xml . scopedElement ( elementName ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
xml . writeAttribute ( " message " , result . getExpandedExpression ( ) ) ;
xml . writeAttribute ( " type " , result . getTestMacroName ( ) ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
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 ) ;
2014-12-28 16:11:01 +08:00
}
}
2015-02-06 05:45:21 +08:00
XmlWriter xml ;
Timer suiteTimer ;
std : : ostringstream stdOutForSuite ;
std : : ostringstream stdErrForSuite ;
unsigned int unexpectedExceptions ;
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
INTERNAL_CATCH_REGISTER_REPORTER ( " junit " , JunitReporter )
2014-12-28 16:11:01 +08:00
} // end namespace Catch
// #included from: ../reporters/catch_reporter_console.hpp
# define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
struct ConsoleReporter : StreamingReporterBase {
ConsoleReporter ( ReporterConfig const & _config )
2014-12-28 16:11:01 +08:00
: StreamingReporterBase ( _config ) ,
m_headerPrinted ( false )
2015-02-06 05:45:21 +08:00
{ }
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
virtual ~ ConsoleReporter ( ) CATCH_OVERRIDE ;
2015-02-06 05:45:21 +08:00
static std : : string getDescription ( ) {
return " Reports test results as plain lines of text " ;
}
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
virtual void noMatchingTestCases ( std : : string const & spec ) CATCH_OVERRIDE {
2015-02-06 05:45:21 +08:00
stream < < " No test cases matched ' " < < spec < < " ' " < < std : : endl ;
}
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
virtual void assertionStarting ( AssertionInfo const & ) CATCH_OVERRIDE {
2015-02-06 05:45:21 +08:00
}
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
virtual bool assertionEnded ( AssertionStats const & _assertionStats ) CATCH_OVERRIDE {
2015-02-06 05:45:21 +08:00
AssertionResult const & result = _assertionStats . assertionResult ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
bool printInfoMessages = true ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
// 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 ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
lazyPrint ( ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
AssertionPrinter printer ( stream , _assertionStats , printInfoMessages ) ;
printer . print ( ) ;
stream < < std : : endl ;
return true ;
}
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
virtual void sectionStarting ( SectionInfo const & _sectionInfo ) CATCH_OVERRIDE {
2015-02-06 05:45:21 +08:00
m_headerPrinted = false ;
StreamingReporterBase : : sectionStarting ( _sectionInfo ) ;
}
2015-12-20 22:42:01 +08:00
virtual void sectionEnded ( SectionStats const & _sectionStats ) CATCH_OVERRIDE {
2015-02-06 05:45:21 +08:00
if ( _sectionStats . missingAssertions ) {
lazyPrint ( ) ;
Colour colour ( Colour : : ResultError ) ;
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 ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
if ( m_headerPrinted ) {
if ( m_config - > showDurations ( ) = = ShowDurations : : Always )
stream < < " Completed in " < < _sectionStats . durationInSeconds < < " s " < < std : : endl ;
m_headerPrinted = false ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
else {
if ( m_config - > showDurations ( ) = = ShowDurations : : Always )
stream < < _sectionStats . sectionInfo . name < < " completed in " < < _sectionStats . durationInSeconds < < " s " < < std : : endl ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
StreamingReporterBase : : sectionEnded ( _sectionStats ) ;
}
2015-12-20 22:42:01 +08:00
virtual void testCaseEnded ( TestCaseStats const & _testCaseStats ) CATCH_OVERRIDE {
2015-02-06 05:45:21 +08:00
StreamingReporterBase : : testCaseEnded ( _testCaseStats ) ;
2014-12-28 16:11:01 +08:00
m_headerPrinted = false ;
}
2015-12-20 22:42:01 +08:00
virtual void testGroupEnded ( TestGroupStats const & _testGroupStats ) CATCH_OVERRIDE {
2015-02-06 05:45:21 +08:00
if ( currentGroupInfo . used ) {
printSummaryDivider ( ) ;
stream < < " Summary for group ' " < < _testGroupStats . groupInfo . name < < " ': \n " ;
printTotals ( _testGroupStats . totals ) ;
stream < < " \n " < < std : : endl ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
StreamingReporterBase : : testGroupEnded ( _testGroupStats ) ;
2014-12-28 16:11:01 +08:00
}
2015-12-20 22:42:01 +08:00
virtual void testRunEnded ( TestRunStats const & _testRunStats ) CATCH_OVERRIDE {
2015-02-06 05:45:21 +08:00
printTotalsDivider ( _testRunStats . totals ) ;
printTotals ( _testRunStats . totals ) ;
stream < < std : : endl ;
StreamingReporterBase : : testRunEnded ( _testRunStats ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
private :
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
class AssertionPrinter {
void operator = ( AssertionPrinter const & ) ;
public :
AssertionPrinter ( std : : ostream & _stream , AssertionStats const & _stats , bool _printInfoMessages )
2014-12-28 16:11:01 +08:00
: stream ( _stream ) ,
stats ( _stats ) ,
result ( _stats . assertionResult ) ,
colour ( Colour : : None ) ,
message ( result . getMessage ( ) ) ,
messages ( _stats . infoMessages ) ,
printInfoMessages ( _printInfoMessages )
{
2015-02-06 05:45:21 +08:00
switch ( result . getResultType ( ) ) {
case ResultWas : : Ok :
2014-12-28 16:11:01 +08:00
colour = Colour : : Success ;
2015-02-06 05:45:21 +08:00
passOrFail = " PASSED " ;
//if( result.hasMessage() )
if ( _stats . infoMessages . size ( ) = = 1 )
messageLabel = " with message " ;
if ( _stats . infoMessages . size ( ) > 1 )
messageLabel = " with messages " ;
break ;
case ResultWas : : ExpressionFailed :
if ( result . isOk ( ) ) {
colour = Colour : : Success ;
passOrFail = " FAILED - but was ok " ;
}
else {
colour = Colour : : Error ;
passOrFail = " FAILED " ;
}
if ( _stats . infoMessages . size ( ) = = 1 )
messageLabel = " with message " ;
if ( _stats . infoMessages . size ( ) > 1 )
messageLabel = " with messages " ;
break ;
case ResultWas : : ThrewException :
2014-12-28 16:11:01 +08:00
colour = Colour : : Error ;
passOrFail = " FAILED " ;
2015-02-06 05:45:21 +08:00
messageLabel = " due to unexpected exception with message " ;
break ;
2015-06-20 21:47:26 +08:00
case ResultWas : : FatalErrorCondition :
colour = Colour : : Error ;
passOrFail = " FAILED " ;
messageLabel = " due to a fatal error condition " ;
break ;
2015-02-06 05:45:21 +08:00
case ResultWas : : DidntThrowException :
colour = Colour : : Error ;
passOrFail = " FAILED " ;
messageLabel = " because no exception was thrown where one was expected " ;
break ;
case ResultWas : : Info :
messageLabel = " info " ;
break ;
case ResultWas : : Warning :
messageLabel = " warning " ;
break ;
case ResultWas : : ExplicitFailure :
passOrFail = " FAILED " ;
colour = Colour : : Error ;
if ( _stats . infoMessages . size ( ) = = 1 )
messageLabel = " explicitly with message " ;
if ( _stats . infoMessages . size ( ) > 1 )
messageLabel = " explicitly with messages " ;
break ;
// These cases are here to prevent compiler warnings
case ResultWas : : Unknown :
case ResultWas : : FailureBit :
case ResultWas : : Exception :
passOrFail = " ** internal error ** " ;
colour = Colour : : Error ;
break ;
}
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
void print ( ) const {
printSourceInfo ( ) ;
if ( stats . totals . assertions . total ( ) > 0 ) {
if ( result . isOk ( ) )
stream < < " \n " ;
printResultType ( ) ;
printOriginalExpression ( ) ;
printReconstructedExpression ( ) ;
}
else {
2014-12-28 16:11:01 +08:00
stream < < " \n " ;
}
2015-02-06 05:45:21 +08:00
printMessage ( ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
private :
void printResultType ( ) const {
if ( ! passOrFail . empty ( ) ) {
Colour colourGuard ( colour ) ;
stream < < passOrFail < < " : \n " ;
}
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
void printOriginalExpression ( ) const {
if ( result . hasExpression ( ) ) {
Colour colourGuard ( Colour : : OriginalExpression ) ;
stream < < " " ;
stream < < result . getExpressionInMacro ( ) ;
stream < < " \n " ;
}
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
void printReconstructedExpression ( ) const {
if ( result . hasExpandedExpression ( ) ) {
stream < < " with expansion: \n " ;
Colour colourGuard ( Colour : : ReconstructedExpression ) ;
stream < < Text ( result . getExpandedExpression ( ) , TextAttributes ( ) . setIndent ( 2 ) ) < < " \n " ;
}
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
void printMessage ( ) const {
if ( ! messageLabel . empty ( ) )
stream < < messageLabel < < " : " < < " \n " ;
for ( std : : vector < MessageInfo > : : const_iterator it = messages . begin ( ) , itEnd = messages . end ( ) ;
it ! = itEnd ;
+ + it ) {
// If this assertion is a warning ignore any INFO messages
if ( printInfoMessages | | it - > type ! = ResultWas : : Info )
stream < < Text ( it - > message , TextAttributes ( ) . setIndent ( 2 ) ) < < " \n " ;
2014-12-28 16:11:01 +08:00
}
}
2015-02-06 05:45:21 +08:00
void printSourceInfo ( ) const {
Colour colourGuard ( Colour : : FileName ) ;
stream < < result . getSourceInfo ( ) < < " : " ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
std : : ostream & stream ;
AssertionStats const & stats ;
AssertionResult const & result ;
Colour : : Code colour ;
std : : string passOrFail ;
std : : string messageLabel ;
std : : string message ;
std : : vector < MessageInfo > messages ;
bool printInfoMessages ;
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
void lazyPrint ( ) {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
if ( ! currentTestRunInfo . used )
lazyPrintRunInfo ( ) ;
if ( ! currentGroupInfo . used )
lazyPrintGroupInfo ( ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
if ( ! m_headerPrinted ) {
printTestCaseAndSectionHeader ( ) ;
m_headerPrinted = true ;
2014-12-28 16:11:01 +08:00
}
}
2015-02-06 05:45:21 +08:00
void lazyPrintRunInfo ( ) {
stream < < " \n " < < getLineOfChars < ' ~ ' > ( ) < < " \n " ;
Colour colour ( Colour : : SecondaryText ) ;
stream < < currentTestRunInfo - > name
2015-07-26 16:41:38 +08:00
< < " is a Catch v " < < libraryVersion < < " host application. \n "
2015-02-06 05:45:21 +08:00
< < " Run with -? for options \n \n " ;
2015-06-20 21:47:26 +08:00
if ( m_config - > rngSeed ( ) ! = 0 )
stream < < " Randomness seeded to: " < < m_config - > rngSeed ( ) < < " \n \n " ;
2015-02-06 05:45:21 +08:00
currentTestRunInfo . used = true ;
}
void lazyPrintGroupInfo ( ) {
if ( ! currentGroupInfo - > name . empty ( ) & & currentGroupInfo - > groupsCounts > 1 ) {
printClosedHeader ( " Group: " + currentGroupInfo - > name ) ;
currentGroupInfo . used = true ;
}
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
void printTestCaseAndSectionHeader ( ) {
assert ( ! m_sectionStack . empty ( ) ) ;
printOpenHeader ( currentTestCaseInfo - > name ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
if ( m_sectionStack . size ( ) > 1 ) {
Colour colourGuard ( Colour : : Headers ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
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 ) ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
SourceLineInfo lineInfo = m_sectionStack . front ( ) . lineInfo ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
if ( ! lineInfo . empty ( ) ) {
stream < < getLineOfChars < ' - ' > ( ) < < " \n " ;
Colour colourGuard ( Colour : : FileName ) ;
stream < < lineInfo < < " \n " ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
stream < < getLineOfChars < ' . ' > ( ) < < " \n " < < std : : endl ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
void printClosedHeader ( std : : string const & _name ) {
printOpenHeader ( _name ) ;
stream < < getLineOfChars < ' . ' > ( ) < < " \n " ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
void printOpenHeader ( std : : string const & _name ) {
stream < < getLineOfChars < ' - ' > ( ) < < " \n " ;
2014-12-28 16:11:01 +08:00
{
2015-02-06 05:45:21 +08:00
Colour colourGuard ( Colour : : Headers ) ;
printHeaderString ( _name ) ;
2014-12-28 16:11:01 +08:00
}
}
2015-02-06 05:45:21 +08:00
// if string has a : in first line will set indent to follow it on
// subsequent lines
void printHeaderString ( std : : string const & _string , std : : size_t indent = 0 ) {
std : : size_t i = _string . find ( " : " ) ;
if ( i ! = std : : string : : npos )
i + = 2 ;
else
i = 0 ;
stream < < Text ( _string , TextAttributes ( )
. setIndent ( indent + i )
. setInitialIndent ( indent ) ) < < " \n " ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08: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 ( ) )
* it = " " + * it ;
while ( it - > size ( ) > row . size ( ) )
row = " " + row ;
}
rows . push_back ( row ) ;
return * this ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
std : : string label ;
Colour : : Code colour ;
std : : vector < std : : string > rows ;
} ;
void printTotals ( Totals const & totals ) {
if ( totals . testCases . total ( ) = = 0 ) {
stream < < Colour ( Colour : : Warning ) < < " No tests ran \n " ;
}
2016-06-20 00:25:43 +08:00
else if ( totals . assertions . total ( ) > 0 & & totals . testCases . allPassed ( ) ) {
2015-02-06 05:45:21 +08:00
stream < < Colour ( Colour : : ResultSuccess ) < < " All tests passed " ;
stream < < " ( "
< < pluralise ( totals . assertions . passed , " assertion " ) < < " in "
< < pluralise ( totals . testCases . passed , " test case " ) < < " ) "
< < " \n " ;
}
else {
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 ) ) ;
printSummaryRow ( " test cases " , columns , 0 ) ;
printSummaryRow ( " assertions " , columns , 1 ) ;
}
}
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 ;
}
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
stream < < " \n " ;
}
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 ;
2014-12-28 16:11:01 +08:00
else
2015-02-06 05:45:21 +08:00
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 , ' = ' ) ;
if ( totals . testCases . allPassed ( ) )
stream < < Colour ( Colour : : ResultSuccess ) < < std : : string ( passedRatio , ' = ' ) ;
else
stream < < Colour ( Colour : : Success ) < < std : : string ( passedRatio , ' = ' ) ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
else {
stream < < Colour ( Colour : : Warning ) < < std : : string ( CATCH_CONFIG_CONSOLE_WIDTH - 1 , ' = ' ) ;
}
stream < < " \n " ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
void printSummaryDivider ( ) {
stream < < getLineOfChars < ' - ' > ( ) < < " \n " ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
private :
bool m_headerPrinted ;
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
INTERNAL_CATCH_REGISTER_REPORTER ( " console " , ConsoleReporter )
2014-12-28 16:11:01 +08:00
} // end namespace Catch
// #included from: ../reporters/catch_reporter_compact.hpp
# define TWOBLUECUBES_CATCH_REPORTER_COMPACT_HPP_INCLUDED
2015-02-06 05:45:21 +08:00
namespace Catch {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
struct CompactReporter : StreamingReporterBase {
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
CompactReporter ( ReporterConfig const & _config )
2014-12-28 16:11:01 +08:00
: StreamingReporterBase ( _config )
2015-02-06 05:45:21 +08:00
{ }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
virtual ~ CompactReporter ( ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
static std : : string getDescription ( ) {
return " Reports test results on a single line, suitable for IDEs " ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
virtual ReporterPreferences getPreferences ( ) const {
ReporterPreferences prefs ;
prefs . shouldRedirectStdOut = false ;
return prefs ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
virtual void noMatchingTestCases ( std : : string const & spec ) {
stream < < " No test cases matched ' " < < spec < < " ' " < < std : : endl ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
virtual void assertionStarting ( AssertionInfo const & ) {
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
virtual bool assertionEnded ( AssertionStats const & _assertionStats ) {
AssertionResult const & result = _assertionStats . assertionResult ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
bool printInfoMessages = true ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
// 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 ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
AssertionPrinter printer ( stream , _assertionStats , printInfoMessages ) ;
printer . print ( ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
stream < < std : : endl ;
return true ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
virtual void testRunEnded ( TestRunStats const & _testRunStats ) {
printTotals ( _testRunStats . totals ) ;
stream < < " \n " < < std : : endl ;
StreamingReporterBase : : testRunEnded ( _testRunStats ) ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
private :
class AssertionPrinter {
void operator = ( AssertionPrinter const & ) ;
public :
AssertionPrinter ( std : : ostream & _stream , AssertionStats const & _stats , bool _printInfoMessages )
2014-12-28 16:11:01 +08:00
: stream ( _stream )
, stats ( _stats )
, result ( _stats . assertionResult )
, messages ( _stats . infoMessages )
, itMessage ( _stats . infoMessages . begin ( ) )
, printInfoMessages ( _printInfoMessages )
2015-02-06 05:45:21 +08:00
{ }
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
void print ( ) {
printSourceInfo ( ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
itMessage = messages . begin ( ) ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
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 ( ) ;
2014-12-28 16:11:01 +08:00
printRemainingMessages ( ) ;
2015-02-06 05:45:21 +08:00
break ;
case ResultWas : : ThrewException :
2014-12-28 16:11:01 +08:00
printResultType ( Colour : : Error , failedString ( ) ) ;
2015-02-06 05:45:21 +08:00
printIssue ( " unexpected exception with message: " ) ;
printMessage ( ) ;
printExpressionWas ( ) ;
printRemainingMessages ( ) ;
break ;
2015-06-20 21:47:26 +08:00
case ResultWas : : FatalErrorCondition :
printResultType ( Colour : : Error , failedString ( ) ) ;
printIssue ( " fatal error condition with message: " ) ;
printMessage ( ) ;
printExpressionWas ( ) ;
printRemainingMessages ( ) ;
break ;
2015-02-06 05:45:21 +08: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 ;
}
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
private :
// Colour::LightGrey
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
static Colour : : Code dimColour ( ) { return Colour : : FileName ; }
2014-12-28 16:11:01 +08:00
# ifdef CATCH_PLATFORM_MAC
2015-02-06 05:45:21 +08:00
static const char * failedString ( ) { return " FAILED " ; }
static const char * passedString ( ) { return " PASSED " ; }
2014-12-28 16:11:01 +08:00
# else
2015-02-06 05:45:21 +08:00
static const char * failedString ( ) { return " failed " ; }
static const char * passedString ( ) { return " passed " ; }
2014-12-28 16:11:01 +08:00
# endif
2015-02-06 05:45:21 +08:00
void printSourceInfo ( ) const {
Colour colourGuard ( Colour : : FileName ) ;
stream < < result . getSourceInfo ( ) < < " : " ;
}
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
void printResultType ( Colour : : Code colour , std : : string passOrFail ) const {
if ( ! passOrFail . empty ( ) ) {
{
Colour colourGuard ( colour ) ;
stream < < " " < < passOrFail ;
}
stream < < " : " ;
2014-12-28 16:11:01 +08:00
}
}
2015-02-06 05:45:21 +08:00
void printIssue ( std : : string issue ) const {
stream < < " " < < issue ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
void printExpressionWas ( ) {
if ( result . hasExpression ( ) ) {
stream < < " ; " ;
{
Colour colour ( dimColour ( ) ) ;
stream < < " expression was: " ;
}
printOriginalExpression ( ) ;
}
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
void printOriginalExpression ( ) const {
if ( result . hasExpression ( ) ) {
stream < < " " < < result . getExpression ( ) ;
2014-12-28 16:11:01 +08:00
}
}
2015-02-06 05:45:21 +08:00
void printReconstructedExpression ( ) const {
if ( result . hasExpandedExpression ( ) ) {
{
Colour colour ( dimColour ( ) ) ;
stream < < " for: " ;
}
stream < < result . getExpandedExpression ( ) ;
}
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
void printMessage ( ) {
if ( itMessage ! = messages . end ( ) ) {
stream < < " ' " < < itMessage - > message < < " ' " ;
+ + itMessage ;
}
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
void printRemainingMessages ( Colour : : Code colour = dimColour ( ) ) {
if ( itMessage = = messages . end ( ) )
return ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
// 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 ) ) ;
2014-12-28 16:11:01 +08:00
{
2015-02-06 05:45:21 +08:00
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 " ;
}
2014-12-28 16:11:01 +08:00
}
}
}
2015-02-06 05:45:21 +08:00
private :
std : : ostream & stream ;
AssertionStats const & stats ;
AssertionResult const & result ;
std : : vector < MessageInfo > messages ;
std : : vector < MessageInfo > : : const_iterator itMessage ;
bool printInfoMessages ;
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
// 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.
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
std : : string bothOrAll ( std : : size_t count ) const {
return count = = 1 ? " " : count = = 2 ? " both " : " all " ;
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
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 " ) < < " . " ;
}
2014-12-28 16:11:01 +08:00
}
2015-02-06 05:45:21 +08:00
} ;
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
INTERNAL_CATCH_REGISTER_REPORTER ( " compact " , CompactReporter )
2014-12-28 16:11:01 +08:00
} // end namespace Catch
2015-02-06 05:45:21 +08:00
namespace Catch {
2015-12-20 22:42:01 +08:00
// These are all here to avoid warnings about not having any out of line
// virtual methods
2015-02-06 05:45:21 +08:00
NonCopyable : : ~ NonCopyable ( ) { }
IShared : : ~ IShared ( ) { }
2015-12-20 22:42:01 +08:00
IStream : : ~ IStream ( ) CATCH_NOEXCEPT { }
FileStream : : ~ FileStream ( ) CATCH_NOEXCEPT { }
CoutStream : : ~ CoutStream ( ) CATCH_NOEXCEPT { }
DebugOutStream : : ~ DebugOutStream ( ) CATCH_NOEXCEPT { }
2015-02-06 05:45:21 +08:00
StreamBufBase : : ~ StreamBufBase ( ) CATCH_NOEXCEPT { }
IContext : : ~ IContext ( ) { }
IResultCapture : : ~ IResultCapture ( ) { }
ITestCase : : ~ ITestCase ( ) { }
ITestCaseRegistry : : ~ ITestCaseRegistry ( ) { }
IRegistryHub : : ~ IRegistryHub ( ) { }
IMutableRegistryHub : : ~ IMutableRegistryHub ( ) { }
IExceptionTranslator : : ~ IExceptionTranslator ( ) { }
IExceptionTranslatorRegistry : : ~ IExceptionTranslatorRegistry ( ) { }
IReporter : : ~ IReporter ( ) { }
IReporterFactory : : ~ IReporterFactory ( ) { }
IReporterRegistry : : ~ IReporterRegistry ( ) { }
IStreamingReporter : : ~ IStreamingReporter ( ) { }
AssertionStats : : ~ AssertionStats ( ) { }
SectionStats : : ~ SectionStats ( ) { }
TestCaseStats : : ~ TestCaseStats ( ) { }
TestGroupStats : : ~ TestGroupStats ( ) { }
TestRunStats : : ~ TestRunStats ( ) { }
CumulativeReporterBase : : SectionNode : : ~ SectionNode ( ) { }
CumulativeReporterBase : : ~ CumulativeReporterBase ( ) { }
StreamingReporterBase : : ~ StreamingReporterBase ( ) { }
ConsoleReporter : : ~ ConsoleReporter ( ) { }
CompactReporter : : ~ CompactReporter ( ) { }
IRunner : : ~ IRunner ( ) { }
IMutableContext : : ~ IMutableContext ( ) { }
IConfig : : ~ IConfig ( ) { }
XmlReporter : : ~ XmlReporter ( ) { }
JunitReporter : : ~ JunitReporter ( ) { }
TestRegistry : : ~ TestRegistry ( ) { }
FreeFunctionTestCase : : ~ FreeFunctionTestCase ( ) { }
IGeneratorInfo : : ~ IGeneratorInfo ( ) { }
IGeneratorsForTest : : ~ IGeneratorsForTest ( ) { }
2015-12-20 22:42:01 +08:00
WildcardPattern : : ~ WildcardPattern ( ) { }
2015-02-06 05:45:21 +08:00
TestSpec : : Pattern : : ~ Pattern ( ) { }
TestSpec : : NamePattern : : ~ NamePattern ( ) { }
TestSpec : : TagPattern : : ~ TagPattern ( ) { }
TestSpec : : ExcludedPattern : : ~ ExcludedPattern ( ) { }
Matchers : : Impl : : StdString : : Equals : : ~ Equals ( ) { }
Matchers : : Impl : : StdString : : Contains : : ~ Contains ( ) { }
Matchers : : Impl : : StdString : : StartsWith : : ~ StartsWith ( ) { }
Matchers : : Impl : : StdString : : EndsWith : : ~ EndsWith ( ) { }
void Config : : dummy ( ) { }
2015-12-20 22:42:01 +08:00
namespace TestCaseTracking {
ITracker : : ~ ITracker ( ) { }
TrackerBase : : ~ TrackerBase ( ) { }
SectionTracker : : ~ SectionTracker ( ) { }
IndexTracker : : ~ IndexTracker ( ) { }
}
2014-12-28 16:11:01 +08:00
}
# ifdef __clang__
2015-02-06 05:45:21 +08:00
# pragma clang diagnostic pop
2014-12-28 16:11:01 +08:00
# endif
# endif
# ifdef CATCH_CONFIG_MAIN
// #included from: internal/catch_default_main.hpp
# define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED
# ifndef __OBJC__
// Standard C/C++ main entry point
2015-12-20 22:42:01 +08:00
int main ( int argc , char * argv [ ] ) {
2014-12-28 16:11:01 +08:00
return Catch : : Session ( ) . run ( argc , argv ) ;
}
# else // __OBJC__
// Objective-C entry point
2015-02-06 05:45:21 +08:00
int main ( int argc , char * const argv [ ] ) {
2014-12-28 16:11:01 +08:00
# if !CATCH_ARC_ENABLED
2015-02-06 05:45:21 +08:00
NSAutoreleasePool * pool = [ [ NSAutoreleasePool alloc ] init ] ;
2014-12-28 16:11:01 +08:00
# endif
Catch : : registerTestMethods ( ) ;
int result = Catch : : Session ( ) . run ( argc , ( char * const * ) argv ) ;
# if !CATCH_ARC_ENABLED
[ pool drain ] ;
# endif
return result ;
}
# endif // __OBJC__
# endif
# ifdef CLARA_CONFIG_MAIN_NOT_DEFINED
2015-02-06 05:45:21 +08:00
# undef CLARA_CONFIG_MAIN
2014-12-28 16:11:01 +08:00
# endif
//////
// If this config identifier is defined then all CATCH macros are prefixed with CATCH_
# ifdef CATCH_CONFIG_PREFIX_ALL
2015-02-06 05:45:21 +08:00
# define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE" )
# define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "CATCH_REQUIRE_FALSE" )
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
# define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "CATCH_REQUIRE_THROWS" )
2015-02-06 05:45:21 +08:00
# define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS_AS" )
2015-12-20 22:42:01 +08:00
# define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, matcher, "CATCH_REQUIRE_THROWS_WITH" )
2015-02-06 05:45:21 +08:00
# define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_NOTHROW" )
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
# define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK" )
# define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CATCH_CHECK_FALSE" )
# 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" )
2014-12-28 16:11:01 +08:00
2017-01-12 05:23:02 +08:00
# define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "", "CATCH_CHECK_THROWS" )
2015-02-06 05:45:21 +08:00
# define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS_AS" )
2015-12-20 22:42:01 +08:00
# define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CATCH_CHECK_THROWS_WITH" )
2015-02-06 05:45:21 +08:00
# define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" )
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08: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" )
# define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" )
# define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "CATCH_WARN", msg )
# define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" )
# define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" )
# define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" )
# ifdef CATCH_CONFIG_VARIADIC_MACROS
# define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
# define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
# define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
2016-02-15 04:36:43 +08:00
# define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
2015-02-06 05:45:21 +08:00
# define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
# define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ )
# define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", __VA_ARGS__ )
2014-12-28 16:11:01 +08:00
# else
2015-02-06 05:45:21 +08:00
# define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
# define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )
# define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
2015-12-20 22:42:01 +08:00
# define CATCH_REGISTER_TEST_CASE( function, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( function, name, description )
2015-02-06 05:45:21 +08:00
# define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
# define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", msg )
# define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", msg )
# endif
# define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08:00
# define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
# define CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType )
# define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
// "BDD-style" convenience wrappers
# ifdef CATCH_CONFIG_VARIADIC_MACROS
# define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ )
# define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
# else
# define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags )
# define CATCH_SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags )
# endif
2015-12-20 22:42:01 +08: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, "" )
2015-02-06 05:45:21 +08:00
// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required
# else
# define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "REQUIRE" )
# define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "REQUIRE_FALSE" )
2015-12-20 22:42:01 +08:00
# define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "REQUIRE_THROWS" )
2015-02-06 05:45:21 +08:00
# define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "REQUIRE_THROWS_AS" )
2015-12-20 22:42:01 +08:00
# define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, matcher, "REQUIRE_THROWS_WITH" )
2015-02-06 05:45:21 +08:00
# define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "REQUIRE_NOTHROW" )
# define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" )
# define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CHECK_FALSE" )
# 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" )
2014-12-28 16:11:01 +08:00
2015-12-20 22:42:01 +08:00
# define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "", "CHECK_THROWS" )
2015-02-06 05:45:21 +08:00
# define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS_AS" )
2015-12-20 22:42:01 +08:00
# define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CHECK_THROWS_WITH" )
2015-02-06 05:45:21 +08:00
# define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_NOTHROW" )
2014-12-28 16:11:01 +08:00
2015-02-06 05:45:21 +08: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" )
# define INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" )
# define WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "WARN", msg )
# define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" )
# define CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" )
# define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" )
# ifdef CATCH_CONFIG_VARIADIC_MACROS
# define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
# define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
# define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
2016-02-15 04:36:43 +08:00
# define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
2015-02-06 05:45:21 +08:00
# define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
# define FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", __VA_ARGS__ )
# define SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", __VA_ARGS__ )
# else
# define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
# define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )
# define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
2016-02-15 04:36:43 +08:00
# define REGISTER_TEST_CASE( method, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( method, name, description )
2015-02-06 05:45:21 +08:00
# define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
# define FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", msg )
# define SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", msg )
# endif
# define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )
# define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
# define REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType )
# define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
2014-12-28 16:11:01 +08:00
# endif
# define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )
// "BDD-style" convenience wrappers
# ifdef CATCH_CONFIG_VARIADIC_MACROS
2015-02-06 05:45:21 +08:00
# define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ )
# define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
2014-12-28 16:11:01 +08:00
# else
2015-02-06 05:45:21 +08:00
# define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags )
# define SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags )
2014-12-28 16:11:01 +08:00
# endif
2015-12-20 22:42:01 +08: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, "" )
2014-12-28 16:11:01 +08:00
using Catch : : Detail : : Approx ;
# endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED