2011-05-24 09:23:02 +02:00
/*
2013-03-12 19:49:37 +01:00
* CATCH v0 .9 build 24 ( integration branch )
* Generated : 2013 - 03 - 12 18 : 45 : 29.590076
2012-05-22 23:22:22 +02:00
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2012-05-09 20:37:51 +02:00
* This file has been merged from multiple headers . Please don ' t edit it directly
* Copyright ( c ) 2012 Two Blue Cubes Ltd . All rights reserved .
2011-05-24 09:23:02 +02:00
*
* Distributed under the Boost Software License , Version 1.0 . ( See accompanying
* file LICENSE_1_0 . txt or copy at http : //www.boost.org/LICENSE_1_0.txt)
*/
2012-05-09 20:37:51 +02:00
# ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
# define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
2011-05-24 09:23:02 +02:00
2012-08-09 08:47:30 +02:00
# define TWOBLUECUBES_CATCH_HPP_INCLUDED
2012-06-03 00:12:42 +02:00
2012-08-16 19:48:50 +02:00
# ifdef __clang__
2012-10-30 10:09:30 +01:00
# pragma clang diagnostic ignored "-Wglobal-constructors"
2012-08-16 19:48:50 +02:00
2012-08-13 08:46:10 +02:00
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wpadded"
2012-08-16 19:48:50 +02:00
# endif
2012-08-13 08:46:10 +02:00
2012-08-09 08:47:30 +02:00
// #included from: internal/catch_notimplemented_exception.h
# define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED
2011-05-24 09:23:02 +02:00
// #included from: catch_common.h
2012-08-09 08:47:30 +02:00
# define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED
2011-05-24 09:23:02 +02:00
# define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
# define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line )
# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
# define INTERNAL_CATCH_STRINGIFY2( expr ) #expr
# define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr )
# ifdef __GNUC__
2012-08-13 08:46:10 +02:00
# define CATCH_ATTRIBUTE_NORETURN __attribute__ ((noreturn))
2011-05-24 09:23:02 +02:00
# else
2012-08-13 08:46:10 +02:00
# define CATCH_ATTRIBUTE_NORETURN
2011-05-24 09:23:02 +02:00
# endif
# include <sstream>
# include <stdexcept>
# include <algorithm>
2012-05-16 16:09:17 +02:00
namespace Catch {
2013-03-08 10:30:25 +01:00
class NonCopyable {
NonCopyable ( const NonCopyable & ) ;
void operator = ( const NonCopyable & ) ;
protected :
NonCopyable ( ) { }
virtual ~ NonCopyable ( ) ;
} ;
2011-05-24 09:23:02 +02:00
2012-05-31 20:40:26 +02:00
class SafeBool {
public :
typedef void ( SafeBool : : * type ) ( ) const ;
static type makeSafe ( bool value ) {
return value ? & SafeBool : : trueValue : 0 ;
}
private :
void trueValue ( ) const { }
} ;
2011-05-24 09:23:02 +02:00
template < typename ContainerT >
2012-05-09 20:04:00 +02:00
inline void deleteAll ( ContainerT & container ) {
2011-05-24 09:23:02 +02:00
typename ContainerT : : const_iterator it = container . begin ( ) ;
typename ContainerT : : const_iterator itEnd = container . end ( ) ;
for ( ; it ! = itEnd ; + + it )
delete * it ;
}
template < typename AssociativeContainerT >
2012-05-09 20:04:00 +02:00
inline void deleteAllValues ( AssociativeContainerT & container ) {
2011-05-24 09:23:02 +02:00
typename AssociativeContainerT : : const_iterator it = container . begin ( ) ;
typename AssociativeContainerT : : const_iterator itEnd = container . end ( ) ;
for ( ; it ! = itEnd ; + + it )
delete it - > second ;
}
template < typename ContainerT , typename Function >
2012-05-09 20:04:00 +02:00
inline void forEach ( ContainerT & container , Function function ) {
2011-05-24 09:23:02 +02:00
std : : for_each ( container . begin ( ) , container . end ( ) , function ) ;
}
template < typename ContainerT , typename Function >
2012-05-09 20:04:00 +02:00
inline void forEach ( const ContainerT & container , Function function ) {
2011-05-24 09:23:02 +02:00
std : : for_each ( container . begin ( ) , container . end ( ) , function ) ;
}
2012-08-23 21:08:50 +02:00
inline bool startsWith ( const std : : string & s , const std : : string & prefix ) {
return s . size ( ) > = prefix . size ( ) & & s . substr ( 0 , prefix . size ( ) ) = = prefix ;
}
2012-08-24 09:23:50 +02:00
inline bool endsWith ( const std : : string & s , const std : : string & suffix ) {
return s . size ( ) > = suffix . size ( ) & & s . substr ( s . size ( ) - suffix . size ( ) , suffix . size ( ) ) = = suffix ;
}
inline bool contains ( const std : : string & s , const std : : string & infix ) {
return s . find ( infix ) ! = std : : string : : npos ;
}
2013-03-12 19:49:37 +01:00
inline void toLower ( std : : string & s ) {
std : : transform ( s . begin ( ) , s . end ( ) , s . begin ( ) , : : tolower ) ;
}
2012-08-24 09:23:50 +02:00
struct pluralise {
pluralise ( std : : size_t count , const std : : string & label )
: m_count ( count ) ,
m_label ( label )
{ }
friend std : : ostream & operator < < ( std : : ostream & os , const pluralise & pluraliser ) {
os < < pluraliser . m_count < < " " < < pluraliser . m_label ;
if ( pluraliser . m_count ! = 1 )
2012-11-04 22:39:38 +01:00
os < < " s " ;
2012-08-24 09:23:50 +02:00
return os ;
}
std : : size_t m_count ;
std : : string m_label ;
} ;
2012-08-23 21:08:50 +02:00
2012-05-16 16:09:17 +02:00
struct SourceLineInfo {
2012-05-09 20:04:00 +02:00
SourceLineInfo ( ) : line ( 0 ) { }
2012-05-11 20:06:43 +02:00
SourceLineInfo ( const std : : string & _file , std : : size_t _line )
: file ( _file ) ,
line ( _line )
2012-02-15 19:37:21 +01:00
{ }
2012-05-09 20:04:00 +02:00
SourceLineInfo ( const SourceLineInfo & other )
: file ( other . file ) ,
line ( other . line )
{ }
2012-10-28 13:07:17 +01:00
bool empty ( ) const {
return file . empty ( ) ;
}
2012-02-15 19:37:21 +01:00
std : : string file ;
std : : size_t line ;
} ;
2012-05-09 20:04:00 +02:00
inline std : : ostream & operator < < ( std : : ostream & os , const SourceLineInfo & info ) {
2012-02-15 19:37:21 +01:00
# ifndef __GNUG__
2013-01-26 21:18:30 +01:00
os < < info . file < < " ( " < < info . line < < " ): " ;
2012-02-15 19:37:21 +01:00
# else
2013-01-16 10:44:43 +01:00
os < < info . file < < " : " < < info . line ;
2012-02-15 19:37:21 +01:00
# endif
return os ;
}
2012-08-13 08:46:10 +02:00
CATCH_ATTRIBUTE_NORETURN
inline void throwLogicError ( const std : : string & message , const SourceLineInfo & locationInfo ) {
2011-05-24 09:23:02 +02:00
std : : ostringstream oss ;
2013-01-16 10:44:43 +01:00
oss < < locationInfo < < " : Internal Catch error: ' " < < message < < " ' " ;
2011-05-24 09:23:02 +02:00
throw std : : logic_error ( oss . str ( ) ) ;
}
}
2012-08-13 08:46:10 +02:00
# define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) )
# define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO );
2011-05-24 09:23:02 +02:00
2012-08-09 08:47:30 +02:00
# include <ostream>
namespace Catch {
class NotImplementedException : public std : : exception
{
public :
NotImplementedException ( const SourceLineInfo & lineInfo ) ;
virtual ~ NotImplementedException ( ) throw ( ) { }
virtual const char * what ( ) const throw ( ) ;
private :
std : : string m_what ;
SourceLineInfo m_lineInfo ;
} ;
} // end namespace Catch
///////////////////////////////////////////////////////////////////////////////
# define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO )
// #included from: internal/catch_context.h
# define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED
2012-08-31 09:10:36 +02:00
// #included from: catch_interfaces_generators.h
# define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED
2012-08-09 08:47:30 +02:00
2012-08-31 09:10:36 +02:00
# include <string>
2012-02-25 10:39:45 +01:00
2012-05-16 16:09:17 +02:00
namespace Catch {
2012-08-31 09:10:36 +02:00
struct IGeneratorInfo {
virtual ~ IGeneratorInfo ( ) ;
virtual bool moveNext ( ) = 0 ;
virtual std : : size_t getCurrentIndex ( ) const = 0 ;
} ;
2012-02-25 10:39:45 +01:00
2012-08-31 09:10:36 +02:00
struct IGeneratorsForTest {
virtual ~ IGeneratorsForTest ( ) ;
2012-05-11 09:17:16 +02:00
2012-08-31 09:10:36 +02:00
virtual IGeneratorInfo & getGeneratorInfo ( const std : : string & fileInfo , std : : size_t size ) = 0 ;
virtual bool moveNext ( ) = 0 ;
2012-02-25 10:39:45 +01:00
} ;
2012-08-31 09:10:36 +02:00
IGeneratorsForTest * createGeneratorsForTest ( ) ;
2012-05-16 16:09:17 +02:00
2012-08-31 09:10:36 +02:00
} // end namespace Catch
2012-02-25 10:39:45 +01:00
2012-08-31 09:10:36 +02:00
# include <memory>
# include <vector>
# include <stdlib.h>
2012-05-22 09:56:59 +02:00
2012-08-31 09:10:36 +02:00
namespace Catch {
2012-08-16 19:48:50 +02:00
2012-12-02 00:57:18 +01:00
class TestCase ;
2012-09-26 19:38:26 +02:00
class Stream ;
2012-08-31 09:10:36 +02:00
struct IResultCapture ;
struct IRunner ;
struct IGeneratorsForTest ;
struct IConfig ;
struct IContext
{
virtual ~ IContext ( ) ;
virtual IResultCapture & getResultCapture ( ) = 0 ;
virtual IRunner & getRunner ( ) = 0 ;
virtual size_t getGeneratorIndex ( const std : : string & fileInfo , size_t totalSize ) = 0 ;
virtual bool advanceGeneratorsForCurrentTest ( ) = 0 ;
virtual const IConfig * getConfig ( ) const = 0 ;
} ;
struct IMutableContext : IContext
{
virtual ~ IMutableContext ( ) ;
virtual void setResultCapture ( IResultCapture * resultCapture ) = 0 ;
virtual void setRunner ( IRunner * runner ) = 0 ;
virtual void setConfig ( const IConfig * config ) = 0 ;
2012-02-25 10:39:45 +01:00
} ;
2012-08-31 09:10:36 +02:00
IContext & getCurrentContext ( ) ;
IMutableContext & getCurrentMutableContext ( ) ;
void cleanUpContext ( ) ;
2012-09-26 19:38:26 +02:00
Stream createStream ( const std : : string & streamName ) ;
2012-08-31 09:10:36 +02:00
2012-02-25 10:39:45 +01:00
}
2012-08-31 09:10:36 +02:00
// #included from: internal/catch_test_registry.hpp
2012-09-17 07:42:29 +02:00
# define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED
2012-08-31 09:10:36 +02:00
// #included from: catch_interfaces_testcase.h
# define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED
2012-05-05 20:35:35 +02:00
// #included from: catch_ptr.hpp
2012-08-09 08:47:30 +02:00
# define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED
2012-05-05 20:35:35 +02:00
2012-05-16 16:09:17 +02:00
namespace Catch {
2012-05-05 20:35:35 +02:00
// An intrusive reference counting smart pointer.
// T must implement addRef() and release() methods
// typically implementing the IShared interface
template < typename T >
2012-05-16 16:09:17 +02:00
class Ptr {
2012-05-05 20:35:35 +02:00
public :
Ptr ( ) : m_p ( NULL ) { }
Ptr ( T * p ) : m_p ( p ) {
2012-07-28 21:37:07 +02:00
if ( m_p )
m_p - > addRef ( ) ;
2012-05-05 20:35:35 +02:00
}
2012-12-02 00:57:18 +01:00
Ptr ( Ptr const & other ) : m_p ( other . m_p ) {
2012-07-28 21:37:07 +02:00
if ( m_p )
m_p - > addRef ( ) ;
2012-05-05 20:35:35 +02:00
}
~ Ptr ( ) {
if ( m_p )
m_p - > release ( ) ;
}
2012-12-06 09:44:51 +01:00
void reset ( ) {
if ( m_p )
m_p - > release ( ) ;
m_p = NULL ;
}
2012-05-05 20:35:35 +02:00
Ptr & operator = ( T * p ) {
Ptr temp ( p ) ;
swap ( temp ) ;
return * this ;
}
2012-12-02 00:57:18 +01:00
Ptr & operator = ( Ptr const & other ) {
2012-05-05 20:35:35 +02:00
Ptr temp ( other ) ;
swap ( temp ) ;
return * this ;
}
2012-12-02 00:57:18 +01:00
void swap ( Ptr & other ) { std : : swap ( m_p , other . m_p ) ; }
T * get ( ) { return m_p ; }
const T * get ( ) const { return m_p ; }
T & operator * ( ) const { return * m_p ; }
T * operator - > ( ) const { return m_p ; }
bool operator ! ( ) const { return m_p = = NULL ; }
2012-12-06 09:44:51 +01:00
operator SafeBool : : type ( ) const { return SafeBool : : makeSafe ( m_p ! = NULL ) ; }
2012-05-05 20:35:35 +02:00
private :
T * m_p ;
} ;
struct IShared : NonCopyable {
2012-08-13 08:46:10 +02:00
virtual ~ IShared ( ) ;
2012-12-02 00:57:18 +01:00
virtual void addRef ( ) const = 0 ;
virtual void release ( ) const = 0 ;
2012-05-05 20:35:35 +02:00
} ;
2012-12-02 00:57:18 +01:00
template < typename T = IShared >
2012-05-05 20:35:35 +02:00
struct SharedImpl : T {
SharedImpl ( ) : m_rc ( 0 ) { }
2012-12-02 00:57:18 +01:00
virtual void addRef ( ) const {
2012-05-05 20:35:35 +02:00
+ + m_rc ;
}
2012-12-02 00:57:18 +01:00
virtual void release ( ) const {
2012-05-05 20:35:35 +02:00
if ( - - m_rc = = 0 )
delete this ;
}
2012-12-02 00:57:18 +01:00
mutable unsigned int m_rc ;
2012-05-05 20:35:35 +02:00
} ;
} // end namespace Catch
2012-06-03 00:12:42 +02:00
# include <vector>
namespace Catch {
2012-08-23 21:08:50 +02:00
class TestCaseFilters ;
2012-08-16 19:48:50 +02:00
struct ITestCase : IShared {
2012-06-03 00:12:42 +02:00
virtual void invoke ( ) const = 0 ;
2012-08-16 19:48:50 +02:00
protected :
virtual ~ ITestCase ( ) ;
2012-06-03 00:12:42 +02:00
} ;
2012-12-02 00:57:18 +01:00
class TestCase ;
2012-06-03 00:12:42 +02:00
struct ITestCaseRegistry {
2012-08-13 08:46:10 +02:00
virtual ~ ITestCaseRegistry ( ) ;
2012-12-02 00:57:18 +01:00
virtual const std : : vector < TestCase > & getAllTests ( ) const = 0 ;
virtual std : : vector < TestCase > getMatchingTestCases ( const std : : string & rawTestSpec ) const = 0 ;
2012-06-03 00:12:42 +02:00
} ;
}
2012-05-16 16:09:17 +02:00
namespace Catch {
2011-05-24 09:23:02 +02:00
template < typename C >
2012-08-16 19:48:50 +02:00
class MethodTestCase : public SharedImpl < ITestCase > {
2012-05-16 16:09:17 +02:00
2012-05-11 09:17:16 +02:00
public :
MethodTestCase ( void ( C : : * method ) ( ) ) : m_method ( method ) { }
2011-05-24 09:23:02 +02:00
2012-05-11 09:17:16 +02:00
virtual void invoke ( ) const {
2011-05-24 09:23:02 +02:00
C obj ;
( obj . * m_method ) ( ) ;
}
private :
2012-08-16 19:48:50 +02:00
virtual ~ MethodTestCase ( ) { }
2011-05-24 09:23:02 +02:00
void ( C : : * m_method ) ( ) ;
} ;
typedef void ( * TestFunction ) ( ) ;
2012-05-16 16:09:17 +02:00
struct AutoReg {
2012-05-11 09:17:16 +02:00
AutoReg ( TestFunction function ,
const char * name ,
const char * description ,
const SourceLineInfo & lineInfo ) ;
2011-05-24 09:23:02 +02:00
template < typename C >
2012-05-11 09:17:16 +02:00
AutoReg ( void ( C : : * method ) ( ) ,
2012-11-04 22:39:38 +01:00
const char * className ,
2012-05-11 09:17:16 +02:00
const char * name ,
const char * description ,
const SourceLineInfo & lineInfo ) {
2012-11-04 22:39:38 +01:00
registerTestCase ( new MethodTestCase < C > ( method ) , className , name , description , lineInfo ) ;
2011-05-24 09:23:02 +02:00
}
2012-05-11 09:17:16 +02:00
void registerTestCase ( ITestCase * testCase ,
2012-11-04 22:39:38 +01:00
const char * className ,
2012-05-11 09:17:16 +02:00
const char * name ,
const char * description ,
const SourceLineInfo & lineInfo ) ;
2011-05-24 09:23:02 +02:00
2012-05-11 09:17:16 +02:00
~ AutoReg ( ) ;
2011-05-24 09:23:02 +02:00
private :
2012-05-11 09:17:16 +02:00
AutoReg ( const AutoReg & ) ;
void operator = ( const AutoReg & ) ;
2011-05-24 09:23:02 +02:00
} ;
} // end namespace Catch
///////////////////////////////////////////////////////////////////////////////
# define INTERNAL_CATCH_TESTCASE( Name, Desc ) \
2012-05-09 20:04:00 +02:00
static void INTERNAL_CATCH_UNIQUE_NAME ( TestCaseFunction_catch_internal_ ) ( ) ; \
namespace { Catch : : AutoReg INTERNAL_CATCH_UNIQUE_NAME ( autoRegistrar ) ( & INTERNAL_CATCH_UNIQUE_NAME ( TestCaseFunction_catch_internal_ ) , Name , Desc , CATCH_INTERNAL_LINEINFO ) ; } \
static void INTERNAL_CATCH_UNIQUE_NAME ( TestCaseFunction_catch_internal_ ) ( )
2011-05-24 09:23:02 +02:00
///////////////////////////////////////////////////////////////////////////////
# define INTERNAL_CATCH_TESTCASE_NORETURN( Name, Desc ) \
2012-08-13 08:46:10 +02:00
static void INTERNAL_CATCH_UNIQUE_NAME ( TestCaseFunction_catch_internal_ ) ( ) CATCH_ATTRIBUTE_NORETURN ; \
2012-05-09 20:04:00 +02:00
namespace { Catch : : AutoReg INTERNAL_CATCH_UNIQUE_NAME ( autoRegistrar ) ( & INTERNAL_CATCH_UNIQUE_NAME ( TestCaseFunction_catch_internal_ ) , Name , Desc , CATCH_INTERNAL_LINEINFO ) ; } \
static void INTERNAL_CATCH_UNIQUE_NAME ( TestCaseFunction_catch_internal_ ) ( )
2011-05-24 09:23:02 +02:00
///////////////////////////////////////////////////////////////////////////////
2012-07-20 19:43:48 +02:00
# define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \
2012-11-04 22:39:38 +01:00
namespace { Catch : : AutoReg INTERNAL_CATCH_UNIQUE_NAME ( autoRegistrar ) ( & QualifiedMethod , " & " # QualifiedMethod , Name , Desc , CATCH_INTERNAL_LINEINFO ) ; }
2011-05-24 09:23:02 +02:00
///////////////////////////////////////////////////////////////////////////////
# define TEST_CASE_METHOD( ClassName, TestName, Desc )\
2011-12-28 20:56:39 +01:00
namespace { \
2012-05-09 20:04:00 +02:00
struct INTERNAL_CATCH_UNIQUE_NAME ( TestCaseMethod_catch_internal_ ) : ClassName { \
2011-12-28 20:56:39 +01:00
void test ( ) ; \
} ; \
2012-11-04 22:39:38 +01:00
Catch : : AutoReg INTERNAL_CATCH_UNIQUE_NAME ( autoRegistrar ) ( & INTERNAL_CATCH_UNIQUE_NAME ( TestCaseMethod_catch_internal_ ) : : test , # ClassName , TestName , Desc , CATCH_INTERNAL_LINEINFO ) ; \
2011-12-28 20:56:39 +01:00
} \
2012-05-09 20:04:00 +02:00
void INTERNAL_CATCH_UNIQUE_NAME ( TestCaseMethod_catch_internal_ ) : : test ( )
2011-05-24 09:23:02 +02:00
// #included from: internal/catch_capture.hpp
2012-08-09 08:47:30 +02:00
# define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
// #included from: catch_expression_decomposer.hpp
# define TWOBLUECUBES_CATCH_EXPRESSION_DECOMPOSER_HPP_INCLUDED
2012-05-16 16:09:17 +02:00
2012-10-28 13:07:17 +01:00
// #included from: catch_expression_lhs.hpp
# define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED
2012-05-11 09:17:16 +02:00
2012-10-28 13:07:17 +01:00
// #included from: catch_expressionresult_builder.h
# define TWOBLUECUBES_CATCH_ASSERTIONRESULT_BUILDER_H_INCLUDED
2012-05-09 20:04:00 +02:00
// #included from: catch_tostring.hpp
2012-08-09 08:47:30 +02:00
# define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED
2012-05-09 20:04:00 +02:00
# include <sstream>
2013-03-04 12:19:15 +01:00
# include <iomanip>
# include <limits>
2012-05-09 20:04:00 +02:00
2012-08-01 09:17:07 +02:00
# ifdef __OBJC__
// #included from: catch_objc_arc.hpp
2012-08-09 08:47:30 +02:00
# define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED
2012-08-01 09:17:07 +02:00
# import <Foundation / Foundation.h>
# ifdef __has_feature
# define CATCH_ARC_ENABLED __has_feature(objc_arc)
# else
# define CATCH_ARC_ENABLED 0
# endif
void arcSafeRelease ( NSObject * obj ) ;
id performOptionalSelector ( id obj , SEL sel ) ;
# if !CATCH_ARC_ENABLED
inline void arcSafeRelease ( NSObject * obj ) {
[ obj release ] ;
}
inline id performOptionalSelector ( id obj , SEL sel ) {
if ( [ obj respondsToSelector : sel ] )
return [ obj performSelector : sel ] ;
return nil ;
}
# define CATCH_UNSAFE_UNRETAINED
# define CATCH_ARC_STRONG
# else
inline void arcSafeRelease ( NSObject * ) { }
inline id performOptionalSelector ( id obj , SEL sel ) {
2012-08-16 19:48:50 +02:00
# ifdef __clang__
2012-08-01 09:17:07 +02:00
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Warc-performSelector-leaks"
2012-08-16 19:48:50 +02:00
# endif
2012-08-01 09:17:07 +02:00
if ( [ obj respondsToSelector : sel ] )
return [ obj performSelector : sel ] ;
2012-08-16 19:48:50 +02:00
# ifdef __clang__
2012-08-01 09:17:07 +02:00
# pragma clang diagnostic pop
2012-08-16 19:48:50 +02:00
# endif
2012-08-01 09:17:07 +02:00
return nil ;
}
# define CATCH_UNSAFE_UNRETAINED __unsafe_unretained
# define CATCH_ARC_STRONG __strong
# endif
# endif
2012-05-16 16:09:17 +02:00
namespace Catch {
namespace Detail {
2012-05-09 20:04:00 +02:00
struct NonStreamable {
template < typename T > NonStreamable ( const T & ) { }
} ;
2013-03-04 12:19:15 +01:00
} // end namespace Detail
2012-05-09 20:04:00 +02:00
2013-03-04 12:19:15 +01:00
// If the type does not have its own << overload for ostream then
// this one will be used instead
inline std : : ostream & operator < < ( std : : ostream & ss , Detail : : NonStreamable ) {
return ss < < " {?} " ;
}
template < typename T >
struct StringMaker {
static std : : string convert ( T const & value ) {
2012-05-09 20:04:00 +02:00
std : : ostringstream oss ;
oss < < value ;
return oss . str ( ) ;
}
2013-03-04 12:19:15 +01:00
} ;
template < typename T >
struct StringMaker < T * > {
static std : : string convert ( T const * p ) {
2012-05-09 20:04:00 +02:00
if ( ! p )
return INTERNAL_CATCH_STRINGIFY ( NULL ) ;
std : : ostringstream oss ;
oss < < p ;
return oss . str ( ) ;
}
2013-03-04 12:19:15 +01:00
} ;
2012-05-09 20:04:00 +02:00
2013-03-04 12:19:15 +01:00
template < typename T >
struct StringMaker < std : : vector < T > > {
static std : : string convert ( std : : vector < T > const & v ) {
2012-05-09 20:04:00 +02:00
std : : ostringstream oss ;
2013-03-04 12:19:15 +01:00
oss < < " { " ;
for ( std : : size_t i = 0 ; i < v . size ( ) ; + + i ) {
oss < < v [ i ] ;
if ( i < v . size ( ) - 1 )
oss < < " , " ;
}
oss < < " } " ;
2012-05-09 20:04:00 +02:00
return oss . str ( ) ;
}
2013-03-04 12:19:15 +01:00
} ;
2012-05-09 20:04:00 +02:00
2013-03-04 12:19:15 +01:00
namespace Detail {
template < typename T >
inline std : : string makeString ( const T & value ) {
return StringMaker < T > : : convert ( value ) ;
}
2012-05-09 20:04:00 +02: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 >
std : : string toString ( const T & value ) {
2013-03-04 12:19:15 +01:00
return StringMaker < T > : : convert ( value ) ;
// return Detail::makeString( value );
2012-05-09 20:04:00 +02:00
}
// Built in overloads
inline std : : string toString ( const std : : string & value ) {
return " \" " + value + " \" " ;
}
inline std : : string toString ( const std : : wstring & value ) {
std : : ostringstream oss ;
oss < < " \" " ;
for ( size_t i = 0 ; i < value . size ( ) ; + + i )
oss < < static_cast < char > ( value [ i ] < = 0xff ? value [ i ] : ' ? ' ) ;
oss < < " \" " ;
return oss . str ( ) ;
}
inline std : : string toString ( const char * const value ) {
return value ? Catch : : toString ( std : : string ( value ) ) : std : : string ( " {null string} " ) ;
}
inline std : : string toString ( char * const value ) {
return Catch : : toString ( static_cast < const char * > ( value ) ) ;
}
inline std : : string toString ( int value ) {
std : : ostringstream oss ;
oss < < value ;
return oss . str ( ) ;
}
inline std : : string toString ( unsigned long value ) {
std : : ostringstream oss ;
if ( value > 8192 )
oss < < " 0x " < < std : : hex < < value ;
else
oss < < value ;
return oss . str ( ) ;
}
inline std : : string toString ( unsigned int value ) {
2012-05-11 20:06:43 +02:00
return toString ( static_cast < unsigned long > ( value ) ) ;
2012-05-09 20:04:00 +02:00
}
inline std : : string toString ( const double value ) {
std : : ostringstream oss ;
2013-03-04 12:19:15 +01:00
oss < < std : : setprecision ( std : : numeric_limits < double > : : digits10 + 1 )
< < value ;
2012-05-09 20:04:00 +02:00
return oss . str ( ) ;
}
inline std : : string toString ( bool value ) {
return value ? " true " : " false " ;
}
2012-06-06 09:06:40 +02:00
inline std : : string toString ( char value ) {
return value < ' '
2012-12-14 08:50:08 +01:00
? toString ( static_cast < unsigned int > ( value ) )
2012-06-06 09:06:40 +02:00
: Detail : : makeString ( value ) ;
}
inline std : : string toString ( signed char value ) {
return toString ( static_cast < char > ( value ) ) ;
}
2012-12-14 08:50:08 +01:00
inline std : : string toString ( unsigned char value ) {
return toString ( static_cast < char > ( value ) ) ;
}
2012-05-11 09:17:16 +02:00
# ifdef CATCH_CONFIG_CPP11_NULLPTR
2012-05-25 09:52:05 +02:00
inline std : : string toString ( std : : nullptr_t ) {
2012-05-11 09:17:16 +02:00
return " nullptr " ;
}
# endif
2012-08-01 09:17:07 +02:00
# ifdef __OBJC__
inline std : : string toString ( NSString const * const & nsstring ) {
2013-03-12 19:49:37 +01:00
if ( ! nsstring )
return " nil " ;
2012-08-01 09:17:07 +02:00
return std : : string ( " @ \" " ) + [ nsstring UTF8String ] + " \" " ;
}
inline std : : string toString ( NSString * CATCH_ARC_STRONG const & nsstring ) {
2013-03-12 19:49:37 +01:00
if ( ! nsstring )
return " nil " ;
2012-08-01 09:17:07 +02:00
return std : : string ( " @ \" " ) + [ nsstring UTF8String ] + " \" " ;
}
inline std : : string toString ( NSObject * const & nsObject ) {
return toString ( [ nsObject description ] ) ;
}
# endif
2012-05-09 20:04:00 +02:00
} // end namespace Catch
2012-10-28 13:07:17 +01:00
// #included from: catch_assertionresult.h
# define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED
2011-05-24 09:23:02 +02:00
# include <string>
// #included from: catch_result_type.h
2012-08-09 08:47:30 +02:00
# define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED
2011-05-24 09:23:02 +02:00
2012-05-16 16:09:17 +02:00
namespace Catch {
2011-05-24 09:23:02 +02:00
2012-11-13 22:46:01 +01:00
// ResultWas::OfType enum
2012-11-10 19:46:39 +01:00
struct ResultWas { enum OfType {
Unknown = - 1 ,
Ok = 0 ,
Info = 1 ,
Warning = 2 ,
2011-05-24 09:23:02 +02:00
2012-11-10 19:46:39 +01:00
FailureBit = 0x10 ,
2011-05-24 09:23:02 +02:00
2012-11-10 19:46:39 +01:00
ExpressionFailed = FailureBit | 1 ,
ExplicitFailure = FailureBit | 2 ,
2011-05-24 09:23:02 +02:00
2012-11-10 19:46:39 +01:00
Exception = 0x100 | FailureBit ,
2011-05-24 09:23:02 +02:00
2012-11-10 19:46:39 +01:00
ThrewException = Exception | 1 ,
DidntThrowException = Exception | 2
2011-05-24 09:23:02 +02:00
2012-11-10 19:46:39 +01:00
} ; } ;
2011-05-24 09:23:02 +02:00
2012-11-10 19:46:39 +01:00
inline bool isOk ( ResultWas : : OfType resultType ) {
return ( resultType & ResultWas : : FailureBit ) = = 0 ;
}
2013-02-02 21:37:58 +01:00
inline bool isJustInfo ( int flags ) {
return flags = = ResultWas : : Info ;
}
2012-10-09 12:48:55 +02:00
2012-11-13 22:46:01 +01:00
// ResultAction::Value enum
2012-11-10 19:46:39 +01:00
struct ResultAction { enum Value {
None ,
Failed = 1 , // Failure - but no debug break if Debug bit not set
Debug = 2 , // If this bit is set, invoke the debugger
Abort = 4 // Test run should abort
} ; } ;
2011-05-24 09:23:02 +02:00
2012-11-13 22:46:01 +01:00
// ResultDisposition::Flags enum
struct ResultDisposition { enum Flags {
2012-11-10 19:46:39 +01:00
Normal = 0x00 ,
2012-11-13 22:46:01 +01:00
ContinueOnFailure = 0x01 , // Failures fail test, but execution continues
NegateResult = 0x02 , // Prefix expressiom with !
SuppressFail = 0x04 // Failures are reported but do not fail the test
} ; } ;
2012-11-10 19:46:39 +01:00
inline ResultDisposition : : Flags operator | ( ResultDisposition : : Flags lhs , ResultDisposition : : Flags rhs ) {
return static_cast < ResultDisposition : : Flags > ( static_cast < int > ( lhs ) | static_cast < int > ( rhs ) ) ;
}
2012-11-17 11:49:24 +01:00
inline bool shouldContinueOnFailure ( int flags ) { return ( flags & ResultDisposition : : ContinueOnFailure ) ! = 0 ; }
inline bool shouldNegate ( int flags ) { return ( flags & ResultDisposition : : NegateResult ) ! = 0 ; }
inline bool shouldSuppressFailure ( int flags ) { return ( flags & ResultDisposition : : SuppressFail ) ! = 0 ; }
2012-11-10 19:46:39 +01:00
} // end namespace Catch
2011-05-24 09:23:02 +02:00
2012-05-16 16:09:17 +02:00
namespace Catch {
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
struct AssertionInfo
2012-10-09 12:48:55 +02:00
{
2012-10-28 13:07:17 +01:00
AssertionInfo ( ) { }
2012-11-13 10:44:52 +01:00
AssertionInfo ( const std : : string & _macroName ,
const SourceLineInfo & _lineInfo ,
const std : : string & _capturedExpression ,
ResultDisposition : : Flags _resultDisposition ) ;
2012-10-09 12:48:55 +02:00
std : : string macroName ;
SourceLineInfo lineInfo ;
std : : string capturedExpression ;
2012-11-13 10:44:52 +01:00
ResultDisposition : : Flags resultDisposition ;
2012-10-28 13:07:17 +01:00
} ;
struct AssertionResultData
{
AssertionResultData ( ) : resultType ( ResultWas : : Unknown ) { }
2012-10-09 12:48:55 +02:00
std : : string reconstructedExpression ;
std : : string message ;
ResultWas : : OfType resultType ;
} ;
2012-10-28 13:07:17 +01:00
class AssertionResult {
2012-05-16 16:09:17 +02:00
public :
2012-10-28 13:07:17 +01:00
AssertionResult ( ) ;
AssertionResult ( const AssertionInfo & info , const AssertionResultData & data ) ;
~ AssertionResult ( ) ;
2012-08-09 08:47:30 +02:00
2012-11-13 10:44:52 +01:00
bool isOk ( ) const ;
bool succeeded ( ) const ;
2012-08-09 08:47:30 +02:00
ResultWas : : OfType getResultType ( ) const ;
bool hasExpression ( ) const ;
bool hasMessage ( ) const ;
std : : string getExpression ( ) const ;
bool hasExpandedExpression ( ) const ;
std : : string getExpandedExpression ( ) const ;
std : : string getMessage ( ) const ;
2012-10-28 13:07:17 +01:00
SourceLineInfo getSourceInfo ( ) const ;
2012-08-09 08:47:30 +02:00
std : : string getTestMacroName ( ) const ;
2011-05-24 09:23:02 +02:00
protected :
2012-10-28 13:07:17 +01:00
AssertionInfo m_info ;
AssertionResultData m_resultData ;
2011-05-24 09:23:02 +02:00
} ;
} // end namespace Catch
// #included from: catch_evaluate.hpp
2012-08-09 08:47:30 +02:00
# define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED
2011-05-24 09:23:02 +02:00
2012-05-16 16:09:17 +02:00
namespace Catch {
namespace Internal {
enum Operator {
2011-05-24 09:23:02 +02:00
IsEqualTo ,
IsNotEqualTo ,
IsLessThan ,
IsGreaterThan ,
IsLessThanOrEqualTo ,
IsGreaterThanOrEqualTo
} ;
2012-05-21 19:52:09 +02:00
template < Operator Op > struct OperatorTraits { static const char * getName ( ) { return " *error* " ; } } ;
template < > struct OperatorTraits < IsEqualTo > { static const char * getName ( ) { return " == " ; } } ;
template < > struct OperatorTraits < IsNotEqualTo > { static const char * getName ( ) { return " != " ; } } ;
template < > struct OperatorTraits < IsLessThan > { static const char * getName ( ) { return " < " ; } } ;
template < > struct OperatorTraits < IsGreaterThan > { static const char * getName ( ) { return " > " ; } } ;
template < > struct OperatorTraits < IsLessThanOrEqualTo > { static const char * getName ( ) { return " <= " ; } } ;
template < > struct OperatorTraits < IsGreaterThanOrEqualTo > { static const char * getName ( ) { return " >= " ; } } ;
2011-05-24 09:23:02 +02:00
// So the compare overloads can be operator agnostic we convey the operator as a template
// enum, which is used to specialise an Evaluator for doing the comparison.
template < typename T1 , typename T2 , Operator Op >
class Evaluator { } ;
template < typename T1 , typename T2 >
2012-05-16 16:09:17 +02:00
struct Evaluator < T1 , T2 , IsEqualTo > {
static bool evaluate ( const T1 & lhs , const T2 & rhs ) {
2012-05-09 20:04:00 +02:00
return const_cast < T1 & > ( lhs ) = = const_cast < T2 & > ( rhs ) ;
2011-05-24 09:23:02 +02:00
}
} ;
template < typename T1 , typename T2 >
2012-05-16 16:09:17 +02:00
struct Evaluator < T1 , T2 , IsNotEqualTo > {
static bool evaluate ( const T1 & lhs , const T2 & rhs ) {
2011-05-24 09:23:02 +02:00
return const_cast < T1 & > ( lhs ) ! = const_cast < T2 & > ( rhs ) ;
}
} ;
template < typename T1 , typename T2 >
2012-05-16 16:09:17 +02:00
struct Evaluator < T1 , T2 , IsLessThan > {
static bool evaluate ( const T1 & lhs , const T2 & rhs ) {
2011-05-24 09:23:02 +02:00
return const_cast < T1 & > ( lhs ) < const_cast < T2 & > ( rhs ) ;
}
} ;
template < typename T1 , typename T2 >
2012-05-16 16:09:17 +02:00
struct Evaluator < T1 , T2 , IsGreaterThan > {
static bool evaluate ( const T1 & lhs , const T2 & rhs ) {
2011-05-24 09:23:02 +02:00
return const_cast < T1 & > ( lhs ) > const_cast < T2 & > ( rhs ) ;
}
} ;
template < typename T1 , typename T2 >
2012-05-16 16:09:17 +02:00
struct Evaluator < T1 , T2 , IsGreaterThanOrEqualTo > {
static bool evaluate ( const T1 & lhs , const T2 & rhs ) {
2011-05-24 09:23:02 +02:00
return const_cast < T1 & > ( lhs ) > = const_cast < T2 & > ( rhs ) ;
}
} ;
template < typename T1 , typename T2 >
2012-05-16 16:09:17 +02:00
struct Evaluator < T1 , T2 , IsLessThanOrEqualTo > {
static bool evaluate ( const T1 & lhs , const T2 & rhs ) {
2011-05-24 09:23:02 +02:00
return const_cast < T1 & > ( lhs ) < = const_cast < T2 & > ( rhs ) ;
}
} ;
template < Operator Op , typename T1 , typename T2 >
2012-05-16 16:09:17 +02:00
bool applyEvaluator ( const T1 & lhs , const T2 & rhs ) {
2011-05-24 09:23:02 +02:00
return Evaluator < T1 , T2 , Op > : : evaluate ( lhs , rhs ) ;
}
2012-11-06 20:13:25 +01:00
// This level of indirection allows us to specialise for integer types
// to avoid signed/ unsigned warnings
2011-05-24 09:23:02 +02:00
// "base" overload
template < Operator Op , typename T1 , typename T2 >
2012-05-16 16:09:17 +02:00
bool compare ( const T1 & lhs , const T2 & rhs ) {
2011-05-24 09:23:02 +02:00
return Evaluator < T1 , T2 , Op > : : evaluate ( lhs , rhs ) ;
}
// unsigned X to int
2012-05-16 16:09:17 +02:00
template < Operator Op > bool compare ( unsigned int lhs , int rhs ) {
2011-05-24 09:23:02 +02:00
return applyEvaluator < Op > ( lhs , static_cast < unsigned int > ( rhs ) ) ;
}
2012-05-16 16:09:17 +02:00
template < Operator Op > bool compare ( unsigned long lhs , int rhs ) {
2011-05-24 09:23:02 +02:00
return applyEvaluator < Op > ( lhs , static_cast < unsigned int > ( rhs ) ) ;
}
2012-05-16 16:09:17 +02:00
template < Operator Op > bool compare ( unsigned char lhs , int rhs ) {
2011-05-24 09:23:02 +02:00
return applyEvaluator < Op > ( lhs , static_cast < unsigned int > ( rhs ) ) ;
}
// unsigned X to long
2012-05-16 16:09:17 +02:00
template < Operator Op > bool compare ( unsigned int lhs , long rhs ) {
2011-05-24 09:23:02 +02:00
return applyEvaluator < Op > ( lhs , static_cast < unsigned long > ( rhs ) ) ;
}
2012-05-16 16:09:17 +02:00
template < Operator Op > bool compare ( unsigned long lhs , long rhs ) {
2011-05-24 09:23:02 +02:00
return applyEvaluator < Op > ( lhs , static_cast < unsigned long > ( rhs ) ) ;
}
2012-05-16 16:09:17 +02:00
template < Operator Op > bool compare ( unsigned char lhs , long rhs ) {
2011-05-24 09:23:02 +02:00
return applyEvaluator < Op > ( lhs , static_cast < unsigned long > ( rhs ) ) ;
}
// int to unsigned X
2012-05-16 16:09:17 +02:00
template < Operator Op > bool compare ( int lhs , unsigned int rhs ) {
2011-05-24 09:23:02 +02:00
return applyEvaluator < Op > ( static_cast < unsigned int > ( lhs ) , rhs ) ;
}
2012-05-16 16:09:17 +02:00
template < Operator Op > bool compare ( int lhs , unsigned long rhs ) {
2011-05-24 09:23:02 +02:00
return applyEvaluator < Op > ( static_cast < unsigned int > ( lhs ) , rhs ) ;
}
2012-05-16 16:09:17 +02:00
template < Operator Op > bool compare ( int lhs , unsigned char rhs ) {
2011-05-24 09:23:02 +02:00
return applyEvaluator < Op > ( static_cast < unsigned int > ( lhs ) , rhs ) ;
}
// long to unsigned X
2012-05-16 16:09:17 +02:00
template < Operator Op > bool compare ( long lhs , unsigned int rhs ) {
2012-04-27 19:42:40 +02:00
return applyEvaluator < Op > ( static_cast < unsigned long > ( lhs ) , rhs ) ;
2011-05-24 09:23:02 +02:00
}
2012-05-16 16:09:17 +02:00
template < Operator Op > bool compare ( long lhs , unsigned long rhs ) {
2012-04-27 19:42:40 +02:00
return applyEvaluator < Op > ( static_cast < unsigned long > ( lhs ) , rhs ) ;
2011-05-24 09:23:02 +02:00
}
2012-05-16 16:09:17 +02:00
template < Operator Op > bool compare ( long lhs , unsigned char rhs ) {
2012-04-27 19:42:40 +02:00
return applyEvaluator < Op > ( static_cast < unsigned long > ( lhs ) , rhs ) ;
2011-05-24 09:23:02 +02:00
}
2012-05-25 09:52:05 +02:00
// pointer to long (when comparing against NULL)
2012-11-06 20:13:25 +01:00
template < Operator Op , typename T > bool compare ( long lhs , T * rhs ) {
2011-05-24 09:23:02 +02:00
return Evaluator < T * , T * , Op > : : evaluate ( reinterpret_cast < T * > ( lhs ) , rhs ) ;
2012-05-07 20:46:19 +02:00
}
2012-11-06 20:13:25 +01:00
template < Operator Op , typename T > bool compare ( T * lhs , long rhs ) {
2012-05-07 20:46:19 +02:00
return Evaluator < T * , T * , Op > : : evaluate ( lhs , reinterpret_cast < T * > ( rhs ) ) ;
2011-05-24 09:23:02 +02:00
}
2012-05-25 09:52:05 +02:00
// pointer to int (when comparing against NULL)
2012-11-06 20:13:25 +01:00
template < Operator Op , typename T > bool compare ( int lhs , T * rhs ) {
2012-05-25 09:52:05 +02:00
return Evaluator < T * , T * , Op > : : evaluate ( reinterpret_cast < T * > ( lhs ) , rhs ) ;
}
2012-11-06 20:13:25 +01:00
template < Operator Op , typename T > bool compare ( T * lhs , int rhs ) {
2012-05-25 09:52:05 +02:00
return Evaluator < T * , T * , Op > : : evaluate ( lhs , reinterpret_cast < T * > ( rhs ) ) ;
}
2011-05-24 09:23:02 +02:00
} // end of namespace Internal
} // end of namespace Catch
2012-05-16 16:09:17 +02:00
namespace Catch {
2011-12-28 11:37:31 +01:00
2012-10-28 13:07:17 +01:00
// Wraps the (stringised versions of) the lhs, operator and rhs of an expression - as well as
// the result of evaluating it. This is used to build an AssertionResult object
class ExpressionResultBuilder {
2011-05-24 09:23:02 +02:00
public :
2012-10-28 13:07:17 +01:00
ExpressionResultBuilder ( ResultWas : : OfType resultType = ResultWas : : Unknown ) ;
ExpressionResultBuilder ( const ExpressionResultBuilder & other ) ;
ExpressionResultBuilder & operator = ( const ExpressionResultBuilder & other ) ;
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
ExpressionResultBuilder & setResultType ( ResultWas : : OfType result ) ;
ExpressionResultBuilder & setResultType ( bool result ) ;
ExpressionResultBuilder & setLhs ( const std : : string & lhs ) ;
ExpressionResultBuilder & setRhs ( const std : : string & rhs ) ;
ExpressionResultBuilder & setOp ( const std : : string & op ) ;
2012-03-04 22:22:36 +01:00
2012-11-10 19:46:39 +01:00
ExpressionResultBuilder & endExpression ( ResultDisposition : : Flags resultDisposition ) ;
2012-10-09 12:48:55 +02:00
2012-10-28 13:07:17 +01:00
template < typename T >
ExpressionResultBuilder & operator < < ( const T & value ) {
m_stream < < value ;
return * this ;
}
2012-10-09 12:48:55 +02:00
2012-10-28 13:07:17 +01:00
std : : string reconstructExpression ( const AssertionInfo & info ) const ;
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
AssertionResult buildResult ( const AssertionInfo & info ) const ;
2011-05-24 09:23:02 +02:00
2012-10-09 12:48:55 +02:00
private :
2012-10-28 13:07:17 +01:00
AssertionResultData m_data ;
struct ExprComponents {
ExprComponents ( ) : shouldNegate ( false ) { }
bool shouldNegate ;
std : : string lhs , rhs , op ;
} m_exprComponents ;
std : : ostringstream m_stream ;
2011-05-24 09:23:02 +02:00
} ;
2012-05-09 20:04:00 +02:00
} // end namespace Catch
2012-05-16 16:09:17 +02:00
namespace Catch {
2012-05-11 09:17:16 +02:00
2012-10-28 21:57:21 +01:00
struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison ;
2012-10-28 13:07:17 +01:00
// Wraps the LHS of an expression and captures the operator and RHS (if any) - wrapping them all
// in an ExpressionResultBuilder object
2012-05-11 09:17:16 +02:00
template < typename T >
2012-10-28 13:07:17 +01:00
class ExpressionLhs {
2013-03-08 10:30:25 +01:00
void operator = ( const ExpressionLhs & ) ;
2012-05-11 09:17:16 +02:00
public :
2012-11-16 10:47:33 +01:00
ExpressionLhs ( T lhs ) : m_lhs ( lhs ) { }
2012-05-11 09:17:16 +02:00
template < typename RhsT >
2012-10-28 13:07:17 +01:00
ExpressionResultBuilder & operator = = ( const RhsT & rhs ) {
2012-10-09 21:58:33 +02:00
return captureExpression < Internal : : IsEqualTo > ( rhs ) ;
2012-05-11 09:17:16 +02:00
}
template < typename RhsT >
2012-10-28 13:07:17 +01:00
ExpressionResultBuilder & operator ! = ( const RhsT & rhs ) {
2012-10-09 21:58:33 +02:00
return captureExpression < Internal : : IsNotEqualTo > ( rhs ) ;
2012-05-11 09:17:16 +02:00
}
template < typename RhsT >
2012-10-28 13:07:17 +01:00
ExpressionResultBuilder & operator < ( const RhsT & rhs ) {
2012-10-09 21:58:33 +02:00
return captureExpression < Internal : : IsLessThan > ( rhs ) ;
2012-05-11 09:17:16 +02:00
}
template < typename RhsT >
2012-10-28 13:07:17 +01:00
ExpressionResultBuilder & operator > ( const RhsT & rhs ) {
2012-10-09 21:58:33 +02:00
return captureExpression < Internal : : IsGreaterThan > ( rhs ) ;
2012-05-11 09:17:16 +02:00
}
template < typename RhsT >
2012-10-28 13:07:17 +01:00
ExpressionResultBuilder & operator < = ( const RhsT & rhs ) {
2012-10-09 21:58:33 +02:00
return captureExpression < Internal : : IsLessThanOrEqualTo > ( rhs ) ;
2012-05-11 09:17:16 +02:00
}
template < typename RhsT >
2012-10-28 13:07:17 +01:00
ExpressionResultBuilder & operator > = ( const RhsT & rhs ) {
2012-10-09 21:58:33 +02:00
return captureExpression < Internal : : IsGreaterThanOrEqualTo > ( rhs ) ;
2012-05-11 09:17:16 +02:00
}
2012-10-28 13:07:17 +01:00
ExpressionResultBuilder & operator = = ( bool rhs ) {
2012-10-09 21:58:33 +02:00
return captureExpression < Internal : : IsEqualTo > ( rhs ) ;
2012-05-11 09:17:16 +02:00
}
2012-10-28 13:07:17 +01:00
ExpressionResultBuilder & operator ! = ( bool rhs ) {
2012-10-09 21:58:33 +02:00
return captureExpression < Internal : : IsNotEqualTo > ( rhs ) ;
2012-05-11 09:17:16 +02:00
}
2012-11-10 19:46:39 +01:00
ExpressionResultBuilder & endExpression ( ResultDisposition : : Flags resultDisposition ) {
2012-10-28 21:57:21 +01:00
bool value = m_lhs ? true : false ;
return m_result
. setLhs ( Catch : : toString ( value ) )
. setResultType ( value )
2012-11-10 19:46:39 +01:00
. endExpression ( resultDisposition ) ;
2012-05-11 09:17:16 +02:00
}
2012-10-28 13:07:17 +01:00
// Only simple binary expressions are allowed on the LHS.
// If more complex compositions are required then place the sub expression in parentheses
template < typename RhsT > STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison & operator + ( const RhsT & ) ;
template < typename RhsT > STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison & operator - ( const RhsT & ) ;
template < typename RhsT > STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison & operator / ( const RhsT & ) ;
template < typename RhsT > STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison & operator * ( const RhsT & ) ;
2012-05-11 09:17:16 +02:00
2012-10-09 21:58:33 +02:00
private :
template < Internal : : Operator Op , typename RhsT >
2012-10-28 13:07:17 +01:00
ExpressionResultBuilder & captureExpression ( const RhsT & rhs ) {
2012-10-09 21:58:33 +02:00
return m_result
2012-10-28 13:07:17 +01:00
. setResultType ( Internal : : compare < Op > ( m_lhs , rhs ) )
2012-10-28 21:57:21 +01:00
. setLhs ( Catch : : toString ( m_lhs ) )
2012-10-09 21:58:33 +02:00
. setRhs ( Catch : : toString ( rhs ) )
. setOp ( Internal : : OperatorTraits < Op > : : getName ( ) ) ;
}
2012-05-11 09:17:16 +02:00
private :
2012-10-28 13:07:17 +01:00
ExpressionResultBuilder m_result ;
2012-05-11 09:17:16 +02:00
T m_lhs ;
} ;
} // end namespace Catch
2012-05-16 16:09:17 +02:00
namespace Catch {
2012-10-28 13:07:17 +01:00
// Captures the LHS of the expression and wraps it in an Expression Lhs object
class ExpressionDecomposer {
2012-05-16 16:09:17 +02:00
public :
template < typename T >
2012-10-28 13:07:17 +01:00
ExpressionLhs < const T & > operator - > * ( const T & operand ) {
return ExpressionLhs < const T & > ( operand ) ;
2012-05-16 16:09:17 +02:00
}
2012-10-28 13:07:17 +01:00
ExpressionLhs < bool > operator - > * ( bool value ) {
return ExpressionLhs < bool > ( value ) ;
2012-05-16 16:09:17 +02:00
}
} ;
} // end namespace Catch
2013-02-02 21:37:58 +01:00
// #included from: catch_message.h
# define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED
# include <string>
namespace Catch {
struct MessageInfo {
MessageInfo ( std : : string const & _macroName ,
SourceLineInfo const & _lineInfo ,
ResultWas : : OfType _type ) ;
std : : string macroName ;
SourceLineInfo lineInfo ;
ResultWas : : OfType type ;
std : : string message ;
unsigned int sequence ;
bool operator = = ( MessageInfo const & other ) const {
return sequence = = other . sequence ;
}
bool operator < ( MessageInfo const & other ) const {
return sequence < other . sequence ;
}
private :
static unsigned int globalCount ;
} ;
class MessageBuilder : public MessageInfo {
public :
MessageBuilder ( std : : string const & _macroName ,
SourceLineInfo const & _lineInfo ,
ResultWas : : OfType _type ) ;
MessageInfo build ( ) const ;
template < typename T >
MessageBuilder & operator < < ( T const & _value ) {
stream < < _value ;
return * this ;
}
private :
std : : ostringstream stream ;
} ;
class ScopedMessageBuilder : public MessageBuilder {
public :
ScopedMessageBuilder ( std : : string const & _macroName ,
SourceLineInfo const & _lineInfo ,
ResultWas : : OfType _type ) ;
~ ScopedMessageBuilder ( ) ;
} ;
} // end namespace Catch
2012-05-09 20:04:00 +02:00
// #included from: catch_interfaces_capture.h
2012-08-09 08:47:30 +02:00
# define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED
2012-05-09 20:04:00 +02:00
# include <string>
2012-08-31 09:10:36 +02:00
// #included from: catch_totals.hpp
# define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED
2012-05-09 20:04:00 +02:00
2012-09-29 21:54:03 +02:00
# include <cstddef>
2012-05-16 16:09:17 +02:00
namespace Catch {
2012-08-31 09:10:36 +02:00
struct Counts {
2013-02-02 21:37:58 +01:00
Counts ( ) : passed ( 0 ) , failed ( 0 ) { }
2012-08-31 09:10:36 +02:00
Counts operator - ( const Counts & other ) const {
Counts diff ;
diff . passed = passed - other . passed ;
diff . failed = failed - other . failed ;
return diff ;
}
Counts & operator + = ( const Counts & other ) {
passed + = other . passed ;
failed + = other . failed ;
return * this ;
}
std : : size_t total ( ) const {
return passed + failed ;
}
std : : size_t passed ;
std : : size_t failed ;
} ;
struct Totals {
Totals operator - ( const Totals & other ) const {
Totals diff ;
diff . assertions = assertions - other . assertions ;
diff . testCases = testCases - other . testCases ;
return diff ;
}
Totals delta ( const Totals & prevTotals ) const {
Totals diff = * this - prevTotals ;
if ( diff . assertions . failed > 0 )
+ + diff . testCases . failed ;
else
+ + diff . testCases . passed ;
return diff ;
}
Totals & operator + = ( const Totals & other ) {
assertions + = other . assertions ;
testCases + = other . testCases ;
return * this ;
}
Counts assertions ;
Counts testCases ;
} ;
}
namespace Catch {
2012-12-02 00:57:18 +01:00
class TestCase ;
2012-10-28 13:07:17 +01:00
class ExpressionResultBuilder ;
class AssertionResult ;
struct AssertionInfo ;
2012-12-02 00:57:18 +01:00
struct SectionInfo ;
2013-02-02 21:37:58 +01:00
class MessageBuilder ;
class ScopedMessageBuilder ;
2012-08-31 09:10:36 +02:00
struct IResultCapture {
2012-05-09 20:04:00 +02:00
2012-08-13 08:46:10 +02:00
virtual ~ IResultCapture ( ) ;
2012-05-09 20:04:00 +02:00
2013-02-02 21:37:58 +01:00
virtual void assertionEnded ( AssertionResult const & result ) = 0 ;
2012-12-02 00:57:18 +01:00
virtual bool sectionStarted ( SectionInfo const & sectionInfo ,
2012-05-16 16:09:17 +02:00
Counts & assertions ) = 0 ;
2012-12-02 00:57:18 +01:00
virtual void sectionEnded ( SectionInfo const & name , Counts const & assertions ) = 0 ;
2013-02-02 21:37:58 +01:00
virtual void pushScopedMessage ( ScopedMessageBuilder const & _builder ) = 0 ;
virtual void popScopedMessage ( ScopedMessageBuilder const & _builder ) = 0 ;
2012-05-16 16:09:17 +02:00
virtual bool shouldDebugBreak ( ) const = 0 ;
2013-02-02 21:37:58 +01:00
virtual void acceptMessage ( const MessageBuilder & messageBuilder ) = 0 ;
2012-12-02 00:57:18 +01:00
virtual ResultAction : : Value acceptExpression ( ExpressionResultBuilder const & assertionResult , AssertionInfo const & assertionInfo ) = 0 ;
2012-05-16 16:09:17 +02:00
virtual std : : string getCurrentTestName ( ) const = 0 ;
2012-10-28 13:07:17 +01:00
virtual const AssertionResult * getLastResult ( ) const = 0 ;
2012-05-09 20:04:00 +02:00
} ;
}
// #included from: catch_debugger.hpp
2012-08-09 08:47:30 +02:00
# define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED
2012-05-09 20:04:00 +02:00
# include <iostream>
# if defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
# define CATCH_PLATFORM_MAC
# elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
# define CATCH_PLATFORM_IPHONE
# elif defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
# define CATCH_PLATFORM_WINDOWS
# endif
# ifdef CATCH_PLATFORM_MAC
# include <assert.h>
# include <stdbool.h>
# include <sys/types.h>
# include <unistd.h>
# include <sys/sysctl.h>
2012-05-16 16:09:17 +02:00
namespace Catch {
2012-05-09 20:04:00 +02:00
// The following function is taken directly from the following technical note:
// http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html
// Returns true if the current process is being debugged (either
// running under the debugger or has a debugger attached post facto).
2012-05-16 16:09:17 +02:00
inline bool isDebuggerActive ( ) {
2012-05-09 20:04:00 +02:00
int junk ;
int mib [ 4 ] ;
struct kinfo_proc info ;
size_t size ;
// Initialize the flags so that, if sysctl fails for some bizarre
// reason, we get a predictable result.
info . kp_proc . p_flag = 0 ;
// Initialize mib, which tells sysctl the info we want, in this case
// we're looking for information about a specific process ID.
mib [ 0 ] = CTL_KERN ;
mib [ 1 ] = KERN_PROC ;
mib [ 2 ] = KERN_PROC_PID ;
mib [ 3 ] = getpid ( ) ;
// Call sysctl.
size = sizeof ( info ) ;
junk = sysctl ( mib , sizeof ( mib ) / sizeof ( * mib ) , & info , & size , NULL , 0 ) ;
assert ( junk = = 0 ) ;
// We're being debugged if the P_TRACED flag is set.
return ( ( info . kp_proc . p_flag & P_TRACED ) ! = 0 ) ;
}
}
// The following code snippet taken from:
// http://cocoawithlove.com/2008/03/break-into-debugger.html
# ifdef DEBUG
# if defined(__ppc64__) || defined(__ppc__)
# define BreakIntoDebugger() \
2012-05-16 16:09:17 +02:00
if ( Catch : : isDebuggerActive ( ) ) { \
2012-05-09 20:04:00 +02:00
__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 BreakIntoDebugger() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );}
# endif
# else
inline void BreakIntoDebugger ( ) { }
# endif
# elif defined(_MSC_VER)
extern " C " __declspec ( dllimport ) int __stdcall IsDebuggerPresent ( ) ;
# define BreakIntoDebugger() if (IsDebuggerPresent() ) { __debugbreak(); }
2012-05-16 16:09:17 +02:00
inline bool isDebuggerActive ( ) {
2012-05-09 20:04:00 +02:00
return IsDebuggerPresent ( ) ! = 0 ;
}
2012-05-11 09:17:16 +02:00
# elif defined(__MINGW32__)
extern " C " __declspec ( dllimport ) int __stdcall IsDebuggerPresent ( ) ;
extern " C " __declspec ( dllimport ) void __stdcall DebugBreak ( ) ;
# define BreakIntoDebugger() if (IsDebuggerPresent() ) { DebugBreak(); }
2012-05-16 16:09:17 +02:00
inline bool isDebuggerActive ( ) {
2012-05-11 09:17:16 +02:00
return IsDebuggerPresent ( ) ! = 0 ;
}
2012-05-09 20:04:00 +02:00
# else
2013-03-08 10:30:25 +01:00
inline void BreakIntoDebugger ( ) { }
inline bool isDebuggerActive ( ) { return false ; }
2012-05-09 20:04:00 +02:00
# endif
# ifdef CATCH_PLATFORM_WINDOWS
extern " C " __declspec ( dllimport ) void __stdcall OutputDebugStringA ( const char * ) ;
2012-05-16 16:09:17 +02:00
inline void writeToDebugConsole ( const std : : string & text ) {
2012-05-09 20:04:00 +02:00
: : OutputDebugStringA ( text . c_str ( ) ) ;
}
# else
2012-05-16 16:09:17 +02:00
inline void writeToDebugConsole ( const std : : string & text ) {
2012-05-09 20:04:00 +02:00
// !TBD: Need a version for Mac/ XCode and other IDEs
std : : cout < < text ;
}
# endif // CATCH_PLATFORM_WINDOWS
2012-10-28 13:07:17 +01:00
// #included from: catch_interfaces_registry_hub.h
# define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED
2012-05-09 20:04:00 +02:00
2012-10-28 13:07:17 +01:00
// #included from: catch_interfaces_reporter.h
# define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
// #included from: catch_config.hpp
# define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
// #included from: catch_test_spec.h
# define TWOBLUECUBES_CATCH_TEST_SPEC_H_INCLUDED
2011-06-29 20:25:14 +02:00
2012-10-28 13:07:17 +01:00
// #included from: catch_test_case_info.h
# define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
# include <string>
# include <set>
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
namespace Catch {
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
struct ITestCase ;
2011-05-24 09:23:02 +02:00
2012-12-02 00:57:18 +01:00
struct TestCaseInfo {
TestCaseInfo ( const std : : string & _name ,
const std : : string & _className ,
const std : : string & _description ,
const std : : set < std : : string > & _tags ,
bool _isHidden ,
const SourceLineInfo & _lineInfo ) ;
TestCaseInfo ( const TestCaseInfo & other ) ;
std : : string name ;
std : : string className ;
std : : string description ;
std : : set < std : : string > tags ;
SourceLineInfo lineInfo ;
2012-12-06 09:44:51 +01:00
bool isHidden ;
2012-12-02 00:57:18 +01:00
} ;
class TestCase : protected TestCaseInfo {
2012-10-28 13:07:17 +01:00
public :
2011-05-24 09:23:02 +02:00
2012-12-02 00:57:18 +01:00
TestCase ( ITestCase * testCase , const TestCaseInfo & info ) ;
TestCase ( const TestCase & other ) ;
2011-05-24 09:23:02 +02:00
2012-12-02 00:57:18 +01:00
TestCase withName ( const std : : string & _newName ) const ;
2012-02-10 09:30:13 +01:00
2012-10-28 13:07:17 +01:00
void invoke ( ) const ;
2012-11-04 22:39:38 +01:00
2012-12-02 00:57:18 +01:00
const TestCaseInfo & getTestCaseInfo ( ) const ;
2012-10-28 13:07:17 +01:00
bool isHidden ( ) const ;
bool hasTag ( const std : : string & tag ) const ;
bool matchesTags ( const std : : string & tagPattern ) const ;
const std : : set < std : : string > & getTags ( ) const ;
2012-02-10 09:30:13 +01:00
2012-12-02 00:57:18 +01:00
void swap ( TestCase & other ) ;
bool operator = = ( const TestCase & other ) const ;
bool operator < ( const TestCase & other ) const ;
TestCase & operator = ( const TestCase & other ) ;
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
private :
2012-12-02 00:57:18 +01:00
Ptr < ITestCase > test ;
2012-10-28 13:07:17 +01:00
} ;
2012-12-02 00:57:18 +01:00
TestCase makeTestCase ( ITestCase * testCase ,
const std : : string & className ,
const std : : string & name ,
const std : : string & description ,
const SourceLineInfo & lineInfo ) ;
2012-10-28 13:07:17 +01:00
}
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
// #included from: catch_tags.hpp
# define TWOBLUECUBES_CATCH_TAGS_HPP_INCLUDED
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
# include <string>
# include <set>
# include <map>
# include <vector>
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
# ifdef __clang__
# pragma clang diagnostic ignored "-Wpadded"
# endif
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
namespace Catch {
class TagParser {
public :
virtual ~ TagParser ( ) ;
2012-03-04 22:22:36 +01:00
2012-10-28 13:07:17 +01:00
void parse ( const std : : string & str ) {
std : : size_t pos = 0 ;
while ( pos < str . size ( ) ) {
char c = str [ pos ] ;
if ( c = = ' [ ' ) {
std : : size_t end = str . find_first_of ( ' ] ' , pos ) ;
if ( end ! = std : : string : : npos ) {
acceptTag ( str . substr ( pos + 1 , end - pos - 1 ) ) ;
pos = end + 1 ;
}
else {
acceptChar ( c ) ;
pos + + ;
}
}
else {
acceptChar ( c ) ;
pos + + ;
}
}
endParse ( ) ;
}
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
protected :
virtual void acceptTag ( const std : : string & tag ) = 0 ;
virtual void acceptChar ( char c ) = 0 ;
virtual void endParse ( ) { }
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
private :
} ;
2012-05-16 16:09:17 +02:00
2012-10-28 13:07:17 +01:00
class TagExtracter : public TagParser {
2011-05-24 09:23:02 +02:00
public :
2012-10-28 13:07:17 +01:00
TagExtracter ( std : : set < std : : string > & tags )
: m_tags ( tags )
{ }
virtual ~ TagExtracter ( ) ;
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
void parse ( std : : string & description ) {
TagParser : : parse ( description ) ;
description = m_remainder ;
2011-05-24 09:23:02 +02:00
}
private :
2012-10-28 13:07:17 +01:00
virtual void acceptTag ( const std : : string & tag ) {
2013-03-12 19:49:37 +01:00
std : : string lcTag = tag ;
toLower ( lcTag ) ;
m_tags . insert ( lcTag ) ;
2012-10-28 13:07:17 +01:00
}
virtual void acceptChar ( char c ) {
m_remainder + = c ;
}
2011-05-24 09:23:02 +02:00
2012-11-04 22:39:38 +01:00
TagExtracter & operator = ( const TagExtracter & ) ;
2012-10-28 13:07:17 +01:00
std : : set < std : : string > & m_tags ;
std : : string m_remainder ;
2011-05-24 09:23:02 +02:00
} ;
2012-10-28 13:07:17 +01:00
class Tag {
public :
Tag ( )
2012-11-06 20:34:35 +01:00
: m_isNegated ( false )
2012-10-28 13:07:17 +01:00
{ }
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
Tag ( const std : : string & name , bool isNegated )
: m_name ( name ) ,
2012-11-06 20:34:35 +01:00
m_isNegated ( isNegated )
2012-10-28 13:07:17 +01:00
{ }
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
std : : string getName ( ) const {
return m_name ;
}
bool isNegated ( ) const {
return m_isNegated ;
}
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
bool operator ! ( ) const {
return m_name . empty ( ) ;
}
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
private :
std : : string m_name ;
bool m_isNegated ;
} ;
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
class TagSet {
typedef std : : map < std : : string , Tag > TagMap ;
public :
void add ( const Tag & tag ) {
2013-03-12 19:49:37 +01:00
std : : string tagName = tag . getName ( ) ;
toLower ( tagName ) ;
m_tags . insert ( std : : make_pair ( tagName , tag ) ) ;
2012-10-28 13:07:17 +01:00
}
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
bool empty ( ) const {
return m_tags . empty ( ) ;
}
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
bool matches ( const std : : set < std : : string > & tags ) const {
TagMap : : const_iterator it = m_tags . begin ( ) ;
TagMap : : const_iterator itEnd = m_tags . end ( ) ;
for ( ; it ! = itEnd ; + + it ) {
bool found = tags . find ( it - > first ) ! = tags . end ( ) ;
if ( found = = it - > second . isNegated ( ) )
return false ;
}
return true ;
}
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
private :
TagMap m_tags ;
} ;
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
class TagExpression {
public :
bool matches ( const std : : set < std : : string > & tags ) const {
std : : vector < TagSet > : : const_iterator it = m_tagSets . begin ( ) ;
std : : vector < TagSet > : : const_iterator itEnd = m_tagSets . end ( ) ;
for ( ; it ! = itEnd ; + + it )
if ( it - > matches ( tags ) )
return true ;
return false ;
}
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
private :
friend class TagExpressionParser ;
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
std : : vector < TagSet > m_tagSets ;
} ;
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
class TagExpressionParser : public TagParser {
public :
TagExpressionParser ( TagExpression & exp )
: m_isNegated ( false ) ,
m_exp ( exp )
{ }
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
~ TagExpressionParser ( ) ;
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
private :
virtual void acceptTag ( const std : : string & tag ) {
m_currentTagSet . add ( Tag ( tag , m_isNegated ) ) ;
m_isNegated = false ;
}
virtual void acceptChar ( char c ) {
switch ( c ) {
case ' ~ ' :
m_isNegated = true ;
break ;
case ' , ' :
m_exp . m_tagSets . push_back ( m_currentTagSet ) ;
break ;
}
}
virtual void endParse ( ) {
if ( ! m_currentTagSet . empty ( ) )
m_exp . m_tagSets . push_back ( m_currentTagSet ) ;
}
2011-05-24 09:23:02 +02:00
2012-11-04 22:39:38 +01:00
TagExpressionParser & operator = ( const TagExpressionParser & ) ;
2012-10-28 13:07:17 +01:00
bool m_isNegated ;
TagSet m_currentTagSet ;
TagExpression & m_exp ;
} ;
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
} // end namespace Catch
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
# include <string>
# include <vector>
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
namespace Catch {
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
struct IfFilterMatches { enum DoWhat {
AutoDetectBehaviour ,
IncludeTests ,
ExcludeTests
} ; } ;
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
class TestCaseFilter {
enum WildcardPosition {
NoWildcard = 0 ,
WildcardAtStart = 1 ,
WildcardAtEnd = 2 ,
WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
} ;
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
public :
TestCaseFilter ( const std : : string & testSpec , IfFilterMatches : : DoWhat matchBehaviour = IfFilterMatches : : AutoDetectBehaviour )
: m_stringToMatch ( testSpec ) ,
m_filterType ( matchBehaviour ) ,
m_wildcardPosition ( NoWildcard )
{
2013-03-12 19:49:37 +01:00
toLower ( m_stringToMatch ) ;
2012-10-28 13:07:17 +01:00
if ( m_filterType = = IfFilterMatches : : AutoDetectBehaviour ) {
if ( startsWith ( m_stringToMatch , " exclude: " ) ) {
m_stringToMatch = m_stringToMatch . substr ( 8 ) ;
m_filterType = IfFilterMatches : : ExcludeTests ;
}
else if ( startsWith ( m_stringToMatch , " ~ " ) ) {
m_stringToMatch = m_stringToMatch . substr ( 1 ) ;
m_filterType = IfFilterMatches : : ExcludeTests ;
}
else {
m_filterType = IfFilterMatches : : IncludeTests ;
}
}
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
if ( m_stringToMatch [ 0 ] = = ' * ' ) {
m_stringToMatch = m_stringToMatch . substr ( 1 ) ;
m_wildcardPosition = ( WildcardPosition ) ( m_wildcardPosition | WildcardAtStart ) ;
}
if ( m_stringToMatch [ m_stringToMatch . size ( ) - 1 ] = = ' * ' ) {
m_stringToMatch = m_stringToMatch . substr ( 0 , m_stringToMatch . size ( ) - 1 ) ;
m_wildcardPosition = ( WildcardPosition ) ( m_wildcardPosition | WildcardAtEnd ) ;
}
}
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
IfFilterMatches : : DoWhat getFilterType ( ) const {
return m_filterType ;
}
2011-05-24 09:23:02 +02:00
2012-12-02 00:57:18 +01:00
bool shouldInclude ( const TestCase & testCase ) const {
2012-10-28 13:07:17 +01:00
return isMatch ( testCase ) = = ( m_filterType = = IfFilterMatches : : IncludeTests ) ;
}
private :
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
# ifdef __clang__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wunreachable-code"
# endif
2011-05-24 09:23:02 +02:00
2012-12-02 00:57:18 +01:00
bool isMatch ( const TestCase & testCase ) const {
2013-03-12 19:49:37 +01:00
std : : string name = testCase . getTestCaseInfo ( ) . name ;
toLower ( name ) ;
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
switch ( m_wildcardPosition ) {
case NoWildcard :
return m_stringToMatch = = name ;
case WildcardAtStart :
return endsWith ( name , m_stringToMatch ) ;
case WildcardAtEnd :
return startsWith ( name , m_stringToMatch ) ;
case WildcardAtBothEnds :
return contains ( name , m_stringToMatch ) ;
}
throw std : : logic_error ( " Unhandled wildcard type " ) ;
}
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
# ifdef __clang__
# pragma clang diagnostic pop
# endif
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
std : : string m_stringToMatch ;
IfFilterMatches : : DoWhat m_filterType ;
WildcardPosition m_wildcardPosition ;
} ;
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
class TestCaseFilters {
public :
TestCaseFilters ( const std : : string & name ) : m_name ( name ) { }
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
std : : string getName ( ) const {
return m_name ;
}
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
void addFilter ( const TestCaseFilter & filter ) {
if ( filter . getFilterType ( ) = = IfFilterMatches : : ExcludeTests )
m_exclusionFilters . push_back ( filter ) ;
else
m_inclusionFilters . push_back ( filter ) ;
}
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
void addTags ( const std : : string & tagPattern ) {
TagExpression exp ;
TagExpressionParser ( exp ) . parse ( tagPattern ) ;
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
m_tagExpressions . push_back ( exp ) ;
}
2012-08-09 08:47:30 +02:00
2012-12-02 00:57:18 +01:00
bool shouldInclude ( const TestCase & testCase ) const {
2012-10-28 13:07:17 +01:00
if ( ! m_tagExpressions . empty ( ) ) {
std : : vector < TagExpression > : : const_iterator it = m_tagExpressions . begin ( ) ;
std : : vector < TagExpression > : : const_iterator itEnd = m_tagExpressions . end ( ) ;
for ( ; it ! = itEnd ; + + it )
if ( it - > matches ( testCase . getTags ( ) ) )
break ;
if ( it = = itEnd )
return false ;
}
2012-08-09 08:47:30 +02:00
2012-10-28 13:07:17 +01:00
if ( ! m_inclusionFilters . empty ( ) ) {
std : : vector < TestCaseFilter > : : const_iterator it = m_inclusionFilters . begin ( ) ;
std : : vector < TestCaseFilter > : : const_iterator itEnd = m_inclusionFilters . end ( ) ;
for ( ; it ! = itEnd ; + + it )
if ( it - > shouldInclude ( testCase ) )
break ;
if ( it = = itEnd )
return false ;
}
else if ( m_exclusionFilters . empty ( ) & & m_tagExpressions . empty ( ) ) {
return ! testCase . isHidden ( ) ;
}
2012-08-09 08:47:30 +02:00
2012-10-28 13:07:17 +01:00
std : : vector < TestCaseFilter > : : const_iterator it = m_exclusionFilters . begin ( ) ;
std : : vector < TestCaseFilter > : : const_iterator itEnd = m_exclusionFilters . end ( ) ;
for ( ; it ! = itEnd ; + + it )
if ( ! it - > shouldInclude ( testCase ) )
return false ;
return true ;
}
private :
std : : vector < TagExpression > m_tagExpressions ;
std : : vector < TestCaseFilter > m_inclusionFilters ;
std : : vector < TestCaseFilter > m_exclusionFilters ;
std : : string m_name ;
} ;
2012-08-09 08:47:30 +02:00
2012-10-28 13:07:17 +01:00
}
2012-08-09 08:47:30 +02:00
2012-10-28 13:07:17 +01:00
// #included from: catch_interfaces_config.h
# define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED
2012-08-09 08:47:30 +02:00
2012-08-31 09:10:36 +02:00
namespace Catch {
2012-08-09 08:47:30 +02:00
2012-10-28 13:07:17 +01:00
struct IConfig {
2012-08-09 08:47:30 +02:00
2012-10-28 13:07:17 +01:00
virtual ~ IConfig ( ) ;
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
virtual bool allowThrows ( ) const = 0 ;
} ;
}
2012-05-16 16:09:17 +02:00
2012-10-28 13:07:17 +01:00
// #included from: catch_stream.hpp
# define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
// #included from: catch_streambuf.h
# define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
# include <streambuf>
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
namespace Catch {
class StreamBufBase : public std : : streambuf {
public :
virtual ~ StreamBufBase ( ) ;
2011-05-24 09:23:02 +02:00
} ;
2012-08-31 09:10:36 +02:00
}
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
# include <stdexcept>
# include <cstdio>
2012-09-26 19:38:26 +02:00
2012-10-28 13:07:17 +01:00
namespace Catch {
2012-09-26 19:38:26 +02:00
2012-10-28 13:07:17 +01:00
template < typename WriterF , size_t bufferSize = 256 >
class StreamBufImpl : public StreamBufBase {
char data [ bufferSize ] ;
WriterF m_writer ;
2012-09-26 19:38:26 +02:00
public :
2012-10-28 13:07:17 +01:00
StreamBufImpl ( ) {
setp ( data , data + sizeof ( data ) ) ;
}
2012-09-26 19:38:26 +02:00
2012-10-28 13:07:17 +01:00
~ StreamBufImpl ( ) {
sync ( ) ;
}
private :
2013-03-08 10:30:25 +01:00
int overflow ( int c ) {
2012-10-28 13:07:17 +01:00
sync ( ) ;
if ( c ! = EOF ) {
if ( pbase ( ) = = epptr ( ) )
m_writer ( std : : string ( 1 , static_cast < char > ( c ) ) ) ;
else
sputc ( static_cast < char > ( c ) ) ;
}
return 0 ;
}
2013-03-08 10:30:25 +01:00
int sync ( ) {
2012-10-28 13:07:17 +01:00
if ( pbase ( ) ! = pptr ( ) ) {
m_writer ( std : : string ( pbase ( ) , static_cast < std : : string : : size_type > ( pptr ( ) - pbase ( ) ) ) ) ;
setp ( pbase ( ) , epptr ( ) ) ;
2012-09-26 19:38:26 +02:00
}
2012-10-28 13:07:17 +01:00
return 0 ;
2012-09-26 19:38:26 +02:00
}
} ;
2012-10-28 13:07:17 +01:00
///////////////////////////////////////////////////////////////////////////
2012-09-26 19:38:26 +02:00
2012-10-28 13:07:17 +01:00
struct OutputDebugWriter {
2012-09-26 19:38:26 +02:00
2012-10-28 13:07:17 +01:00
void operator ( ) ( const std : : string & str ) {
writeToDebugConsole ( str ) ;
2012-09-26 19:38:26 +02:00
}
} ;
2012-10-28 13:07:17 +01:00
class Stream {
2012-09-26 19:38:26 +02:00
public :
2012-10-28 13:07:17 +01:00
Stream ( )
: streamBuf ( NULL ) , isOwned ( false )
2012-09-26 19:38:26 +02:00
{ }
2012-10-28 13:07:17 +01:00
Stream ( std : : streambuf * _streamBuf , bool _isOwned )
: streamBuf ( _streamBuf ) , isOwned ( _isOwned )
2012-09-26 19:38:26 +02:00
{ }
2012-10-28 13:07:17 +01:00
void release ( ) {
if ( isOwned ) {
delete streamBuf ;
streamBuf = NULL ;
isOwned = false ;
}
2012-09-26 19:38:26 +02:00
}
2012-10-28 13:07:17 +01:00
std : : streambuf * streamBuf ;
2012-09-26 19:38:26 +02:00
private :
2012-10-28 13:07:17 +01:00
bool isOwned ;
2012-09-26 19:38:26 +02:00
} ;
2012-10-28 13:07:17 +01:00
}
2012-09-26 19:38:26 +02:00
2012-10-28 13:07:17 +01:00
# include <memory>
# include <vector>
# include <string>
# include <iostream>
2012-09-26 19:38:26 +02:00
2013-01-26 21:18:30 +01:00
# ifndef CATCH_CONFIG_CONSOLE_WIDTH
# define CATCH_CONFIG_CONSOLE_WIDTH 80
# endif
2012-10-28 13:07:17 +01:00
namespace Catch {
2012-09-26 19:38:26 +02:00
2012-10-28 13:07:17 +01:00
struct Include { enum WhichResults {
FailedOnly ,
SuccessfulResults
} ; } ;
2012-09-26 19:38:26 +02:00
2012-10-28 13:07:17 +01:00
struct List { enum What {
None = 0 ,
2012-09-26 19:38:26 +02:00
2012-10-28 13:07:17 +01:00
Reports = 1 ,
Tests = 2 ,
All = 3 ,
2012-09-26 19:38:26 +02:00
2012-10-28 13:07:17 +01:00
TestNames = 6 ,
2012-09-26 19:38:26 +02:00
2012-10-28 13:07:17 +01:00
WhatMask = 0xf ,
AsText = 0x10 ,
AsXml = 0x20 ,
AsMask = 0xf0
} ; } ;
struct ConfigData {
struct WarnAbout { enum What {
Nothing = 0x00 ,
NoAssertions = 0x01
} ; } ;
ConfigData ( )
: listSpec ( List : : None ) ,
shouldDebugBreak ( false ) ,
includeWhichResults ( Include : : FailedOnly ) ,
cutoff ( - 1 ) ,
allowThrows ( true ) ,
warnings ( WarnAbout : : Nothing )
{ }
std : : string reporter ;
std : : string outputFilename ;
List : : What listSpec ;
std : : vector < TestCaseFilters > filters ;
bool shouldDebugBreak ;
std : : string stream ;
Include : : WhichResults includeWhichResults ;
std : : string name ;
int cutoff ;
bool allowThrows ;
WarnAbout : : What warnings ;
2012-09-26 19:38:26 +02:00
} ;
2012-10-28 13:07:17 +01:00
class Config : public IConfig {
private :
Config ( const Config & other ) ;
Config & operator = ( const Config & other ) ;
virtual void dummy ( ) ;
2012-09-26 19:38:26 +02:00
public :
2012-10-28 13:07:17 +01:00
Config ( )
: m_os ( std : : cout . rdbuf ( ) )
2012-09-26 19:38:26 +02:00
{ }
2012-10-28 13:07:17 +01:00
Config ( const ConfigData & data )
: m_data ( data ) ,
m_os ( std : : cout . rdbuf ( ) )
{ }
2012-09-26 19:38:26 +02:00
2012-10-28 13:07:17 +01:00
virtual ~ Config ( ) {
m_os . rdbuf ( std : : cout . rdbuf ( ) ) ;
m_stream . release ( ) ;
2012-09-26 19:38:26 +02:00
}
2012-10-28 13:07:17 +01:00
void setFilename ( const std : : string & filename ) {
m_data . outputFilename = filename ;
}
2012-09-26 19:38:26 +02:00
2012-10-28 13:07:17 +01:00
List : : What getListSpec ( void ) const {
return m_data . listSpec ;
}
2012-09-26 19:38:26 +02:00
2012-10-28 13:07:17 +01:00
const std : : string & getFilename ( ) const {
return m_data . outputFilename ;
}
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
List : : What listWhat ( ) const {
return static_cast < List : : What > ( m_data . listSpec & List : : WhatMask ) ;
}
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
List : : What listAs ( ) const {
return static_cast < List : : What > ( m_data . listSpec & List : : AsMask ) ;
}
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
std : : string getName ( ) const {
return m_data . name ;
}
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
bool shouldDebugBreak ( ) const {
return m_data . shouldDebugBreak ;
}
2012-09-07 18:52:35 +02:00
2012-10-28 13:07:17 +01:00
virtual std : : ostream & stream ( ) const {
return m_os ;
2011-05-24 09:23:02 +02:00
}
2012-10-28 13:07:17 +01:00
void setStreamBuf ( std : : streambuf * buf ) {
m_os . rdbuf ( buf ? buf : std : : cout . rdbuf ( ) ) ;
2012-08-31 09:10:36 +02:00
}
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
void useStream ( const std : : string & streamName ) {
Stream stream = createStream ( streamName ) ;
setStreamBuf ( stream . streamBuf ) ;
m_stream . release ( ) ;
m_stream = stream ;
2012-08-31 09:10:36 +02:00
}
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
void addTestSpec ( const std : : string & testSpec ) {
TestCaseFilters filters ( testSpec ) ;
filters . addFilter ( TestCaseFilter ( testSpec ) ) ;
m_data . filters . push_back ( filters ) ;
}
2011-06-07 15:13:57 +02:00
2012-10-28 13:07:17 +01:00
virtual bool includeSuccessfulResults ( ) const {
return m_data . includeWhichResults = = Include : : SuccessfulResults ;
}
2011-06-07 15:13:57 +02:00
2012-10-28 13:07:17 +01:00
int getCutoff ( ) const {
return m_data . cutoff ;
2012-05-16 16:09:17 +02:00
}
2011-06-07 15:13:57 +02:00
2012-10-28 13:07:17 +01:00
virtual bool allowThrows ( ) const {
return m_data . allowThrows ;
}
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
const ConfigData & data ( ) const {
return m_data ;
}
ConfigData & data ( ) {
return m_data ;
}
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
private :
ConfigData m_data ;
2012-08-31 09:10:36 +02:00
2012-10-28 13:07:17 +01:00
// !TBD Move these out of here
Stream m_stream ;
mutable std : : ostream m_os ;
} ;
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
} // end namespace Catch
2012-08-31 09:10:36 +02:00
2012-12-06 09:44:51 +01:00
// #included from: catch_option.hpp
# define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED
namespace Catch {
// An optional type
template < typename T >
class Option {
public :
Option ( ) : nullableValue ( NULL ) { }
Option ( T const & _value )
: nullableValue ( new ( storage ) T ( _value ) )
{ }
Option ( Option const & _other )
: nullableValue ( _other ? new ( storage ) T ( * _other ) : NULL )
{ }
~ Option ( ) {
reset ( ) ;
}
Option & operator = ( Option const & _other ) {
reset ( ) ;
if ( _other )
nullableValue = new ( storage ) T ( * _other ) ;
return * this ;
}
void reset ( ) {
if ( nullableValue )
nullableValue - > ~ T ( ) ;
nullableValue = NULL ;
}
T & operator * ( ) { return * nullableValue ; }
const T & operator * ( ) const { return * nullableValue ; }
T * operator - > ( ) { return nullableValue ; }
const T * operator - > ( ) const { return nullableValue ; }
bool some ( ) const { return nullableValue ! = NULL ; }
bool none ( ) const { return nullableValue = = NULL ; }
bool operator ! ( ) const { return nullableValue = = NULL ; }
operator SafeBool : : type ( ) const {
return SafeBool : : makeSafe ( some ( ) ) ;
}
private :
T * nullableValue ;
char storage [ sizeof ( T ) ] ;
} ;
} // end namespace Catch
2012-10-28 13:07:17 +01:00
# include <string>
# include <ostream>
# include <map>
2012-09-26 19:38:26 +02:00
2012-10-28 13:07:17 +01:00
namespace Catch
{
2012-12-02 00:57:18 +01:00
struct ReporterConfig {
ReporterConfig ( std : : ostream & _stream , ConfigData const & _fullConfig )
: m_stream ( & _stream ) , m_fullConfig ( _fullConfig ) { }
2012-12-06 09:44:51 +01:00
std : : ostream & stream ( ) const { return * m_stream ; }
2012-12-02 00:57:18 +01:00
std : : string name ( ) const { return m_fullConfig . name ; }
bool includeSuccessfulResults ( ) const { return m_fullConfig . includeWhichResults = = Include : : SuccessfulResults ; }
bool warnAboutMissingAssertions ( ) const { return m_fullConfig . warnings & ConfigData : : WarnAbout : : NoAssertions ; }
private :
std : : ostream * m_stream ;
ConfigData m_fullConfig ;
} ;
struct ReporterPreferences {
ReporterPreferences ( )
: shouldRedirectStdOut ( false )
2012-10-28 13:07:17 +01:00
{ }
2012-09-26 19:38:26 +02:00
2012-12-02 00:57:18 +01:00
bool shouldRedirectStdOut ;
} ;
struct TestRunInfo {
TestRunInfo ( std : : string const & _name ) : name ( _name ) { }
std : : string name ;
} ;
struct GroupInfo {
2013-01-16 10:44:43 +01:00
GroupInfo ( std : : string const & _name ,
std : : size_t _groupIndex ,
std : : size_t _groupsCount )
: name ( _name ) ,
groupIndex ( _groupIndex ) ,
groupsCounts ( _groupsCount )
{ }
2012-12-02 00:57:18 +01:00
std : : string name ;
2013-01-16 10:44:43 +01:00
std : : size_t groupIndex ;
std : : size_t groupsCounts ;
2012-12-02 00:57:18 +01:00
} ;
struct SectionInfo {
SectionInfo ( std : : string const & _name ,
std : : string const & _description ,
SourceLineInfo const & _lineInfo )
: name ( _name ) ,
description ( _description ) ,
lineInfo ( _lineInfo )
2012-10-28 13:07:17 +01:00
{ }
2012-09-26 19:38:26 +02:00
2012-10-28 13:07:17 +01:00
std : : string name ;
2012-12-02 00:57:18 +01:00
std : : string description ;
SourceLineInfo lineInfo ;
} ;
2012-09-15 18:53:27 +02:00
2012-12-06 09:44:51 +01:00
struct ThreadedSectionInfo : SectionInfo , SharedImpl < > {
2013-01-26 21:18:30 +01:00
ThreadedSectionInfo ( SectionInfo const & _sectionInfo , ThreadedSectionInfo * _parent = NULL )
2012-12-06 09:44:51 +01:00
: SectionInfo ( _sectionInfo ) ,
2013-01-16 10:44:43 +01:00
parent ( _parent )
2012-12-06 09:44:51 +01:00
{ }
virtual ~ ThreadedSectionInfo ( ) ;
std : : vector < Ptr < ThreadedSectionInfo > > children ;
2013-01-26 21:18:30 +01:00
ThreadedSectionInfo * parent ;
2012-12-06 09:44:51 +01:00
} ;
2013-01-16 10:44:43 +01:00
struct AssertionStats {
2012-12-02 00:57:18 +01:00
AssertionStats ( AssertionResult const & _assertionResult ,
2013-02-02 21:37:58 +01:00
std : : vector < MessageInfo > const & _infoMessages ,
2012-12-02 00:57:18 +01:00
Totals const & _totals )
: assertionResult ( _assertionResult ) ,
2013-02-02 21:37:58 +01:00
infoMessages ( _infoMessages ) ,
2012-12-02 00:57:18 +01:00
totals ( _totals )
2013-02-02 21:37:58 +01: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 ( ) ;
infoMessages . push_back ( builder . build ( ) ) ;
}
}
2012-12-02 00:57:18 +01:00
virtual ~ AssertionStats ( ) ;
AssertionResult assertionResult ;
2013-02-02 21:37:58 +01:00
std : : vector < MessageInfo > infoMessages ;
2012-12-02 00:57:18 +01:00
Totals totals ;
2012-08-31 09:10:36 +02:00
} ;
2013-01-16 10:44:43 +01:00
struct SectionStats {
2012-12-02 00:57:18 +01:00
SectionStats ( SectionInfo const & _sectionInfo ,
Counts const & _assertions ,
bool _missingAssertions )
: sectionInfo ( _sectionInfo ) ,
assertions ( _assertions ) ,
missingAssertions ( _missingAssertions )
{ }
virtual ~ SectionStats ( ) ;
SectionInfo sectionInfo ;
Counts assertions ;
bool missingAssertions ;
} ;
2013-01-16 10:44:43 +01:00
struct TestCaseStats {
2012-12-02 00:57:18 +01:00
TestCaseStats ( TestCaseInfo const & _testInfo ,
Totals const & _totals ,
std : : string const & _stdOut ,
std : : string const & _stdErr ,
bool _missingAssertions ,
bool _aborting )
: testInfo ( _testInfo ) ,
totals ( _totals ) ,
stdOut ( _stdOut ) ,
stdErr ( _stdErr ) ,
missingAssertions ( _missingAssertions ) ,
aborting ( _aborting )
{ }
virtual ~ TestCaseStats ( ) ;
TestCaseInfo testInfo ;
Totals totals ;
std : : string stdOut ;
std : : string stdErr ;
bool missingAssertions ;
bool aborting ;
} ;
2013-01-16 10:44:43 +01:00
struct TestGroupStats {
2012-12-02 00:57:18 +01:00
TestGroupStats ( GroupInfo const & _groupInfo ,
Totals const & _totals ,
bool _aborting )
: groupInfo ( _groupInfo ) ,
totals ( _totals ) ,
aborting ( _aborting )
{ }
2013-01-16 10:44:43 +01:00
TestGroupStats ( GroupInfo const & _groupInfo )
: groupInfo ( _groupInfo ) ,
aborting ( false )
{ }
2012-12-02 00:57:18 +01:00
virtual ~ TestGroupStats ( ) ;
GroupInfo groupInfo ;
Totals totals ;
bool aborting ;
} ;
2013-01-16 10:44:43 +01:00
struct TestRunStats {
2012-12-02 00:57:18 +01:00
TestRunStats ( TestRunInfo const & _runInfo ,
Totals const & _totals ,
bool _aborting )
: runInfo ( _runInfo ) ,
totals ( _totals ) ,
aborting ( _aborting )
{ }
2013-01-16 10:44:43 +01:00
TestRunStats ( TestRunStats const & _other )
: runInfo ( _other . runInfo ) ,
totals ( _other . totals ) ,
aborting ( _other . aborting )
{ }
2012-12-02 00:57:18 +01:00
virtual ~ TestRunStats ( ) ;
TestRunInfo runInfo ;
Totals totals ;
bool aborting ;
} ;
// !Work In progress
struct IStreamingReporter : IShared {
virtual ~ IStreamingReporter ( ) ;
2012-12-06 09:44:51 +01:00
2013-01-16 10:44:43 +01:00
// Implementing class must also provide the following static method:
2012-12-06 09:44:51 +01:00
// static std::string getDescription();
2012-12-02 00:57:18 +01:00
virtual ReporterPreferences getPreferences ( ) const = 0 ;
virtual void testRunStarting ( TestRunInfo const & testRunInfo ) = 0 ;
virtual void testGroupStarting ( GroupInfo const & groupInfo ) = 0 ;
virtual void testCaseStarting ( TestCaseInfo const & testInfo ) = 0 ;
virtual void sectionStarting ( SectionInfo const & sectionInfo ) = 0 ;
virtual void assertionStarting ( AssertionInfo const & assertionInfo ) = 0 ;
2012-08-31 09:10:36 +02:00
2013-01-16 10:44:43 +01:00
virtual void assertionEnded ( AssertionStats const & assertionStats ) = 0 ;
virtual void sectionEnded ( SectionStats const & sectionStats ) = 0 ;
virtual void testCaseEnded ( TestCaseStats const & testCaseStats ) = 0 ;
virtual void testGroupEnded ( TestGroupStats const & testGroupStats ) = 0 ;
virtual void testRunEnded ( TestRunStats const & testRunStats ) = 0 ;
2012-12-02 00:57:18 +01:00
} ;
2012-12-06 09:44:51 +01:00
2013-01-16 10:44:43 +01:00
struct StreamingReporterBase : SharedImpl < IStreamingReporter > {
StreamingReporterBase ( ReporterConfig const & _config )
2012-12-10 09:54:57 +01:00
: m_config ( _config ) ,
stream ( _config . stream ( ) )
2012-12-06 09:44:51 +01:00
{ }
2013-01-16 10:44:43 +01:00
virtual ~ StreamingReporterBase ( ) ;
2012-12-06 09:44:51 +01:00
virtual void testRunStarting ( TestRunInfo const & _testRunInfo ) {
testRunInfo = _testRunInfo ;
}
virtual void testGroupStarting ( GroupInfo const & _groupInfo ) {
unusedGroupInfo = _groupInfo ;
}
virtual void testCaseStarting ( TestCaseInfo const & _testInfo ) {
unusedTestCaseInfo = _testInfo ;
}
virtual void sectionStarting ( SectionInfo const & _sectionInfo ) {
Ptr < ThreadedSectionInfo > sectionInfo = new ThreadedSectionInfo ( _sectionInfo ) ;
if ( ! currentSectionInfo ) {
currentSectionInfo = sectionInfo ;
2013-01-26 21:18:30 +01:00
m_rootSections . push_back ( currentSectionInfo ) ;
2012-12-06 09:44:51 +01:00
}
else {
currentSectionInfo - > children . push_back ( sectionInfo ) ;
2013-01-26 21:18:30 +01:00
sectionInfo - > parent = currentSectionInfo . get ( ) ;
2012-12-06 09:44:51 +01:00
currentSectionInfo = sectionInfo ;
}
}
2013-01-16 10:44:43 +01:00
virtual void sectionEnded ( SectionStats const & /* _sectionStats */ ) {
2012-12-06 09:44:51 +01:00
currentSectionInfo = currentSectionInfo - > parent ;
}
2013-01-16 10:44:43 +01:00
virtual void testCaseEnded ( TestCaseStats const & /* _testCaseStats */ ) {
2012-12-06 09:44:51 +01:00
unusedTestCaseInfo . reset ( ) ;
}
2013-01-16 10:44:43 +01:00
virtual void testGroupEnded ( TestGroupStats const & /* _testGroupStats */ ) {
2012-12-06 09:44:51 +01:00
unusedGroupInfo . reset ( ) ;
}
2013-01-16 10:44:43 +01:00
virtual void testRunEnded ( TestRunStats const & /* _testRunStats */ ) {
currentSectionInfo . reset ( ) ;
unusedTestCaseInfo . reset ( ) ;
unusedGroupInfo . reset ( ) ;
testRunInfo . reset ( ) ;
2012-12-06 09:44:51 +01:00
}
2012-12-10 09:54:57 +01:00
ReporterConfig m_config ;
2012-12-06 09:44:51 +01:00
Option < TestRunInfo > testRunInfo ;
Option < GroupInfo > unusedGroupInfo ;
Option < TestCaseInfo > unusedTestCaseInfo ;
Ptr < ThreadedSectionInfo > currentSectionInfo ;
2013-01-16 10:44:43 +01:00
std : : ostream & stream ;
2013-01-26 21:18:30 +01:00
// !TBD: This should really go in the TestCaseStats class
std : : vector < Ptr < ThreadedSectionInfo > > m_rootSections ;
2013-01-16 10:44:43 +01:00
} ;
struct TestGroupNode : TestGroupStats {
TestGroupNode ( TestGroupStats const & _stats ) : TestGroupStats ( _stats ) { }
// TestGroupNode( GroupInfo const& _info ) : TestGroupStats( _stats ) {}
~ TestGroupNode ( ) ;
} ;
struct TestRunNode : TestRunStats {
TestRunNode ( TestRunStats const & _stats ) : TestRunStats ( _stats ) { }
~ TestRunNode ( ) ;
std : : vector < TestGroupNode > groups ;
} ;
// !TBD: Derived helper that implements the streaming interface but holds the stats
// - declares a new interface where methods are called at the end of each event
// - this would be used by the JUnit reporter, for example.
// - it may be used by the basic reporter, too, but that would clear down the stack
// as it goes
struct CumulativeReporterBase : SharedImpl < IStreamingReporter > {
CumulativeReporterBase ( ReporterConfig const & _config )
: m_config ( _config ) ,
stream ( _config . stream ( ) )
{ }
virtual ~ CumulativeReporterBase ( ) ;
virtual void testRunStarting ( TestRunInfo const & _testRunInfo ) {
// testRunInfo = _testRunInfo;
}
virtual void testGroupStarting ( GroupInfo const & _groupInfo ) {
testGroupNode = TestGroupNode ( _groupInfo ) ;
}
virtual void testCaseStarting ( TestCaseInfo const & _testInfo ) {
// unusedTestCaseInfo = _testInfo;
}
virtual void sectionStarting ( SectionInfo const & _sectionInfo ) {
// Ptr<ThreadedSectionInfo> sectionInfo = new ThreadedSectionInfo( _sectionInfo );
// if( !currentSectionInfo ) {
// currentSectionInfo = sectionInfo;
// }
// else {
// currentSectionInfo->children.push_back( sectionInfo );
// sectionInfo->parent = currentSectionInfo;
// currentSectionInfo = sectionInfo;
// }
}
virtual void sectionEnded ( SectionStats const & /* _sectionStats */ ) {
// currentSectionInfo = currentSectionInfo->parent;
}
virtual void testCaseEnded ( TestCaseStats const & /* _testCaseStats */ ) {
// unusedTestCaseInfo.reset();
}
virtual void testGroupEnded ( TestGroupStats const & _testGroupStats ) {
// testGroupNode-> // populate
// Ptr<TestGroupNode> node ( new TestGroupNode( _testGroupStats ) );
// unusedGroupInfo.reset();
}
virtual void testRunEnded ( TestRunStats const & /* _testRunStats */ ) {
// currentSectionInfo.reset();
// unusedTestCaseInfo.reset();
// unusedGroupInfo.reset();
// testRunInfo.reset();
}
ReporterConfig m_config ;
// Option<TestRunInfo> testRunInfo;
// Option<GroupInfo> unusedGroupInfo;
// Option<TestCaseInfo> unusedTestCaseInfo;
// Ptr<ThreadedSectionInfo> currentSectionInfo;
// Ptr<TestGroupNode> testGroupNode;
Option < TestGroupNode > testGroupNode ;
2012-12-06 09:44:51 +01:00
std : : ostream & stream ;
} ;
2012-12-02 00:57:18 +01:00
// Deprecated
2012-10-28 13:07:17 +01:00
struct IReporter : IShared {
virtual ~ IReporter ( ) ;
2012-08-31 09:10:36 +02:00
2012-10-28 13:07:17 +01:00
virtual bool shouldRedirectStdout ( ) const = 0 ;
2012-08-31 09:10:36 +02:00
2012-10-28 13:07:17 +01:00
virtual void StartTesting ( ) = 0 ;
2012-12-02 00:57:18 +01:00
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 , const Counts & 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 ( const AssertionResult & result ) = 0 ;
} ;
2012-08-31 09:10:36 +02:00
2012-12-02 00:57:18 +01:00
class LegacyReporterAdapter : public SharedImpl < IStreamingReporter >
{
public :
LegacyReporterAdapter ( Ptr < IReporter > const & legacyReporter , ReporterConfig const & config )
: m_legacyReporter ( legacyReporter ) ,
m_config ( config )
{ }
virtual ~ LegacyReporterAdapter ( ) ;
2012-08-31 09:10:36 +02:00
2012-12-02 00:57:18 +01:00
virtual ReporterPreferences getPreferences ( ) const {
ReporterPreferences prefs ;
prefs . shouldRedirectStdOut = m_legacyReporter - > shouldRedirectStdout ( ) ;
return prefs ;
}
2012-09-26 19:38:26 +02:00
2012-12-02 00:57:18 +01:00
virtual void testRunStarting ( TestRunInfo const & ) {
m_legacyReporter - > StartTesting ( ) ;
}
virtual void testGroupStarting ( GroupInfo const & groupInfo ) {
m_legacyReporter - > StartGroup ( groupInfo . name ) ;
}
virtual void testCaseStarting ( TestCaseInfo const & testInfo ) {
m_legacyReporter - > StartTestCase ( testInfo ) ;
}
virtual void sectionStarting ( SectionInfo const & sectionInfo ) {
m_legacyReporter - > StartSection ( sectionInfo . name , sectionInfo . description ) ;
}
virtual void assertionStarting ( AssertionInfo const & ) {
// Not on legacy interface
}
2012-09-29 21:54:03 +02:00
2013-01-16 10:44:43 +01:00
virtual void assertionEnded ( AssertionStats const & assertionStats ) {
m_legacyReporter - > Result ( assertionStats . assertionResult ) ;
2012-12-02 00:57:18 +01:00
}
2013-01-16 10:44:43 +01:00
virtual void sectionEnded ( SectionStats const & sectionStats ) {
if ( sectionStats . missingAssertions )
m_legacyReporter - > NoAssertionsInSection ( sectionStats . sectionInfo . name ) ;
m_legacyReporter - > EndSection ( sectionStats . sectionInfo . name , sectionStats . assertions ) ;
2012-12-02 00:57:18 +01:00
}
2013-01-16 10:44:43 +01:00
virtual void testCaseEnded ( TestCaseStats const & testCaseStats ) {
if ( testCaseStats . missingAssertions )
m_legacyReporter - > NoAssertionsInTestCase ( testCaseStats . testInfo . name ) ;
2012-12-02 00:57:18 +01:00
m_legacyReporter - > EndTestCase
2013-01-16 10:44:43 +01:00
( testCaseStats . testInfo ,
testCaseStats . totals ,
testCaseStats . stdOut ,
testCaseStats . stdErr ) ;
2012-12-02 00:57:18 +01:00
}
2013-01-16 10:44:43 +01:00
virtual void testGroupEnded ( TestGroupStats const & testGroupStats ) {
if ( testGroupStats . aborting )
2012-12-02 00:57:18 +01:00
m_legacyReporter - > Aborted ( ) ;
2013-01-16 10:44:43 +01:00
m_legacyReporter - > EndGroup ( testGroupStats . groupInfo . name , testGroupStats . totals ) ;
2012-12-02 00:57:18 +01:00
}
2013-01-16 10:44:43 +01:00
virtual void testRunEnded ( TestRunStats const & testRunStats ) {
m_legacyReporter - > EndTesting ( testRunStats . totals ) ;
2012-12-02 00:57:18 +01:00
}
2012-09-29 21:54:03 +02:00
2012-12-02 00:57:18 +01:00
private :
Ptr < IReporter > m_legacyReporter ;
ReporterConfig m_config ;
2012-10-28 13:07:17 +01:00
} ;
2012-09-29 21:54:03 +02:00
2012-10-28 13:07:17 +01:00
struct IReporterFactory {
virtual ~ IReporterFactory ( ) ;
2012-12-02 00:57:18 +01:00
virtual IStreamingReporter * create ( ReporterConfig const & config ) const = 0 ;
2012-10-28 13:07:17 +01:00
virtual std : : string getDescription ( ) const = 0 ;
} ;
struct IReporterRegistry {
typedef std : : map < std : : string , IReporterFactory * > FactoryMap ;
virtual ~ IReporterRegistry ( ) ;
2012-12-02 00:57:18 +01:00
virtual IStreamingReporter * create ( std : : string const & name , ReporterConfig const & config ) const = 0 ;
2012-10-28 13:07:17 +01:00
virtual const FactoryMap & getFactories ( ) const = 0 ;
2012-09-29 21:54:03 +02:00
} ;
2012-10-28 13:07:17 +01:00
2012-12-02 00:57:18 +01:00
inline std : : string trim ( std : : string const & str ) {
2012-10-28 13:07:17 +01:00
std : : string : : size_type start = str . find_first_not_of ( " \n \r \t " ) ;
std : : string : : size_type end = str . find_last_not_of ( " \n \r \t " ) ;
return start ! = std : : string : : npos ? str . substr ( start , 1 + end - start ) : " " ;
}
2012-09-29 21:54:03 +02:00
}
2012-10-28 13:07:17 +01:00
# include <vector>
2012-09-26 19:38:26 +02:00
namespace Catch {
2012-12-02 00:57:18 +01:00
class TestCase ;
2012-10-28 13:07:17 +01:00
struct ITestCaseRegistry ;
struct IExceptionTranslatorRegistry ;
struct IExceptionTranslator ;
2012-09-26 19:38:26 +02:00
2012-10-28 13:07:17 +01:00
struct IRegistryHub {
virtual ~ IRegistryHub ( ) ;
2012-09-26 19:38:26 +02:00
2012-10-28 13:07:17 +01:00
virtual const IReporterRegistry & getReporterRegistry ( ) const = 0 ;
virtual const ITestCaseRegistry & getTestCaseRegistry ( ) const = 0 ;
virtual IExceptionTranslatorRegistry & getExceptionTranslatorRegistry ( ) = 0 ;
} ;
2012-09-26 19:38:26 +02:00
2012-10-28 13:07:17 +01:00
struct IMutableRegistryHub {
virtual ~ IMutableRegistryHub ( ) ;
virtual void registerReporter ( const std : : string & name , IReporterFactory * factory ) = 0 ;
2012-12-02 00:57:18 +01:00
virtual void registerTest ( const TestCase & testInfo ) = 0 ;
2012-10-28 13:07:17 +01:00
virtual void registerTranslator ( const IExceptionTranslator * translator ) = 0 ;
} ;
2012-09-26 19:38:26 +02:00
2012-10-28 13:07:17 +01:00
IRegistryHub & getRegistryHub ( ) ;
IMutableRegistryHub & getMutableRegistryHub ( ) ;
void cleanUp ( ) ;
std : : string translateActiveException ( ) ;
2012-09-26 19:38:26 +02:00
2012-10-28 13:07:17 +01:00
}
# include <ostream>
namespace Catch {
inline IResultCapture & getResultCapture ( ) {
return getCurrentContext ( ) . getResultCapture ( ) ;
}
template < typename MatcherT >
ExpressionResultBuilder expressionResultBuilderFromMatcher ( const MatcherT & matcher ,
const std : : string & matcherCallAsString ) {
std : : string matcherAsString = matcher . toString ( ) ;
if ( matcherAsString = = " {?} " )
matcherAsString = matcherCallAsString ;
return ExpressionResultBuilder ( )
. setRhs ( matcherAsString )
. setOp ( " matches " ) ;
}
2012-09-26 19:38:26 +02:00
2012-10-28 13:07:17 +01:00
template < typename MatcherT , typename ArgT >
ExpressionResultBuilder expressionResultBuilderFromMatcher ( const MatcherT & matcher ,
const ArgT & arg ,
const std : : string & matcherCallAsString ) {
return expressionResultBuilderFromMatcher ( matcher , matcherCallAsString )
. setLhs ( Catch : : toString ( arg ) )
. setResultType ( matcher . match ( arg ) ) ;
}
2012-09-26 19:38:26 +02:00
2012-10-28 13:07:17 +01:00
template < typename MatcherT , typename ArgT >
ExpressionResultBuilder expressionResultBuilderFromMatcher ( const MatcherT & matcher ,
ArgT * arg ,
const std : : string & matcherCallAsString ) {
return expressionResultBuilderFromMatcher ( matcher , matcherCallAsString )
. setLhs ( Catch : : toString ( arg ) )
. setResultType ( matcher . match ( arg ) ) ;
}
2012-09-26 19:38:26 +02:00
2012-10-28 13:07:17 +01:00
struct TestFailureException { } ;
2012-09-26 19:38:26 +02:00
2012-10-28 13:07:17 +01:00
// This is just here to avoid compiler warnings with macro constants and boolean literals
inline bool isTrue ( bool value ) { return value ; }
2012-09-26 19:38:26 +02:00
2012-10-28 13:07:17 +01:00
} // end namespace Catch
2012-09-26 19:38:26 +02:00
2012-10-29 21:49:22 +01:00
///////////////////////////////////////////////////////////////////////////////
# define INTERNAL_CATCH_ASSERTIONINFO_NAME INTERNAL_CATCH_UNIQUE_NAME( __assertionInfo )
2012-10-28 13:07:17 +01:00
///////////////////////////////////////////////////////////////////////////////
2012-11-10 19:46:39 +01:00
# define INTERNAL_CATCH_ACCEPT_EXPR( evaluatedExpr, resultDisposition, originalExpr ) \
2012-10-29 21:49:22 +01:00
if ( Catch : : ResultAction : : Value internal_catch_action = Catch : : getResultCapture ( ) . acceptExpression ( evaluatedExpr , INTERNAL_CATCH_ASSERTIONINFO_NAME ) ) { \
2012-10-28 13:07:17 +01:00
if ( internal_catch_action & Catch : : ResultAction : : Debug ) BreakIntoDebugger ( ) ; \
if ( internal_catch_action & Catch : : ResultAction : : Abort ) throw Catch : : TestFailureException ( ) ; \
2012-11-10 19:46:39 +01:00
if ( ! Catch : : shouldContinueOnFailure ( resultDisposition ) ) throw Catch : : TestFailureException ( ) ; \
2013-03-11 19:38:29 +01:00
Catch : : isTrue ( false & & originalExpr ) ; \
2012-10-28 13:07:17 +01:00
}
2012-08-31 09:10:36 +02:00
2012-10-28 13:07:17 +01:00
///////////////////////////////////////////////////////////////////////////////
2012-11-10 19:46:39 +01:00
# define INTERNAL_CATCH_ACCEPT_INFO( expr, macroName, resultDisposition ) \
2012-11-13 10:44:52 +01:00
Catch : : AssertionInfo INTERNAL_CATCH_ASSERTIONINFO_NAME ( macroName , CATCH_INTERNAL_LINEINFO , expr , resultDisposition ) ;
2012-08-31 09:10:36 +02:00
2012-10-28 13:07:17 +01:00
///////////////////////////////////////////////////////////////////////////////
2012-11-10 19:46:39 +01:00
# define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \
2012-10-29 21:49:22 +01:00
do { \
2012-11-10 19:46:39 +01:00
INTERNAL_CATCH_ACCEPT_INFO ( # expr , macroName , resultDisposition ) ; \
2012-10-29 21:49:22 +01:00
try { \
2012-11-10 19:46:39 +01:00
INTERNAL_CATCH_ACCEPT_EXPR ( ( Catch : : ExpressionDecomposer ( ) - > * expr ) . endExpression ( resultDisposition ) , resultDisposition , expr ) ; \
2012-10-29 21:49:22 +01:00
} catch ( Catch : : TestFailureException & ) { \
throw ; \
} catch ( . . . ) { \
2012-11-10 19:46:39 +01:00
INTERNAL_CATCH_ACCEPT_EXPR ( Catch : : ExpressionResultBuilder ( Catch : : ResultWas : : ThrewException ) < < Catch : : translateActiveException ( ) , \
resultDisposition | Catch : : ResultDisposition : : ContinueOnFailure , expr ) ; \
2012-10-29 21:49:22 +01:00
throw ; \
} \
} while ( Catch : : isTrue ( false ) )
2012-08-31 09:10:36 +02:00
2012-10-28 13:07:17 +01:00
///////////////////////////////////////////////////////////////////////////////
2012-11-10 19:46:39 +01:00
# define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \
INTERNAL_CATCH_TEST ( expr , resultDisposition , macroName ) ; \
2012-11-13 10:44:52 +01:00
if ( Catch : : getResultCapture ( ) . getLastResult ( ) - > succeeded ( ) )
2012-08-31 09:10:36 +02:00
2012-10-28 13:07:17 +01:00
///////////////////////////////////////////////////////////////////////////////
2012-11-10 19:46:39 +01:00
# define INTERNAL_CATCH_ELSE( expr, resultDisposition, macroName ) \
INTERNAL_CATCH_TEST ( expr , resultDisposition , macroName ) ; \
2012-11-13 10:44:52 +01:00
if ( ! Catch : : getResultCapture ( ) . getLastResult ( ) - > succeeded ( ) )
2012-08-31 09:10:36 +02:00
2012-10-28 13:07:17 +01:00
///////////////////////////////////////////////////////////////////////////////
2012-11-10 19:46:39 +01:00
# define INTERNAL_CATCH_NO_THROW( expr, resultDisposition, macroName ) \
2012-10-29 21:49:22 +01:00
do { \
2012-11-10 19:46:39 +01:00
INTERNAL_CATCH_ACCEPT_INFO ( # expr , macroName , resultDisposition ) ; \
2012-10-29 21:49:22 +01:00
try { \
expr ; \
2012-11-10 19:46:39 +01:00
INTERNAL_CATCH_ACCEPT_EXPR ( Catch : : ExpressionResultBuilder ( Catch : : ResultWas : : Ok ) , resultDisposition , false ) ; \
2012-10-29 21:49:22 +01:00
} \
catch ( . . . ) { \
2012-11-10 19:46:39 +01:00
INTERNAL_CATCH_ACCEPT_EXPR ( Catch : : ExpressionResultBuilder ( Catch : : ResultWas : : ThrewException ) < < Catch : : translateActiveException ( ) , resultDisposition , false ) ; \
2012-10-29 21:49:22 +01:00
} \
} while ( Catch : : isTrue ( false ) )
2012-08-31 09:10:36 +02:00
2012-10-28 13:07:17 +01:00
///////////////////////////////////////////////////////////////////////////////
2012-11-10 19:46:39 +01:00
# define INTERNAL_CATCH_THROWS_IMPL( expr, exceptionType, resultDisposition ) \
2012-10-28 13:07:17 +01:00
try { \
if ( Catch : : getCurrentContext ( ) . getConfig ( ) - > allowThrows ( ) ) { \
expr ; \
2012-11-10 19:46:39 +01:00
INTERNAL_CATCH_ACCEPT_EXPR ( Catch : : ExpressionResultBuilder ( Catch : : ResultWas : : DidntThrowException ) , resultDisposition , false ) ; \
2012-10-28 13:07:17 +01:00
} \
} \
catch ( Catch : : TestFailureException & ) { \
throw ; \
} \
catch ( exceptionType ) { \
2012-11-10 19:46:39 +01:00
INTERNAL_CATCH_ACCEPT_EXPR ( Catch : : ExpressionResultBuilder ( Catch : : ResultWas : : Ok ) , resultDisposition , false ) ; \
2012-10-28 13:07:17 +01:00
}
2012-08-31 09:10:36 +02:00
2012-10-29 21:49:22 +01:00
///////////////////////////////////////////////////////////////////////////////
2012-11-10 19:46:39 +01:00
# define INTERNAL_CATCH_THROWS( expr, exceptionType, resultDisposition, macroName ) \
2012-10-29 21:49:22 +01:00
do { \
2012-11-10 19:46:39 +01:00
INTERNAL_CATCH_ACCEPT_INFO ( # expr , macroName , resultDisposition ) ; \
INTERNAL_CATCH_THROWS_IMPL ( expr , exceptionType , resultDisposition ) \
2012-10-29 21:49:22 +01:00
} while ( Catch : : isTrue ( false ) )
2012-10-28 13:07:17 +01:00
///////////////////////////////////////////////////////////////////////////////
2012-11-10 19:46:39 +01:00
# define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, resultDisposition, macroName ) \
2012-10-29 21:49:22 +01:00
do { \
2012-11-10 19:46:39 +01:00
INTERNAL_CATCH_ACCEPT_INFO ( # expr , macroName , resultDisposition ) ; \
INTERNAL_CATCH_THROWS_IMPL ( expr , exceptionType , resultDisposition ) \
2012-10-29 21:49:22 +01:00
catch ( . . . ) { \
2012-11-10 19:46:39 +01:00
INTERNAL_CATCH_ACCEPT_EXPR ( ( Catch : : ExpressionResultBuilder ( Catch : : ResultWas : : ThrewException ) < < Catch : : translateActiveException ( ) ) , \
resultDisposition | Catch : : ResultDisposition : : ContinueOnFailure , false ) ; \
2012-10-29 21:49:22 +01:00
} \
} while ( Catch : : isTrue ( false ) )
2012-08-31 09:10:36 +02:00
2012-10-28 13:07:17 +01:00
///////////////////////////////////////////////////////////////////////////////
2013-02-02 21:37:58 +01:00
# define INTERNAL_CATCH_INFO( log, macroName ) \
do { \
Catch : : getResultCapture ( ) . acceptMessage ( Catch : : MessageBuilder ( macroName , CATCH_INTERNAL_LINEINFO , Catch : : ResultWas : : Info ) < < log ) ; \
} while ( Catch : : isTrue ( false ) )
///////////////////////////////////////////////////////////////////////////////
# define INTERNAL_CATCH_MSG( log, messageType, resultDisposition, macroName ) \
2012-11-06 08:52:28 +01:00
do { \
2012-11-10 19:46:39 +01:00
INTERNAL_CATCH_ACCEPT_INFO ( " " , macroName , resultDisposition ) ; \
2013-02-02 21:37:58 +01:00
INTERNAL_CATCH_ACCEPT_EXPR ( Catch : : ExpressionResultBuilder ( messageType ) < < log , resultDisposition , true ) \
2012-11-06 08:52:28 +01:00
} while ( Catch : : isTrue ( false ) )
2012-08-31 09:10:36 +02:00
2012-10-28 13:07:17 +01:00
///////////////////////////////////////////////////////////////////////////////
# define INTERNAL_CATCH_SCOPED_INFO( log, macroName ) \
2013-02-02 21:37:58 +01:00
Catch : : ScopedMessageBuilder INTERNAL_CATCH_UNIQUE_NAME ( scopedMessage ) ( macroName , CATCH_INTERNAL_LINEINFO , Catch : : ResultWas : : Info ) ; \
INTERNAL_CATCH_UNIQUE_NAME ( scopedMessage ) < < log ; \
Catch : : getResultCapture ( ) . pushScopedMessage ( INTERNAL_CATCH_UNIQUE_NAME ( scopedMessage ) )
2012-08-31 09:10:36 +02:00
2012-10-28 13:07:17 +01:00
///////////////////////////////////////////////////////////////////////////////
2012-11-10 19:46:39 +01:00
# define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \
2012-10-29 21:49:22 +01:00
do { \
2012-11-10 19:46:39 +01:00
INTERNAL_CATCH_ACCEPT_INFO ( # arg " " # matcher , macroName , resultDisposition ) ; \
2012-10-29 21:49:22 +01:00
try { \
2012-11-10 19:46:39 +01:00
INTERNAL_CATCH_ACCEPT_EXPR ( ( Catch : : expressionResultBuilderFromMatcher ( : : Catch : : Matchers : : matcher , arg , # matcher ) ) , resultDisposition , false ) ; \
2012-10-29 21:49:22 +01:00
} catch ( Catch : : TestFailureException & ) { \
throw ; \
} catch ( . . . ) { \
2012-11-10 19:46:39 +01:00
INTERNAL_CATCH_ACCEPT_EXPR ( ( Catch : : ExpressionResultBuilder ( Catch : : ResultWas : : ThrewException ) < < Catch : : translateActiveException ( ) ) , \
resultDisposition | Catch : : ResultDisposition : : ContinueOnFailure , false ) ; \
2012-10-29 21:49:22 +01:00
throw ; \
} \
} while ( Catch : : isTrue ( false ) )
2012-08-31 09:10:36 +02:00
2012-10-28 13:07:17 +01:00
// #included from: internal/catch_section.hpp
# define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED
2012-08-31 09:10:36 +02:00
2012-10-28 13:07:17 +01:00
# include <string>
2012-08-31 09:10:36 +02:00
2012-10-28 13:07:17 +01:00
namespace Catch {
2012-08-31 09:10:36 +02:00
2012-10-28 13:07:17 +01:00
class Section {
2012-08-31 09:10:36 +02:00
public :
2012-10-28 13:07:17 +01:00
Section ( const std : : string & name ,
const std : : string & description ,
const SourceLineInfo & lineInfo )
2012-12-02 00:57:18 +01:00
: m_info ( name , description , lineInfo ) ,
m_sectionIncluded ( getCurrentContext ( ) . getResultCapture ( ) . sectionStarted ( m_info , m_assertions ) )
2012-08-31 09:10:36 +02:00
{ }
2012-10-28 13:07:17 +01:00
~ Section ( ) {
if ( m_sectionIncluded )
2012-12-02 00:57:18 +01:00
getCurrentContext ( ) . getResultCapture ( ) . sectionEnded ( m_info , m_assertions ) ;
2012-08-31 09:10:36 +02:00
}
2012-10-28 13:07:17 +01:00
// This indicates whether the section should be executed or not
operator bool ( ) {
return m_sectionIncluded ;
2012-08-31 09:10:36 +02:00
}
2012-10-28 13:07:17 +01:00
private :
2012-12-02 00:57:18 +01:00
SectionInfo m_info ;
2012-08-31 09:10:36 +02:00
2012-10-28 13:07:17 +01:00
std : : string m_name ;
Counts m_assertions ;
bool m_sectionIncluded ;
} ;
2012-08-31 09:10:36 +02:00
2012-10-28 13:07:17 +01:00
} // end namespace Catch
2012-08-31 09:10:36 +02:00
2012-10-28 13:07:17 +01:00
# define INTERNAL_CATCH_SECTION( name, desc ) \
if ( Catch : : Section INTERNAL_CATCH_UNIQUE_NAME ( catch_internal_Section ) = Catch : : Section ( name , desc , CATCH_INTERNAL_LINEINFO ) )
2012-08-31 09:10:36 +02:00
2012-10-28 13:07:17 +01:00
// #included from: internal/catch_generators.hpp
# define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED
2012-08-31 09:10:36 +02:00
2012-10-28 13:07:17 +01:00
# include <iterator>
# include <vector>
# include <string>
# include <stdlib.h>
2012-08-31 09:10:36 +02:00
2012-10-28 13:07:17 +01:00
namespace Catch {
2012-08-31 09:10:36 +02:00
2012-10-28 13:07:17 +01:00
template < typename T >
struct IGenerator {
virtual ~ IGenerator ( ) { }
virtual T getValue ( std : : size_t index ) const = 0 ;
virtual std : : size_t size ( ) const = 0 ;
} ;
2012-08-31 09:10:36 +02:00
2012-10-28 13:07:17 +01:00
template < typename T >
class BetweenGenerator : public IGenerator < T > {
public :
BetweenGenerator ( T from , T to ) : m_from ( from ) , m_to ( to ) { }
2012-08-31 09:10:36 +02:00
2012-10-28 13:07:17 +01:00
virtual T getValue ( std : : size_t index ) const {
2013-01-16 10:44:43 +01:00
return m_from + static_cast < int > ( index ) ;
2012-10-28 13:07:17 +01:00
}
virtual std : : size_t size ( ) const {
return static_cast < std : : size_t > ( 1 + m_to - m_from ) ;
}
private :
T m_from ;
T m_to ;
} ;
template < typename T >
class ValuesGenerator : public IGenerator < T > {
public :
ValuesGenerator ( ) { }
2012-09-07 18:52:35 +02:00
2012-10-28 13:07:17 +01:00
void add ( T value ) {
m_values . push_back ( value ) ;
}
2012-08-31 09:10:36 +02:00
2012-10-28 13:07:17 +01:00
virtual T getValue ( std : : size_t index ) const {
return m_values [ index ] ;
}
2012-08-31 09:10:36 +02:00
2012-10-28 13:07:17 +01:00
virtual std : : size_t size ( ) const {
return m_values . size ( ) ;
}
2012-08-31 09:10:36 +02:00
2012-10-28 13:07:17 +01:00
private :
std : : vector < T > m_values ;
} ;
2012-08-31 09:10:36 +02:00
2012-10-28 13:07:17 +01:00
template < typename T >
class CompositeGenerator {
public :
CompositeGenerator ( ) : m_totalSize ( 0 ) { }
2012-08-31 09:10:36 +02:00
2013-03-08 10:30:25 +01:00
// *** Move semantics, similar to auto_ptr ***
2012-10-28 13:07:17 +01:00
CompositeGenerator ( CompositeGenerator & other )
: m_fileInfo ( other . m_fileInfo ) ,
m_totalSize ( 0 )
{
2013-03-08 10:30:25 +01:00
move ( other ) ;
2012-10-28 13:07:17 +01:00
}
2012-08-31 09:10:36 +02:00
2012-10-28 13:07:17 +01:00
CompositeGenerator & setFileInfo ( const char * fileInfo ) {
m_fileInfo = fileInfo ;
return * this ;
}
2012-08-31 09:10:36 +02:00
2012-10-28 13:07:17 +01:00
~ CompositeGenerator ( ) {
deleteAll ( m_composed ) ;
}
2012-08-31 09:10:36 +02:00
2012-10-28 13:07:17 +01:00
operator T ( ) const {
size_t overallIndex = getCurrentContext ( ) . getGeneratorIndex ( m_fileInfo , m_totalSize ) ;
2012-08-31 09:10:36 +02:00
2012-10-28 13:07:17 +01:00
typename std : : vector < const IGenerator < T > * > : : const_iterator it = m_composed . begin ( ) ;
typename std : : vector < const IGenerator < T > * > : : const_iterator itEnd = m_composed . end ( ) ;
for ( size_t index = 0 ; it ! = itEnd ; + + it )
{
const IGenerator < T > * generator = * it ;
if ( overallIndex > = index & & overallIndex < index + generator - > size ( ) )
{
return generator - > getValue ( overallIndex - index ) ;
}
index + = generator - > size ( ) ;
}
CATCH_INTERNAL_ERROR ( " Indexed past end of generated range " ) ;
2013-03-08 10:30:25 +01:00
return T ( ) ; // Suppress spurious "not all control paths return a value" warning in Visual Studio - if you know how to fix this please do so
2012-10-28 13:07:17 +01:00
}
2012-09-24 09:30:13 +02:00
2012-10-28 13:07:17 +01:00
void add ( const IGenerator < T > * generator ) {
m_totalSize + = generator - > size ( ) ;
m_composed . push_back ( generator ) ;
}
2012-09-24 09:30:13 +02:00
2012-10-28 13:07:17 +01:00
CompositeGenerator & then ( CompositeGenerator & other ) {
move ( other ) ;
return * this ;
}
2012-08-31 09:10:36 +02:00
2012-10-28 13:07:17 +01:00
CompositeGenerator & then ( T value ) {
ValuesGenerator < T > * valuesGen = new ValuesGenerator < T > ( ) ;
valuesGen - > add ( value ) ;
add ( valuesGen ) ;
return * this ;
}
2012-08-31 09:10:36 +02:00
2012-10-28 13:07:17 +01:00
private :
2012-08-31 09:10:36 +02:00
2012-10-28 13:07:17 +01:00
void move ( CompositeGenerator & other ) {
std : : copy ( other . m_composed . begin ( ) , other . m_composed . end ( ) , std : : back_inserter ( m_composed ) ) ;
m_totalSize + = other . m_totalSize ;
other . m_composed . clear ( ) ;
}
2012-08-31 09:10:36 +02:00
2012-10-28 13:07:17 +01:00
std : : vector < const IGenerator < T > * > m_composed ;
std : : string m_fileInfo ;
size_t m_totalSize ;
} ;
2012-08-31 09:10:36 +02:00
2012-10-28 13:07:17 +01:00
namespace Generators
{
template < typename T >
CompositeGenerator < T > between ( T from , T to ) {
CompositeGenerator < T > generators ;
generators . add ( new BetweenGenerator < T > ( from , to ) ) ;
return generators ;
}
2012-08-31 09:10:36 +02:00
2012-10-28 13:07:17 +01: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 ;
}
2012-08-31 09:10:36 +02:00
2012-10-28 13:07:17 +01: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 ;
2012-08-31 09:10:36 +02:00
}
2012-10-28 13:07:17 +01: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 ;
}
2012-08-31 09:10:36 +02:00
2012-10-28 13:07:17 +01:00
} // end namespace Generators
2012-08-31 09:10:36 +02:00
2012-10-28 13:07:17 +01:00
using namespace Generators ;
2012-08-31 09:10:36 +02:00
2012-10-28 13:07:17 +01:00
} // end namespace Catch
2012-08-31 09:10:36 +02:00
2012-10-28 13:07:17 +01:00
# define INTERNAL_CATCH_LINESTR2( line ) #line
# define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line )
2012-08-31 09:10:36 +02:00
2012-10-28 13:07:17 +01:00
# define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" )
2012-08-31 09:10:36 +02:00
2012-10-28 13:07:17 +01:00
// #included from: internal/catch_interfaces_exception.h
# define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED
2012-08-31 09:10:36 +02:00
2012-10-28 13:07:17 +01:00
# include <string>
2012-08-31 09:10:36 +02:00
namespace Catch {
typedef std : : string ( * exceptionTranslateFunction ) ( ) ;
struct IExceptionTranslator {
virtual ~ IExceptionTranslator ( ) ;
virtual std : : string translate ( ) const = 0 ;
} ;
struct IExceptionTranslatorRegistry {
virtual ~ IExceptionTranslatorRegistry ( ) ;
virtual std : : string translateActiveException ( ) const = 0 ;
} ;
class ExceptionTranslatorRegistrar {
template < typename T >
class ExceptionTranslator : public IExceptionTranslator {
public :
ExceptionTranslator ( std : : string ( * translateFunction ) ( T & ) )
: m_translateFunction ( translateFunction )
{ }
virtual std : : string translate ( ) const {
try {
throw ;
}
catch ( T & ex ) {
return m_translateFunction ( ex ) ;
}
}
protected :
std : : string ( * m_translateFunction ) ( T & ) ;
} ;
public :
template < typename T >
ExceptionTranslatorRegistrar ( std : : string ( * translateFunction ) ( T & ) ) {
getMutableRegistryHub ( ) . registerTranslator
( new ExceptionTranslator < T > ( translateFunction ) ) ;
}
} ;
}
///////////////////////////////////////////////////////////////////////////////
# define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) \
static std : : string INTERNAL_CATCH_UNIQUE_NAME ( catch_internal_ExceptionTranslator ) ( signature ) ; \
namespace { Catch : : ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME ( catch_internal_ExceptionRegistrar ) ( & INTERNAL_CATCH_UNIQUE_NAME ( catch_internal_ExceptionTranslator ) ) ; } \
static std : : string INTERNAL_CATCH_UNIQUE_NAME ( catch_internal_ExceptionTranslator ) ( signature )
// #included from: internal/catch_approx.hpp
# define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
# include <cmath>
# include <limits>
namespace Catch {
namespace Detail {
class Approx {
public :
explicit Approx ( double value )
: m_epsilon ( std : : numeric_limits < float > : : epsilon ( ) * 100 ) ,
m_scale ( 1.0 ) ,
m_value ( value )
{ }
Approx ( const Approx & other )
: m_epsilon ( other . m_epsilon ) ,
m_scale ( other . m_scale ) ,
m_value ( other . m_value )
{ }
static Approx custom ( ) {
return Approx ( 0 ) ;
}
Approx operator ( ) ( double value ) {
Approx approx ( value ) ;
approx . epsilon ( m_epsilon ) ;
approx . scale ( m_scale ) ;
return approx ;
}
friend bool operator = = ( double lhs , const Approx & 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 ) ) ) ;
}
friend bool operator = = ( const Approx & lhs , double rhs ) {
return operator = = ( rhs , lhs ) ;
}
friend bool operator ! = ( double lhs , const Approx & rhs ) {
return ! operator = = ( lhs , rhs ) ;
2012-05-16 16:09:17 +02:00
}
2011-05-24 09:23:02 +02:00
2012-05-16 16:09:17 +02:00
friend bool operator ! = ( const Approx & lhs , double rhs ) {
return ! operator = = ( rhs , lhs ) ;
}
2011-05-24 09:23:02 +02:00
2012-05-16 16:09:17 +02:00
Approx & epsilon ( double newEpsilon ) {
m_epsilon = newEpsilon ;
return * this ;
}
2011-05-24 09:23:02 +02:00
2012-05-16 16:09:17 +02:00
Approx & scale ( double newScale ) {
m_scale = newScale ;
return * this ;
}
2011-05-24 09:23:02 +02:00
2012-05-16 16:09:17 +02:00
std : : string toString ( ) const {
std : : ostringstream oss ;
2012-10-09 12:48:55 +02:00
oss < < " Approx( " < < m_value < < " ) " ;
2012-05-16 16:09:17 +02:00
return oss . str ( ) ;
}
2011-05-24 09:23:02 +02:00
2012-05-16 16:09:17 +02:00
private :
double m_epsilon ;
double m_scale ;
double m_value ;
} ;
}
template < >
inline std : : string toString < Detail : : Approx > ( const Detail : : Approx & value ) {
return value . toString ( ) ;
}
2011-05-24 09:23:02 +02:00
} // end namespace Catch
2012-05-21 19:52:09 +02:00
// #included from: internal/catch_matchers.hpp
2012-08-09 08:47:30 +02:00
# define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED
2012-05-21 19:52:09 +02:00
namespace Catch {
namespace Matchers {
namespace Impl {
2012-10-12 08:58:17 +02:00
template < typename ExpressionT >
struct Matcher : SharedImpl < IShared >
{
2012-12-06 09:44:51 +01:00
typedef ExpressionT ExpressionType ;
2012-10-12 08:58:17 +02:00
virtual ~ Matcher ( ) { }
virtual Ptr < Matcher > clone ( ) const = 0 ;
2012-12-06 09:44:51 +01:00
virtual bool match ( ExpressionT const & expr ) const = 0 ;
2012-10-12 08:58:17 +02:00
virtual std : : string toString ( ) const = 0 ;
} ;
template < typename DerivedT , typename ExpressionT >
struct MatcherImpl : Matcher < ExpressionT > {
virtual Ptr < Matcher < ExpressionT > > clone ( ) const {
return Ptr < Matcher < ExpressionT > > ( new DerivedT ( static_cast < const DerivedT & > ( * this ) ) ) ;
}
} ;
namespace Generic {
2012-05-24 09:29:41 +02:00
2012-10-12 08:58:17 +02:00
template < typename ExpressionT >
class AllOf : public MatcherImpl < AllOf < ExpressionT > , ExpressionT > {
public :
AllOf ( ) { }
AllOf ( const AllOf & other ) : m_matchers ( other . m_matchers ) { }
AllOf & add ( const Matcher < ExpressionT > & matcher ) {
m_matchers . push_back ( matcher . clone ( ) ) ;
return * this ;
}
virtual bool match ( const ExpressionT & expr ) const
2012-05-24 09:29:41 +02:00
{
2012-10-12 08:58:17 +02:00
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 ( ) ;
2012-05-24 09:29:41 +02:00
}
2012-10-12 08:58:17 +02:00
private :
std : : vector < Ptr < Matcher < ExpressionT > > > m_matchers ;
} ;
template < typename ExpressionT >
class AnyOf : public MatcherImpl < AnyOf < ExpressionT > , ExpressionT > {
public :
AnyOf ( ) { }
AnyOf ( const AnyOf & other ) : m_matchers ( other . m_matchers ) { }
AnyOf & add ( const Matcher < ExpressionT > & matcher ) {
m_matchers . push_back ( matcher . clone ( ) ) ;
return * this ;
}
virtual bool match ( const ExpressionT & expr ) const
2012-05-24 09:29:41 +02:00
{
2012-10-12 08:58:17 +02:00
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 ( ) ;
2012-05-24 09:29:41 +02:00
}
2012-10-12 08:58:17 +02:00
private :
std : : vector < Ptr < Matcher < ExpressionT > > > m_matchers ;
} ;
}
namespace StdString {
struct Equals : MatcherImpl < Equals , std : : string > {
Equals ( const std : : string & str ) : m_str ( str ) { }
Equals ( const Equals & other ) : m_str ( other . m_str ) { }
virtual ~ Equals ( ) ;
virtual bool match ( const std : : string & expr ) const {
return m_str = = expr ;
}
virtual std : : string toString ( ) const {
return " equals: \" " + m_str + " \" " ;
}
2012-08-31 09:10:36 +02:00
std : : string m_str ;
} ;
2012-03-04 22:22:36 +01:00
2012-10-12 08:58:17 +02:00
struct Contains : MatcherImpl < Contains , std : : string > {
2012-08-31 09:10:36 +02:00
Contains ( const std : : string & substr ) : m_substr ( substr ) { }
2012-10-12 08:58:17 +02:00
Contains ( const Contains & other ) : m_substr ( other . m_substr ) { }
2012-03-04 22:22:36 +01:00
2012-10-12 08:58:17 +02:00
virtual ~ Contains ( ) ;
2012-03-04 22:22:36 +01:00
2012-10-12 08:58:17 +02:00
virtual bool match ( const std : : string & expr ) const {
return expr . find ( m_substr ) ! = std : : string : : npos ;
2012-08-31 09:10:36 +02:00
}
2012-10-12 08:58:17 +02:00
virtual std : : string toString ( ) const {
return " contains: \" " + m_substr + " \" " ;
}
2012-08-31 09:10:36 +02:00
std : : string m_substr ;
} ;
2012-03-04 22:22:36 +01:00
2012-10-12 08:58:17 +02:00
struct StartsWith : MatcherImpl < StartsWith , std : : string > {
2012-08-31 09:10:36 +02:00
StartsWith ( const std : : string & substr ) : m_substr ( substr ) { }
2012-10-12 08:58:17 +02:00
StartsWith ( const StartsWith & other ) : m_substr ( other . m_substr ) { }
2012-03-04 22:22:36 +01:00
2012-10-12 08:58:17 +02:00
virtual ~ StartsWith ( ) ;
2012-03-04 22:22:36 +01:00
2012-10-12 08:58:17 +02:00
virtual bool match ( const std : : string & expr ) const {
return expr . find ( m_substr ) = = 0 ;
}
virtual std : : string toString ( ) const {
return " starts with: \" " + m_substr + " \" " ;
2012-08-31 09:10:36 +02:00
}
2012-10-12 08:58:17 +02:00
2012-08-31 09:10:36 +02:00
std : : string m_substr ;
} ;
2012-03-04 22:22:36 +01:00
2012-10-12 08:58:17 +02:00
struct EndsWith : MatcherImpl < EndsWith , std : : string > {
2012-08-31 09:10:36 +02:00
EndsWith ( const std : : string & substr ) : m_substr ( substr ) { }
2012-10-12 08:58:17 +02:00
EndsWith ( const EndsWith & other ) : m_substr ( other . m_substr ) { }
2012-03-14 21:06:14 +01:00
2012-10-12 08:58:17 +02:00
virtual ~ EndsWith ( ) ;
2012-03-14 21:06:14 +01:00
2012-10-12 08:58:17 +02:00
virtual bool match ( const std : : string & expr ) const {
return expr . find ( m_substr ) = = expr . size ( ) - m_substr . size ( ) ;
2012-08-31 09:10:36 +02:00
}
2012-10-12 08:58:17 +02:00
virtual std : : string toString ( ) const {
return " ends with: \" " + m_substr + " \" " ;
}
2012-08-31 09:10:36 +02:00
std : : string m_substr ;
} ;
} // namespace StdString
} // namespace Impl
2012-03-14 21:06:14 +01:00
2012-10-12 08:58:17 +02:00
// The following functions create the actual matcher objects.
// This allows the types to be inferred
template < typename ExpressionT >
inline Impl : : Generic : : AllOf < ExpressionT > AllOf ( const Impl : : Matcher < ExpressionT > & m1 ,
const Impl : : Matcher < ExpressionT > & m2 ) {
return Impl : : Generic : : AllOf < ExpressionT > ( ) . add ( m1 ) . add ( m2 ) ;
}
template < typename ExpressionT >
inline Impl : : Generic : : AllOf < ExpressionT > AllOf ( const Impl : : Matcher < ExpressionT > & m1 ,
const Impl : : Matcher < ExpressionT > & m2 ,
const Impl : : Matcher < ExpressionT > & m3 ) {
return Impl : : Generic : : AllOf < ExpressionT > ( ) . add ( m1 ) . add ( m2 ) . add ( m3 ) ;
}
template < typename ExpressionT >
inline Impl : : Generic : : AnyOf < ExpressionT > AnyOf ( const Impl : : Matcher < ExpressionT > & m1 ,
const Impl : : Matcher < ExpressionT > & m2 ) {
return Impl : : Generic : : AnyOf < ExpressionT > ( ) . add ( m1 ) . add ( m2 ) ;
}
template < typename ExpressionT >
inline Impl : : Generic : : AnyOf < ExpressionT > AnyOf ( const Impl : : Matcher < ExpressionT > & m1 ,
const Impl : : Matcher < ExpressionT > & m2 ,
const Impl : : Matcher < ExpressionT > & m3 ) {
return Impl : : Generic : : AnyOf < ExpressionT > ( ) . add ( m1 ) . add ( m2 ) . add ( m3 ) ;
}
2012-08-31 09:10:36 +02:00
inline Impl : : StdString : : Equals Equals ( const std : : string & str ) { return Impl : : StdString : : Equals ( str ) ; }
inline Impl : : StdString : : Contains Contains ( const std : : string & substr ) { return Impl : : StdString : : Contains ( substr ) ; }
inline Impl : : StdString : : StartsWith StartsWith ( const std : : string & substr ) { return Impl : : StdString : : StartsWith ( substr ) ; }
inline Impl : : StdString : : EndsWith EndsWith ( const std : : string & substr ) { return Impl : : StdString : : EndsWith ( substr ) ; }
2012-03-04 22:22:36 +01:00
2012-08-31 09:10:36 +02:00
} // namespace Matchers
2012-03-04 22:22:36 +01:00
2012-08-31 09:10:36 +02:00
using namespace Matchers ;
2012-03-04 22:22:36 +01:00
} // namespace Catch
2011-08-12 19:53:28 +02:00
2012-08-31 09:10:36 +02:00
// These files are included here so the single_include script doesn't put them
// in the conditionally compiled sections
// #included from: internal/catch_interfaces_runner.h
2012-09-17 07:42:29 +02:00
# define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED
2011-08-12 19:53:28 +02:00
2012-08-31 09:10:36 +02:00
# include <string>
2011-08-12 19:53:28 +02:00
2012-08-31 09:10:36 +02:00
namespace Catch {
2012-12-02 00:57:18 +01:00
class TestCase ;
2012-08-13 08:46:10 +02:00
2012-08-31 09:10:36 +02:00
struct IRunner {
virtual ~ IRunner ( ) ;
} ;
}
2012-08-13 08:46:10 +02:00
2012-08-31 09:10:36 +02:00
# ifdef __OBJC__
// #included from: internal/catch_objc.hpp
# define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED
2011-08-12 19:53:28 +02:00
2012-08-31 09:10:36 +02:00
# import <objc / runtime.h>
2011-08-12 19:53:28 +02:00
2012-08-31 09:10:36 +02:00
# include <string>
2012-08-13 08:46:10 +02:00
2012-08-31 09:10:36 +02:00
// 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
2012-08-13 08:46:10 +02:00
2012-08-31 09:10:36 +02:00
///////////////////////////////////////////////////////////////////////////////
// This protocol is really only here for (self) documenting purposes, since
// all its methods are optional.
@ protocol OcFixture
2012-08-13 08:46:10 +02:00
2012-08-31 09:10:36 +02:00
@ optional
2012-08-13 08:46:10 +02:00
2012-08-31 09:10:36 +02:00
- ( void ) setUp ;
- ( void ) tearDown ;
2012-08-13 08:46:10 +02:00
2012-08-31 09:10:36 +02:00
@ end
2012-08-24 09:23:50 +02:00
2012-08-31 09:10:36 +02:00
namespace Catch {
2012-08-13 08:46:10 +02:00
2012-08-31 09:10:36 +02:00
class OcMethod : public SharedImpl < ITestCase > {
2012-08-13 08:46:10 +02:00
2012-08-31 09:10:36 +02:00
public :
OcMethod ( Class cls , SEL sel ) : m_cls ( cls ) , m_sel ( sel ) { }
2011-05-24 09:23:02 +02:00
2012-08-31 09:10:36 +02:00
virtual void invoke ( ) const {
id obj = [ [ m_cls alloc ] init ] ;
2012-08-27 22:48:15 +02:00
2012-08-31 09:10:36 +02:00
performOptionalSelector ( obj , @ selector ( setUp ) ) ;
performOptionalSelector ( obj , m_sel ) ;
performOptionalSelector ( obj , @ selector ( tearDown ) ) ;
2012-08-24 09:23:50 +02:00
2012-08-31 09:10:36 +02:00
arcSafeRelease ( obj ) ;
2012-08-23 21:08:50 +02:00
}
2012-08-31 09:10:36 +02:00
private :
virtual ~ OcMethod ( ) { }
2012-05-16 16:09:17 +02:00
2012-08-31 09:10:36 +02:00
Class m_cls ;
SEL m_sel ;
2012-08-23 21:08:50 +02:00
} ;
2011-05-24 09:23:02 +02:00
2012-08-31 09:10:36 +02:00
namespace Detail {
2011-05-24 09:23:02 +02:00
2012-08-31 09:10:36 +02:00
inline bool startsWith ( const std : : string & str , const std : : string & sub ) {
return str . length ( ) > sub . length ( ) & & str . substr ( 0 , sub . length ( ) ) = = sub ;
2012-08-23 21:08:50 +02:00
}
2011-05-24 09:23:02 +02:00
2012-08-31 09:10:36 +02:00
inline std : : string getAnnotation ( Class cls ,
const std : : string & annotationName ,
const std : : string & 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 " " ;
2012-08-23 21:08:50 +02:00
}
2012-08-31 09:10:36 +02:00
}
2012-07-05 19:37:58 +02:00
2012-08-31 09:10:36 +02:00
inline size_t registerTestMethods ( ) {
size_t noTestMethods = 0 ;
int noClasses = objc_getClassList ( NULL , 0 ) ;
2012-08-23 21:08:50 +02:00
2012-08-31 09:10:36 +02:00
Class * classes = ( CATCH_UNSAFE_UNRETAINED Class * ) malloc ( sizeof ( Class ) * noClasses ) ;
objc_getClassList ( classes , noClasses ) ;
2011-05-24 09:23:02 +02:00
2012-08-31 09:10:36 +02:00
for ( int c = 0 ; c < noClasses ; c + + ) {
Class cls = classes [ c ] ;
{
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 ( Detail : : 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 ) ;
2013-02-19 20:47:18 +01:00
const char * className = class_getName ( cls ) ;
2012-07-05 19:37:58 +02:00
2013-02-19 20:47:18 +01:00
getMutableRegistryHub ( ) . registerTest ( makeTestCase ( new OcMethod ( cls , selector ) , className , name . c_str ( ) , desc . c_str ( ) , SourceLineInfo ( ) ) ) ;
2012-08-31 09:10:36 +02:00
noTestMethods + + ;
}
}
free ( methods ) ;
}
}
return noTestMethods ;
}
2011-05-24 09:23:02 +02:00
2012-08-31 09:10:36 +02:00
namespace Matchers {
namespace Impl {
namespace NSStringMatchers {
2011-05-24 09:23:02 +02:00
2012-12-06 09:44:51 +01:00
template < typename MatcherT >
struct StringHolder : MatcherImpl < MatcherT , NSString * > {
2012-08-31 09:10:36 +02:00
StringHolder ( NSString * substr ) : m_substr ( [ substr copy ] ) { }
2012-12-06 09:44:51 +01:00
StringHolder ( StringHolder const & other ) : m_substr ( [ other . m_substr copy ] ) { }
2012-08-31 09:10:36 +02:00
StringHolder ( ) {
arcSafeRelease ( m_substr ) ;
}
2011-05-24 09:23:02 +02:00
2012-08-31 09:10:36 +02:00
NSString * m_substr ;
} ;
2011-05-24 09:23:02 +02:00
2012-12-06 09:44:51 +01:00
struct Equals : StringHolder < Equals > {
2012-08-31 09:10:36 +02:00
Equals ( NSString * substr ) : StringHolder ( substr ) { }
2011-05-24 09:23:02 +02:00
2012-12-06 09:44:51 +01:00
virtual bool match ( ExpressionType const & str ) const {
2012-08-31 09:10:36 +02:00
return [ str isEqualToString : m_substr ] ;
}
2011-05-24 09:23:02 +02:00
2012-12-06 09:44:51 +01:00
virtual std : : string toString ( ) const {
return " equals string: \" " + Catch : : toString ( m_substr ) + " \" " ;
2012-08-31 09:10:36 +02:00
}
} ;
2011-05-24 09:23:02 +02:00
2012-12-06 09:44:51 +01:00
struct Contains : StringHolder < Contains > {
2012-08-31 09:10:36 +02:00
Contains ( NSString * substr ) : StringHolder ( substr ) { }
2011-05-24 09:23:02 +02:00
2012-12-06 09:44:51 +01:00
virtual bool match ( ExpressionType const & str ) const {
2012-08-31 09:10:36 +02:00
return [ str rangeOfString : m_substr ] . location ! = NSNotFound ;
}
2012-08-13 08:46:10 +02:00
2012-12-06 09:44:51 +01:00
virtual std : : string toString ( ) const {
return " contains string: \" " + Catch : : toString ( m_substr ) + " \" " ;
2012-08-31 09:10:36 +02:00
}
} ;
2012-08-23 21:08:50 +02:00
2012-12-06 09:44:51 +01:00
struct StartsWith : StringHolder < StartsWith > {
2012-08-31 09:10:36 +02:00
StartsWith ( NSString * substr ) : StringHolder ( substr ) { }
2012-08-13 08:46:10 +02:00
2012-12-06 09:44:51 +01:00
virtual bool match ( ExpressionType const & str ) const {
2012-08-31 09:10:36 +02:00
return [ str rangeOfString : m_substr ] . location = = 0 ;
}
2012-08-13 08:46:10 +02:00
2012-12-06 09:44:51 +01:00
virtual std : : string toString ( ) const {
return " starts with: \" " + Catch : : toString ( m_substr ) + " \" " ;
2012-08-31 09:10:36 +02:00
}
} ;
2012-12-06 09:44:51 +01:00
struct EndsWith : StringHolder < EndsWith > {
2012-08-31 09:10:36 +02:00
EndsWith ( NSString * substr ) : StringHolder ( substr ) { }
2011-05-24 09:23:02 +02:00
2012-12-06 09:44:51 +01:00
virtual bool match ( ExpressionType const & str ) const {
2012-08-31 09:10:36 +02:00
return [ str rangeOfString : m_substr ] . location = = [ str length ] - [ m_substr length ] ;
}
2011-05-24 09:23:02 +02:00
2012-12-06 09:44:51 +01:00
virtual std : : string toString ( ) const {
return " ends with: \" " + Catch : : toString ( m_substr ) + " \" " ;
2012-08-31 09:10:36 +02:00
}
} ;
2011-05-24 09:23:02 +02:00
2012-08-31 09:10:36 +02:00
} // namespace NSStringMatchers
} // namespace Impl
2011-05-24 09:23:02 +02:00
2012-08-31 09:10:36 +02:00
inline Impl : : NSStringMatchers : : Equals
Equals ( NSString * substr ) { return Impl : : NSStringMatchers : : Equals ( substr ) ; }
2011-05-24 09:23:02 +02:00
2012-08-31 09:10:36 +02:00
inline Impl : : NSStringMatchers : : Contains
Contains ( NSString * substr ) { return Impl : : NSStringMatchers : : Contains ( substr ) ; }
2011-05-24 09:23:02 +02:00
2012-08-31 09:10:36 +02:00
inline Impl : : NSStringMatchers : : StartsWith
StartsWith ( NSString * substr ) { return Impl : : NSStringMatchers : : StartsWith ( substr ) ; }
2011-05-24 09:23:02 +02:00
2012-08-31 09:10:36 +02:00
inline Impl : : NSStringMatchers : : EndsWith
EndsWith ( NSString * substr ) { return Impl : : NSStringMatchers : : EndsWith ( substr ) ; }
2012-06-01 20:40:27 +02:00
2012-08-31 09:10:36 +02:00
} // namespace Matchers
2012-06-05 21:51:05 +02:00
2012-08-31 09:10:36 +02:00
using namespace Matchers ;
2012-06-05 21:51:05 +02:00
2012-08-31 09:10:36 +02:00
} // namespace Catch
2011-05-24 09:23:02 +02:00
2012-08-31 09:10:36 +02:00
///////////////////////////////////////////////////////////////////////////////
# define OC_TEST_CASE( name, desc )\
+ ( 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 )
2012-08-09 08:47:30 +02:00
2012-08-31 09:10:36 +02:00
# endif
2011-05-24 09:23:02 +02:00
2012-08-31 09:10:36 +02:00
# if defined( CATCH_CONFIG_MAIN ) || defined( CATCH_CONFIG_RUNNER )
// #included from: internal/catch_impl.hpp
2012-09-17 07:42:29 +02:00
# define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED
2011-05-24 09:23:02 +02:00
2012-08-31 09:10:36 +02:00
// Collect all the implementation files together here
// These are the equivalent of what would usually be cpp files
2011-05-24 09:23:02 +02:00
2012-08-31 09:10:36 +02:00
# ifdef __clang__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wweak-vtables"
# endif
2012-05-16 16:09:17 +02:00
2012-08-31 09:10:36 +02:00
// #included from: catch_runner.hpp
# define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED
2012-05-16 16:09:17 +02:00
2012-08-31 09:10:36 +02:00
// #included from: internal/catch_commandline.hpp
# define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED
2012-08-23 21:08:50 +02:00
namespace Catch {
class Command {
public :
Command ( ) { }
2012-08-27 22:42:55 +02:00
explicit Command ( const std : : string & name ) : m_name ( name ) {
}
2012-08-23 21:08:50 +02:00
Command & operator + = ( const std : : string & arg ) {
m_args . push_back ( arg ) ;
return * this ;
}
Command & operator + = ( const Command & other ) {
std : : copy ( other . m_args . begin ( ) , other . m_args . end ( ) , std : : back_inserter ( m_args ) ) ;
if ( m_name . empty ( ) )
m_name = other . m_name ;
return * this ;
}
Command operator + ( const Command & other ) {
Command newCommand ( * this ) ;
newCommand + = other ;
return newCommand ;
2012-08-13 08:46:10 +02:00
}
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
operator SafeBool : : type ( ) const {
2012-08-24 19:54:56 +02:00
return SafeBool : : makeSafe ( ! m_name . empty ( ) | | ! m_args . empty ( ) ) ;
2012-08-23 21:08:50 +02:00
}
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
std : : string name ( ) const { return m_name ; }
std : : string operator [ ] ( std : : size_t i ) const { return m_args [ i ] ; }
std : : size_t argsCount ( ) const { return m_args . size ( ) ; }
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
CATCH_ATTRIBUTE_NORETURN
void raiseError ( const std : : string & message ) const {
std : : ostringstream oss ;
2012-08-27 22:42:55 +02:00
if ( m_name . empty ( ) )
oss < < " Error while parsing " < < m_name < < " . " < < message < < " . " ;
else
oss < < " Error while parsing arguments. " < < message < < " . " ;
2012-08-23 21:08:50 +02:00
if ( m_args . size ( ) > 0 )
2012-08-27 22:42:55 +02:00
oss < < " Arguments were: " ;
2012-08-23 21:08:50 +02:00
for ( std : : size_t i = 0 ; i < m_args . size ( ) ; + + i )
oss < < " " < < m_args [ i ] ;
throw std : : domain_error ( oss . str ( ) ) ;
2011-05-24 09:23:02 +02:00
}
2012-08-23 21:08:50 +02:00
private :
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
std : : string m_name ;
std : : vector < std : : string > m_args ;
} ;
class CommandParser {
public :
CommandParser ( int argc , char const * const * argv ) : m_argc ( static_cast < std : : size_t > ( argc ) ) , m_argv ( argv ) { }
2012-09-07 18:52:35 +02:00
std : : string exeName ( ) const {
2012-11-19 20:59:10 +01:00
std : : string exeName = m_argv [ 0 ] ;
std : : string : : size_type pos = exeName . find_last_of ( " / \\ " ) ;
if ( pos ! = std : : string : : npos )
exeName = exeName . substr ( pos + 1 ) ;
return exeName ;
2012-09-07 18:52:35 +02:00
}
2012-08-23 21:08:50 +02:00
Command find ( const std : : string & arg1 , const std : : string & arg2 , const std : : string & arg3 ) const {
return find ( arg1 ) + find ( arg2 ) + find ( arg3 ) ;
}
Command find ( const std : : string & shortArg , const std : : string & longArg ) const {
return find ( shortArg ) + find ( longArg ) ;
}
Command find ( const std : : string & arg ) const {
2012-08-27 22:42:55 +02:00
if ( arg . empty ( ) )
return getArgs ( " " , 1 ) ;
else
for ( std : : size_t i = 1 ; i < m_argc ; + + i )
if ( m_argv [ i ] = = arg )
return getArgs ( m_argv [ i ] , i + 1 ) ;
2012-08-23 21:08:50 +02:00
return Command ( ) ;
}
2012-08-24 19:54:56 +02:00
Command getDefaultArgs ( ) const {
return getArgs ( " " , 1 ) ;
}
2012-08-23 21:08:50 +02:00
private :
2012-08-24 19:54:56 +02:00
Command getArgs ( const std : : string & cmdName , std : : size_t from ) const {
Command command ( cmdName ) ;
for ( std : : size_t i = from ; i < m_argc & & m_argv [ i ] [ 0 ] ! = ' - ' ; + + i )
2012-08-23 21:08:50 +02:00
command + = m_argv [ i ] ;
return command ;
}
std : : size_t m_argc ;
char const * const * m_argv ;
} ;
2012-08-27 22:42:55 +02:00
class OptionParser : public SharedImpl < IShared > {
public :
OptionParser ( int minArgs = 0 , int maxArgs = 0 )
: m_minArgs ( minArgs ) , m_maxArgs ( maxArgs )
{ }
2012-08-23 21:08:50 +02:00
2012-08-27 22:42:55 +02:00
virtual ~ OptionParser ( ) { }
2012-08-23 21:08:50 +02:00
2012-08-27 22:42:55 +02:00
Command find ( const CommandParser & parser ) const {
Command cmd ;
for ( std : : vector < std : : string > : : const_iterator it = m_optionNames . begin ( ) ;
it ! = m_optionNames . end ( ) ;
+ + it )
cmd + = parser . find ( * it ) ;
return cmd ;
2012-08-23 21:08:50 +02:00
}
2012-05-16 16:09:17 +02:00
2012-08-27 22:42:55 +02:00
void validateArgs ( const Command & args ) const {
if ( tooFewArgs ( args ) | | tooManyArgs ( args ) ) {
std : : ostringstream oss ;
if ( m_maxArgs = = - 1 )
oss < < " Expected at least " < < pluralise ( static_cast < std : : size_t > ( m_minArgs ) , " argument " ) ;
else if ( m_minArgs = = m_maxArgs )
oss < < " Expected " < < pluralise ( static_cast < std : : size_t > ( m_minArgs ) , " argument " ) ;
2012-08-23 21:08:50 +02:00
else
2012-08-27 22:42:55 +02:00
oss < < " Expected between " < < m_minArgs < < " and " < < m_maxArgs < < " argument " ;
args . raiseError ( oss . str ( ) ) ;
2012-08-23 21:08:50 +02:00
}
}
2011-05-24 09:23:02 +02:00
2012-08-27 22:42:55 +02:00
void parseIntoConfig ( const CommandParser & parser , ConfigData & config ) {
if ( Command cmd = find ( parser ) ) {
validateArgs ( cmd ) ;
parseIntoConfig ( cmd , config ) ;
}
2012-08-23 21:08:50 +02:00
}
2012-08-27 22:42:55 +02:00
virtual void parseIntoConfig ( const Command & cmd , ConfigData & config ) = 0 ;
virtual std : : string argsSynopsis ( ) const = 0 ;
virtual std : : string optionSummary ( ) const = 0 ;
2013-02-02 21:37:58 +01:00
virtual std : : string optionDescription ( ) const { return " " ; }
2012-08-27 22:42:55 +02:00
std : : string optionNames ( ) const {
std : : string names ;
for ( std : : vector < std : : string > : : const_iterator it = m_optionNames . begin ( ) ;
it ! = m_optionNames . end ( ) ;
+ + it ) {
if ( ! it - > empty ( ) ) {
if ( ! names . empty ( ) )
names + = " , " ;
names + = * it ;
}
else {
names = " [ " + names ;
}
}
if ( names [ 0 ] = = ' [ ' )
names + = " ] " ;
return names ;
2012-08-23 21:08:50 +02:00
}
2012-08-27 22:42:55 +02:00
protected :
bool tooFewArgs ( const Command & args ) const {
return args . argsCount ( ) < static_cast < std : : size_t > ( m_minArgs ) ;
2012-08-23 21:08:50 +02:00
}
2012-08-27 22:42:55 +02:00
bool tooManyArgs ( const Command & args ) const {
return m_maxArgs > = 0 & & args . argsCount ( ) > static_cast < std : : size_t > ( m_maxArgs ) ;
}
std : : vector < std : : string > m_optionNames ;
int m_minArgs ;
int m_maxArgs ;
} ;
namespace Options {
class HelpOptionParser : public OptionParser {
public :
HelpOptionParser ( ) {
m_optionNames . push_back ( " -? " ) ;
m_optionNames . push_back ( " -h " ) ;
m_optionNames . push_back ( " --help " ) ;
}
virtual std : : string argsSynopsis ( ) const {
2012-09-26 19:38:26 +02:00
return " [<option for help on> ...] " ;
2012-08-27 22:42:55 +02:00
}
virtual std : : string optionSummary ( ) const {
2012-09-26 19:38:26 +02:00
return " Shows this usage summary, or help on a specific option, or options, if supplied " ;
2012-09-07 18:52:35 +02:00
}
virtual std : : string optionDescription ( ) const {
return " " ;
2012-08-27 22:42:55 +02:00
}
virtual void parseIntoConfig ( const Command & , ConfigData & ) {
// Does not affect config
}
} ;
class TestCaseOptionParser : public OptionParser {
public :
TestCaseOptionParser ( ) : OptionParser ( 1 , - 1 ) {
m_optionNames . push_back ( " -t " ) ;
m_optionNames . push_back ( " --test " ) ;
m_optionNames . push_back ( " " ) ; // default option
}
virtual std : : string argsSynopsis ( ) const {
return " <testspec> [<testspec>...] " ;
}
virtual std : : string optionSummary ( ) const {
2012-09-07 18:52:35 +02:00
return " Specifies which test case or cases to run " ;
}
// Lines are split at the nearest prior space char to the 80 char column.
// Tab chars are removed from the output but their positions are used to align
// subsequently wrapped lines
virtual std : : string optionDescription ( ) const {
2012-09-09 12:44:30 +02:00
return
" This option allows one ore more test specs to be supplied. Each spec either fully "
" specifies a test case or is a pattern containing wildcards to match a set of test "
" cases. If this option is not provided then all test cases, except those prefixed "
" by './' are run \n "
" \n "
" Specs must be enclosed in \" quotes \" if they contain spaces. If they do not "
" contain spaces the quotes are optional. \n "
" \n "
" Wildcards consist of the * character at the beginning, end, or both and can substitute for "
" any number of any characters (including none) \n "
" \n "
" If spec is prefixed with exclude: or the ~ character then the pattern matches an exclusion. "
" This means that tests matching the pattern are excluded from the set - even if a prior "
2012-09-24 09:30:13 +02:00
" inclusion spec included them. Subsequent inclusion specs will take precedence, however. "
2012-09-09 12:44:30 +02:00
" Inclusions and exclusions are evaluated in left-to-right order. \n "
" \n "
" Examples: \n "
" \n "
" -t thisTestOnly \t Matches the test case called, 'thisTestOnly' \n "
" -t \" this test only \" \t Matches the test case called, 'this test only' \n "
" -t these/* \t Matches all cases starting with 'these/' \n "
" -t exclude:notThis \t Matches all tests except, 'notThis' \n "
" -t ~notThis \t Matches all tests except, 'notThis' \n "
" -t ~*private* \t Matches all tests except those that contain 'private' \n "
" -t a/* ~a/b/* a/b/c \t Matches all tests that start with 'a/', except those "
" that start with 'a/b/', except 'a/b/c', which is included " ;
2012-08-27 22:42:55 +02:00
}
virtual void parseIntoConfig ( const Command & cmd , ConfigData & config ) {
std : : string groupName ;
for ( std : : size_t i = 0 ; i < cmd . argsCount ( ) ; + + i ) {
if ( i ! = 0 )
groupName + = " " ;
groupName + = cmd [ i ] ;
}
TestCaseFilters filters ( groupName ) ;
2012-09-07 18:52:35 +02:00
for ( std : : size_t i = 0 ; i < cmd . argsCount ( ) ; + + i )
filters . addFilter ( TestCaseFilter ( cmd [ i ] ) ) ;
2012-08-27 22:42:55 +02:00
config . filters . push_back ( filters ) ;
}
} ;
2012-08-23 21:08:50 +02:00
2012-09-24 09:30:13 +02:00
class TagOptionParser : public OptionParser {
public :
TagOptionParser ( ) : OptionParser ( 1 , - 1 ) {
m_optionNames . push_back ( " -g " ) ;
m_optionNames . push_back ( " --tag " ) ;
}
virtual std : : string argsSynopsis ( ) const {
return " <tagspec> [,<tagspec>...] " ;
}
virtual std : : string optionSummary ( ) const {
return " Matches test cases against tags or tag patterns " ;
}
// Lines are split at the nearest prior space char to the 80 char column.
// Tab chars are removed from the output but their positions are used to align
// subsequently wrapped lines
virtual std : : string optionDescription ( ) const {
return
2012-11-06 20:34:35 +01:00
" This option allows one or more tags or tag patterns to be specified. \n "
" Each tag is enclosed in square brackets. A series of tags form an AND expression "
" wheras a comma seperated sequence forms an OR expression. e.g.: \n \n "
" -g [one][two],[three] \n \n "
" This matches all tests tagged [one] and [two], as well as all tests tagged [three]. \n \n "
" Tags can be negated with the ~ character. This removes matching tests from the set. e.g.: \n \n "
" -g [one]~[two] \n \n "
" matches all tests tagged [one], except those also tagged [two] " ;
2012-09-24 09:30:13 +02:00
}
virtual void parseIntoConfig ( const Command & cmd , ConfigData & config ) {
2012-09-26 19:38:26 +02:00
std : : string groupName ;
for ( std : : size_t i = 0 ; i < cmd . argsCount ( ) ; + + i ) {
if ( i ! = 0 )
groupName + = " " ;
groupName + = cmd [ i ] ;
}
TestCaseFilters filters ( groupName ) ;
for ( std : : size_t i = 0 ; i < cmd . argsCount ( ) ; + + i )
filters . addTags ( cmd [ i ] ) ;
config . filters . push_back ( filters ) ;
2012-09-24 09:30:13 +02:00
}
} ;
2012-08-27 22:42:55 +02:00
class ListOptionParser : public OptionParser {
public :
ListOptionParser ( ) : OptionParser ( 0 , 2 ) {
m_optionNames . push_back ( " -l " ) ;
m_optionNames . push_back ( " --list " ) ;
}
virtual std : : string argsSynopsis ( ) const {
return " [all | tests | reporters [xml]] " ;
}
virtual std : : string optionSummary ( ) const {
2012-09-07 18:52:35 +02:00
return " Lists available tests or reporters " ;
}
virtual std : : string optionDescription ( ) const {
2012-09-09 12:44:30 +02:00
return
" With no arguments this option will list all registered tests - one per line. \n "
" Supplying the xml argument formats the list as an xml document (which may be useful for "
" consumption by other tools). \n "
" Supplying the tests or reporters lists tests or reporters respectively - with descriptions. \n "
" \n "
" Examples: \n "
" \n "
" -l \n "
" -l tests \n "
" -l reporters xml \n "
" -l xml " ;
2012-08-27 22:42:55 +02:00
}
virtual void parseIntoConfig ( const Command & cmd , ConfigData & config ) {
config . listSpec = List : : TestNames ;
if ( cmd . argsCount ( ) > = 1 ) {
if ( cmd [ 0 ] = = " all " )
config . listSpec = List : : All ;
else if ( cmd [ 0 ] = = " tests " )
config . listSpec = List : : Tests ;
else if ( cmd [ 0 ] = = " reporters " )
config . listSpec = List : : Reports ;
else
cmd . raiseError ( " Expected [tests] or [reporters] " ) ;
}
if ( cmd . argsCount ( ) > = 2 ) {
if ( cmd [ 1 ] = = " xml " )
config . listSpec = static_cast < List : : What > ( config . listSpec | List : : AsXml ) ;
else if ( cmd [ 1 ] = = " text " )
config . listSpec = static_cast < List : : What > ( config . listSpec | List : : AsText ) ;
else
cmd . raiseError ( " Expected [xml] or [text] " ) ;
}
}
} ;
class ReporterOptionParser : public OptionParser {
public :
ReporterOptionParser ( ) : OptionParser ( 1 , 1 ) {
m_optionNames . push_back ( " -r " ) ;
m_optionNames . push_back ( " --reporter " ) ;
}
virtual std : : string argsSynopsis ( ) const {
return " <reporter name> " ;
}
virtual std : : string optionSummary ( ) const {
2012-09-07 18:52:35 +02:00
return " Specifies type of reporter " ;
}
virtual std : : string optionDescription ( ) const {
2012-09-09 12:44:30 +02:00
return
" A reporter is an object that formats and structures the output of running "
2013-01-16 10:44:43 +01:00
" tests, and potentially summarises the results. By default the console reporter "
" is used which writes IDE friendly results. CATCH comes bundled with some "
2012-09-09 12:44:30 +02:00
" alternative reporters, but more can be added in client code. \n "
" \n "
" The bundled reporters are: \n "
2013-01-16 10:44:43 +01:00
" -r console \n "
2012-09-09 12:44:30 +02:00
" -r xml \n "
" -r junit \n "
" \n "
" The JUnit reporter is an xml format that follows the structure of the JUnit "
" XML Report ANT task, as consumed by a number of third-party tools, "
" including Continuous Integration servers such as Jenkins. \n "
" If not otherwise needed, the standard XML reporter is preferred as this is "
" a streaming reporter, whereas the Junit reporter needs to hold all its "
" results until the end so it can write the overall results into attributes "
" of the root node. " ;
2012-08-27 22:42:55 +02:00
}
virtual void parseIntoConfig ( const Command & cmd , ConfigData & config ) {
config . reporter = cmd [ 0 ] ;
}
} ;
class OutputOptionParser : public OptionParser {
public :
OutputOptionParser ( ) : OptionParser ( 1 , 1 ) {
m_optionNames . push_back ( " -o " ) ;
m_optionNames . push_back ( " --out " ) ;
}
virtual std : : string argsSynopsis ( ) const {
return " <file name>|<%stream name> " ;
}
virtual std : : string optionSummary ( ) const {
2012-09-07 18:52:35 +02:00
return " Sends output to a file or stream " ;
2012-08-27 22:42:55 +02:00
}
2012-09-09 12:44:30 +02:00
virtual std : : string optionDescription ( ) const {
return
" Use this option to send all output to a file or a stream. By default output is "
2012-09-24 09:30:13 +02:00
" sent to stdout (note that uses of stdout and stderr from within test cases are "
2012-09-09 12:44:30 +02:00
" redirected and included in the report - so even stderr will effectively end up "
2012-09-24 09:30:13 +02:00
" on stdout). If the name begins with % it is interpreted as a stream. "
2012-09-09 12:44:30 +02:00
" Otherwise it is treated as a filename. \n "
" \n "
" Examples are: \n "
" \n "
" -o filename.txt \n "
" -o \" long filename.txt \" \n "
" -o %stdout \n "
" -o %stderr \n "
" -o %debug \t (The IDE's debug output window - currently only Windows' "
" OutputDebugString is supported). " ;
}
2012-08-27 22:42:55 +02:00
virtual void parseIntoConfig ( const Command & cmd , ConfigData & config ) {
if ( cmd [ 0 ] [ 0 ] = = ' % ' )
config . stream = cmd [ 0 ] . substr ( 1 ) ;
else
config . outputFilename = cmd [ 0 ] ;
}
} ;
2012-09-09 12:44:30 +02:00
class SuccessOptionParser : public OptionParser {
2012-08-27 22:42:55 +02:00
public :
2012-09-09 12:44:30 +02:00
SuccessOptionParser ( ) {
2012-08-27 22:42:55 +02:00
m_optionNames . push_back ( " -s " ) ;
m_optionNames . push_back ( " --success " ) ;
}
virtual std : : string argsSynopsis ( ) const {
return " " ;
}
virtual std : : string optionSummary ( ) const {
2012-09-07 18:52:35 +02:00
return " Shows results for successful tests " ;
2012-08-27 22:42:55 +02:00
}
2012-09-09 12:44:30 +02:00
virtual std : : string optionDescription ( ) const {
return
" Usually you only want to see reporting for failed tests. Sometimes it's useful "
" to see all the output (especially when you don't trust that that test you just "
2012-09-24 09:30:13 +02:00
" added worked first time!). To see successful, as well as failing, test results "
2012-09-09 12:44:30 +02:00
" just pass this option. " ;
}
2012-08-27 22:48:15 +02:00
virtual void parseIntoConfig ( const Command & , ConfigData & config ) {
2012-08-27 22:42:55 +02:00
config . includeWhichResults = Include : : SuccessfulResults ;
}
} ;
class DebugBreakOptionParser : public OptionParser {
public :
DebugBreakOptionParser ( ) {
m_optionNames . push_back ( " -b " ) ;
m_optionNames . push_back ( " --break " ) ;
}
virtual std : : string argsSynopsis ( ) const {
return " " ;
}
virtual std : : string optionSummary ( ) const {
2012-09-07 18:52:35 +02:00
return " Breaks into the debugger on failure " ;
2012-08-27 22:42:55 +02:00
}
2012-09-09 12:44:30 +02:00
virtual std : : string optionDescription ( ) const {
return
" In some IDEs (currently XCode and Visual Studio) it is possible for CATCH to "
" break into the debugger on a test failure. This can be very helpful during "
" debug sessions - especially when there is more than one path through a "
" particular test. In addition to the command line option, ensure you have "
" built your code with the DEBUG preprocessor symbol " ;
}
2012-08-27 22:42:55 +02:00
2012-08-27 22:48:15 +02:00
virtual void parseIntoConfig ( const Command & , ConfigData & config ) {
2012-08-27 22:42:55 +02:00
config . shouldDebugBreak = true ;
}
} ;
class NameOptionParser : public OptionParser {
public :
NameOptionParser ( ) : OptionParser ( 1 , 1 ) {
m_optionNames . push_back ( " -n " ) ;
m_optionNames . push_back ( " --name " ) ;
}
virtual std : : string argsSynopsis ( ) const {
return " <name> " ;
}
virtual std : : string optionSummary ( ) const {
2012-09-07 18:52:35 +02:00
return " Names a test run " ;
2012-08-27 22:42:55 +02:00
}
2012-09-09 12:44:30 +02:00
virtual std : : string optionDescription ( ) const {
return
" If a name is supplied it will be used by the reporter to provide an overall "
" name for the test run. This can be useful if you are sending to a file, for "
" example, and need to distinguish different test runs - either from different "
" Catch executables or runs of the same executable with different options. \n "
" \n "
" Examples: \n "
" \n "
" -n testRun \n "
" -n \" tests of the widget component \" " ;
}
2012-08-27 22:42:55 +02:00
virtual void parseIntoConfig ( const Command & cmd , ConfigData & config ) {
config . name = cmd [ 0 ] ;
}
} ;
class AbortOptionParser : public OptionParser {
public :
AbortOptionParser ( ) : OptionParser ( 0 , 1 ) {
m_optionNames . push_back ( " -a " ) ;
m_optionNames . push_back ( " --abort " ) ;
}
virtual std : : string argsSynopsis ( ) const {
return " [#] " ;
}
virtual std : : string optionSummary ( ) const {
2012-09-07 18:52:35 +02:00
return " Aborts after a certain number of failures " ;
2012-08-27 22:42:55 +02:00
}
2012-09-09 12:44:30 +02:00
virtual std : : string optionDescription ( ) const {
return
" If a REQUIRE assertion fails the test case aborts, but subsequent test cases "
" are still run. If a CHECK assertion fails even the current test case is not "
" aborted. \n "
" \n "
" Sometimes this results in a flood of failure messages and you'd rather just "
" see the first few. Specifying -a or --abort on its own will abort the whole "
" test run on the first failed assertion of any kind. Following it with a "
" number causes it to abort after that number of assertion failures. " ;
}
2012-08-27 22:42:55 +02:00
virtual void parseIntoConfig ( const Command & cmd , ConfigData & config ) {
int threshold = 1 ;
if ( cmd . argsCount ( ) = = 1 ) {
std : : stringstream ss ;
ss < < cmd [ 0 ] ;
ss > > threshold ;
if ( ss . fail ( ) | | threshold < = 0 )
cmd . raiseError ( " threshold must be a number greater than zero " ) ;
}
config . cutoff = threshold ;
}
} ;
class NoThrowOptionParser : public OptionParser {
public :
NoThrowOptionParser ( ) {
m_optionNames . push_back ( " -nt " ) ;
m_optionNames . push_back ( " --nothrow " ) ;
}
virtual std : : string argsSynopsis ( ) const {
return " " ;
}
virtual std : : string optionSummary ( ) const {
2012-09-07 18:52:35 +02:00
return " Elides assertions expected to throw " ;
2012-08-27 22:42:55 +02:00
}
2012-09-09 12:44:30 +02:00
virtual std : : string optionDescription ( ) const {
return
" Skips all assertions that test that an exception is thrown, "
" e.g. REQUIRE_THROWS. \n "
" \n "
" These can be a nuisance in certain debugging environments that may break when "
" exceptions are thrown (while this is usually optional for handled exceptions, "
" it can be useful to have enabled if you are trying to track down something "
" unexpected). \n "
" \n "
" When running with this option the throw checking assertions are skipped so "
" as not to contribute additional noise. " ;
}
2012-08-27 22:42:55 +02:00
2012-08-27 22:48:15 +02:00
virtual void parseIntoConfig ( const Command & , ConfigData & config ) {
2012-08-27 22:42:55 +02:00
config . allowThrows = false ;
}
} ;
2012-08-31 09:10:36 +02:00
class WarningsOptionParser : public OptionParser {
public :
WarningsOptionParser ( ) : OptionParser ( 1 , - 1 ) {
m_optionNames . push_back ( " -w " ) ;
m_optionNames . push_back ( " --warnings " ) ;
}
virtual std : : string argsSynopsis ( ) const {
return " <warning> " ;
}
virtual std : : string optionSummary ( ) const {
2012-09-07 18:52:35 +02:00
return " Enable warnings " ;
2012-08-31 09:10:36 +02:00
}
2012-09-09 12:44:30 +02:00
virtual std : : string optionDescription ( ) const {
return
" Enables the named warnings. If the warnings are violated the test case is "
" failed. \n "
" \n "
" At present only one warning has been provided: NoAssertions. If this warning "
" is enabled then any test case that completes without an assertions (CHECK, "
" REQUIRE etc) being encountered violates the warning. \n "
" \n "
" e.g.: \n "
" \n "
" -w NoAssertions " ;
}
2012-08-31 09:10:36 +02:00
virtual void parseIntoConfig ( const Command & cmd , ConfigData & config ) {
for ( std : : size_t i = 0 ; i < cmd . argsCount ( ) ; + + i ) {
if ( cmd [ i ] = = " NoAssertions " )
config . warnings = ( ConfigData : : WarnAbout : : What ) ( config . warnings | ConfigData : : WarnAbout : : NoAssertions ) ;
else
cmd . raiseError ( " Unrecognised warning: " + cmd [ i ] ) ;
}
}
} ;
2012-08-27 22:42:55 +02:00
}
class AllOptions
{
public :
typedef std : : vector < Ptr < OptionParser > > Parsers ;
typedef Parsers : : const_iterator const_iterator ;
typedef Parsers : : const_iterator iterator ;
AllOptions ( ) {
2012-08-31 09:10:36 +02:00
add < Options : : TestCaseOptionParser > ( ) ; // Keep this one first
2012-09-26 19:38:26 +02:00
add < Options : : TagOptionParser > ( ) ;
2012-08-27 22:42:55 +02:00
add < Options : : ListOptionParser > ( ) ;
add < Options : : ReporterOptionParser > ( ) ;
add < Options : : OutputOptionParser > ( ) ;
2012-09-09 12:44:30 +02:00
add < Options : : SuccessOptionParser > ( ) ;
2012-08-27 22:42:55 +02:00
add < Options : : DebugBreakOptionParser > ( ) ;
add < Options : : NameOptionParser > ( ) ;
add < Options : : AbortOptionParser > ( ) ;
add < Options : : NoThrowOptionParser > ( ) ;
2012-08-31 09:10:36 +02:00
add < Options : : WarningsOptionParser > ( ) ;
add < Options : : HelpOptionParser > ( ) ; // Keep this one last
2012-08-23 21:08:50 +02:00
}
2012-08-27 22:42:55 +02:00
void parseIntoConfig ( const CommandParser & parser , ConfigData & config ) {
2012-11-19 20:59:10 +01:00
config . name = parser . exeName ( ) ;
if ( endsWith ( config . name , " .exe " ) )
config . name = config . name . substr ( 0 , config . name . size ( ) - 4 ) ;
2012-08-27 22:42:55 +02:00
for ( const_iterator it = m_parsers . begin ( ) ; it ! = m_parsers . end ( ) ; + + it )
( * it ) - > parseIntoConfig ( parser , config ) ;
2012-08-23 21:08:50 +02:00
}
2012-08-27 22:42:55 +02:00
const_iterator begin ( ) const {
return m_parsers . begin ( ) ;
2012-08-23 21:08:50 +02:00
}
2012-08-27 22:42:55 +02:00
const_iterator end ( ) const {
return m_parsers . end ( ) ;
}
private :
2011-05-24 09:23:02 +02:00
2012-08-27 22:42:55 +02:00
template < typename T >
void add ( ) {
m_parsers . push_back ( new T ( ) ) ;
2012-08-23 21:08:50 +02:00
}
2012-08-27 22:42:55 +02:00
Parsers m_parsers ;
2012-08-23 21:08:50 +02:00
2012-08-27 22:42:55 +02:00
} ;
2012-08-23 21:08:50 +02:00
} // end namespace Catch
// #included from: internal/catch_list.hpp
# define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED
# include <limits>
namespace Catch {
2012-12-02 00:57:18 +01:00
inline bool matchesFilters ( const std : : vector < TestCaseFilters > & filters , const TestCase & testCase ) {
2012-08-23 21:08:50 +02:00
std : : vector < TestCaseFilters > : : const_iterator it = filters . begin ( ) ;
std : : vector < TestCaseFilters > : : const_iterator itEnd = filters . end ( ) ;
for ( ; it ! = itEnd ; + + it )
if ( ! it - > shouldInclude ( testCase ) )
return false ;
return true ;
}
inline void List ( const ConfigData & config ) {
if ( config . listSpec & List : : Reports ) {
std : : cout < < " Available reports: \n " ;
IReporterRegistry : : FactoryMap : : const_iterator it = getRegistryHub ( ) . getReporterRegistry ( ) . getFactories ( ) . begin ( ) ;
IReporterRegistry : : FactoryMap : : const_iterator itEnd = getRegistryHub ( ) . getReporterRegistry ( ) . getFactories ( ) . end ( ) ;
for ( ; it ! = itEnd ; + + it ) {
// !TBD: consider listAs()
std : : cout < < " \t " < < it - > first < < " \n \t \t ' " < < it - > second - > getDescription ( ) < < " ' \n " ;
2012-08-13 08:46:10 +02:00
}
2012-08-23 21:08:50 +02:00
std : : cout < < std : : endl ;
2011-05-24 09:23:02 +02:00
}
2012-08-23 21:08:50 +02:00
if ( config . listSpec & List : : Tests ) {
if ( config . filters . empty ( ) )
2012-08-24 09:23:50 +02:00
std : : cout < < " All available test cases: \n " ;
2012-08-23 21:08:50 +02:00
else
2012-08-24 09:23:50 +02:00
std : : cout < < " Matching test cases: \n " ;
2012-12-02 00:57:18 +01:00
std : : vector < TestCase > : : const_iterator it = getRegistryHub ( ) . getTestCaseRegistry ( ) . getAllTests ( ) . begin ( ) ;
std : : vector < TestCase > : : const_iterator itEnd = getRegistryHub ( ) . getTestCaseRegistry ( ) . getAllTests ( ) . end ( ) ;
2012-08-24 09:23:50 +02:00
std : : size_t matchedTests = 0 ;
2012-08-23 21:08:50 +02:00
for ( ; it ! = itEnd ; + + it ) {
if ( matchesFilters ( config . filters , * it ) ) {
2012-08-24 09:23:50 +02:00
matchedTests + + ;
2012-08-23 21:08:50 +02:00
// !TBD: consider listAs()
2012-12-02 00:57:18 +01:00
std : : cout < < " \t " < < it - > getTestCaseInfo ( ) . name < < " \n " ;
2012-08-23 21:08:50 +02:00
if ( ( config . listSpec & List : : TestNames ) ! = List : : TestNames )
2012-12-02 00:57:18 +01:00
std : : cout < < " \t \t ' " < < it - > getTestCaseInfo ( ) . description < < " ' \n " ;
2012-08-23 21:08:50 +02:00
}
2011-05-24 09:23:02 +02:00
}
2012-08-24 09:23:50 +02:00
if ( config . filters . empty ( ) )
std : : cout < < pluralise ( matchedTests , " test case " ) < < std : : endl ;
else
std : : cout < < pluralise ( matchedTests , " matching test case " ) < < std : : endl ;
2011-05-24 09:23:02 +02:00
}
2012-08-23 21:08:50 +02:00
if ( ( config . listSpec & List : : All ) = = 0 ) {
std : : ostringstream oss ;
oss < < " Unknown list type " ;
throw std : : domain_error ( oss . str ( ) ) ;
}
}
2012-05-16 16:09:17 +02:00
2012-08-13 08:46:10 +02:00
} // end namespace Catch
2012-05-16 16:09:17 +02:00
2012-08-23 21:08:50 +02:00
// #included from: internal/catch_runner_impl.hpp
2012-09-17 07:42:29 +02:00
# define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
// #included from: catch_running_test.hpp
2012-09-17 07:42:29 +02:00
# define TWOBLUECUBES_CATCH_RUNNING_TEST_HPP_INCLUDED
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
// #included from: catch_section_info.hpp
2012-09-17 07:42:29 +02:00
# define TWOBLUECUBES_CATCH_SECTION_INFO_HPP_INCLUDED
2012-08-23 21:08:50 +02:00
# include <map>
2012-08-13 08:46:10 +02:00
# include <string>
2011-05-24 09:23:02 +02:00
2012-08-13 08:46:10 +02:00
namespace Catch {
2011-05-24 09:23:02 +02:00
2012-12-02 00:57:18 +01:00
class RunningSection {
2012-08-13 08:46:10 +02:00
public :
2011-05-24 09:23:02 +02:00
2012-12-02 00:57:18 +01:00
typedef std : : vector < RunningSection * > SubSections ;
enum State {
2012-08-23 21:08:50 +02:00
Root ,
Unknown ,
Branch ,
TestedBranch ,
TestedLeaf
2012-08-13 08:46:10 +02:00
} ;
2012-12-02 00:57:18 +01:00
RunningSection ( RunningSection * parent , const std : : string & name )
: m_state ( Unknown ) ,
m_parent ( parent ) ,
m_name ( name )
2012-08-13 08:46:10 +02:00
{ }
2012-12-02 00:57:18 +01:00
RunningSection ( const std : : string & name )
: m_state ( Root ) ,
m_parent ( NULL ) ,
m_name ( name )
2012-08-13 08:46:10 +02:00
{ }
2012-12-02 00:57:18 +01:00
~ RunningSection ( ) {
deleteAll ( m_subSections ) ;
2011-05-24 09:23:02 +02:00
}
2012-12-02 00:57:18 +01:00
std : : string getName ( ) const {
return m_name ;
2011-05-24 09:23:02 +02:00
}
2012-12-02 00:57:18 +01:00
bool shouldRun ( ) const {
return m_state < TestedBranch ;
2011-05-24 09:23:02 +02:00
}
2012-08-31 09:10:36 +02:00
bool isBranch ( ) const {
2012-12-02 00:57:18 +01:00
return m_state = = Branch ;
2012-08-31 09:10:36 +02:00
}
2012-12-02 00:57:18 +01:00
const RunningSection * getParent ( ) const {
return m_parent ;
2012-08-13 08:46:10 +02:00
}
2012-05-05 20:35:35 +02:00
2012-12-02 00:57:18 +01:00
bool hasUntestedSections ( ) const {
if ( m_state = = Unknown )
return true ;
for ( SubSections : : const_iterator it = m_subSections . begin ( ) ;
it ! = m_subSections . end ( ) ;
+ + it )
if ( ( * it ) - > hasUntestedSections ( ) )
return true ;
return false ;
2012-08-13 08:46:10 +02:00
}
2012-05-05 20:35:35 +02:00
2012-12-02 00:57:18 +01:00
// Mutable methods:
2012-05-16 16:09:17 +02:00
2012-12-02 00:57:18 +01:00
RunningSection * getParent ( ) {
2012-08-23 21:08:50 +02:00
return m_parent ;
2012-08-13 08:46:10 +02:00
}
2012-05-16 16:09:17 +02:00
2012-12-02 00:57:18 +01:00
RunningSection * findOrAddSubSection ( const std : : string & name , bool & changed ) {
for ( SubSections : : const_iterator it = m_subSections . begin ( ) ;
it ! = m_subSections . end ( ) ;
+ + it )
if ( ( * it ) - > getName ( ) = = name )
return * it ;
RunningSection * subSection = new RunningSection ( this , name ) ;
m_subSections . push_back ( subSection ) ;
m_state = Branch ;
changed = true ;
return subSection ;
}
2012-05-05 20:35:35 +02:00
2012-12-02 00:57:18 +01:00
bool ran ( ) {
if ( m_state > = Branch )
return false ;
m_state = TestedLeaf ;
return true ;
}
void ranToCompletion ( ) {
if ( m_state = = Branch & & ! hasUntestedSections ( ) )
m_state = TestedBranch ;
2012-05-05 20:35:35 +02:00
}
2012-08-23 21:08:50 +02:00
private :
2012-12-02 00:57:18 +01:00
State m_state ;
RunningSection * m_parent ;
std : : string m_name ;
SubSections m_subSections ;
2012-08-23 21:08:50 +02:00
} ;
}
namespace Catch {
class RunningTest {
enum RunStatus {
NothingRun ,
EncounteredASection ,
RanAtLeastOneSection ,
RanToCompletionWithSections ,
RanToCompletionWithNoSections
} ;
public :
2012-12-02 00:57:18 +01:00
explicit RunningTest ( const TestCase & info )
2012-08-23 21:08:50 +02:00
: m_info ( info ) ,
m_runStatus ( RanAtLeastOneSection ) ,
2012-12-02 00:57:18 +01:00
m_rootSection ( info . getTestCaseInfo ( ) . name ) ,
2012-08-23 21:08:50 +02:00
m_currentSection ( & m_rootSection ) ,
m_changed ( false )
{ }
bool wasSectionSeen ( ) const {
return m_runStatus = = RanAtLeastOneSection | |
m_runStatus = = RanToCompletionWithSections ;
2012-08-13 08:46:10 +02:00
}
2012-05-16 16:09:17 +02:00
2012-08-31 09:10:36 +02:00
bool isBranchSection ( ) const {
return m_currentSection & &
m_currentSection - > isBranch ( ) ;
}
bool hasSections ( ) const {
return m_runStatus = = RanAtLeastOneSection | |
m_runStatus = = RanToCompletionWithSections | |
m_runStatus = = EncounteredASection ;
}
2012-08-23 21:08:50 +02:00
void reset ( ) {
m_runStatus = NothingRun ;
m_changed = false ;
m_lastSectionToRun = NULL ;
2012-08-13 08:46:10 +02:00
}
2012-05-16 16:09:17 +02:00
2012-08-23 21:08:50 +02:00
void ranToCompletion ( ) {
2012-12-02 00:57:18 +01:00
if ( m_runStatus ! = RanAtLeastOneSection & & m_runStatus ! = EncounteredASection )
2012-08-23 21:08:50 +02:00
m_runStatus = RanToCompletionWithNoSections ;
2012-12-02 00:57:18 +01:00
m_runStatus = RanToCompletionWithSections ;
if ( m_lastSectionToRun ) {
m_lastSectionToRun - > ranToCompletion ( ) ;
m_changed = true ;
2012-08-23 21:08:50 +02:00
}
2012-08-13 08:46:10 +02:00
}
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
bool addSection ( const std : : string & name ) {
if ( m_runStatus = = NothingRun )
m_runStatus = EncounteredASection ;
2011-05-24 09:23:02 +02:00
2012-12-02 00:57:18 +01:00
RunningSection * thisSection = m_currentSection - > findOrAddSubSection ( name , m_changed ) ;
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
if ( ! wasSectionSeen ( ) & & thisSection - > shouldRun ( ) ) {
m_currentSection = thisSection ;
m_lastSectionToRun = NULL ;
return true ;
2012-08-13 08:46:10 +02:00
}
2012-08-23 21:08:50 +02:00
return false ;
2011-05-24 09:23:02 +02:00
}
2013-03-04 12:19:15 +01:00
void endSection ( const std : : string & , bool stealth ) {
2012-08-23 21:08:50 +02:00
if ( m_currentSection - > ran ( ) ) {
2013-03-04 12:19:15 +01:00
if ( ! stealth )
m_runStatus = RanAtLeastOneSection ;
2012-08-23 21:08:50 +02:00
m_changed = true ;
}
else if ( m_runStatus = = EncounteredASection ) {
2013-03-04 12:19:15 +01:00
if ( ! stealth )
m_runStatus = RanAtLeastOneSection ;
2012-08-23 21:08:50 +02:00
m_lastSectionToRun = m_currentSection ;
2011-05-24 09:23:02 +02:00
}
2012-08-23 21:08:50 +02:00
m_currentSection = m_currentSection - > getParent ( ) ;
2011-05-24 09:23:02 +02:00
}
2012-12-02 00:57:18 +01:00
const TestCase & getTestCase ( ) const {
return m_info ;
2012-08-23 21:08:50 +02:00
}
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
bool hasUntestedSections ( ) const {
return m_runStatus = = RanAtLeastOneSection | |
( m_rootSection . hasUntestedSections ( ) & & m_changed ) ;
2011-05-24 09:23:02 +02:00
}
2012-08-23 21:08:50 +02:00
private :
2012-12-02 00:57:18 +01:00
const TestCase & m_info ;
2012-08-23 21:08:50 +02:00
RunStatus m_runStatus ;
2012-12-02 00:57:18 +01:00
RunningSection m_rootSection ;
RunningSection * m_currentSection ;
RunningSection * m_lastSectionToRun ;
2012-08-23 21:08:50 +02:00
bool m_changed ;
2012-08-13 08:46:10 +02:00
} ;
}
2012-08-23 21:08:50 +02:00
# include <set>
# include <string>
2012-08-13 08:46:10 +02:00
namespace Catch {
2012-08-23 21:08:50 +02:00
class StreamRedirect {
2012-08-13 08:46:10 +02:00
public :
2012-08-23 21:08:50 +02:00
StreamRedirect ( std : : ostream & stream , std : : string & targetString )
: m_stream ( stream ) ,
m_prevBuf ( stream . rdbuf ( ) ) ,
m_targetString ( targetString )
{
stream . rdbuf ( m_oss . rdbuf ( ) ) ;
}
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
~ StreamRedirect ( ) {
m_targetString + = m_oss . str ( ) ;
m_stream . rdbuf ( m_prevBuf ) ;
2012-08-13 08:46:10 +02:00
}
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
private :
std : : ostream & m_stream ;
std : : streambuf * m_prevBuf ;
std : : ostringstream m_oss ;
std : : string & m_targetString ;
} ;
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
///////////////////////////////////////////////////////////////////////////
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
class Runner : public IResultCapture , public IRunner {
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
Runner ( const Runner & ) ;
void operator = ( const Runner & ) ;
2012-06-05 21:51:05 +02:00
2012-08-23 21:08:50 +02:00
public :
2011-05-24 09:23:02 +02:00
2012-12-02 00:57:18 +01:00
explicit Runner ( const Config & config , const Ptr < IStreamingReporter > & reporter )
: m_runInfo ( config . data ( ) . name ) ,
m_context ( getCurrentMutableContext ( ) ) ,
2012-08-23 21:08:50 +02:00
m_runningTest ( NULL ) ,
m_config ( config ) ,
m_reporter ( reporter ) ,
m_prevRunner ( & m_context . getRunner ( ) ) ,
m_prevResultCapture ( & m_context . getResultCapture ( ) ) ,
m_prevConfig ( m_context . getConfig ( ) )
{
m_context . setRunner ( this ) ;
m_context . setConfig ( & m_config ) ;
m_context . setResultCapture ( this ) ;
2012-12-02 00:57:18 +01:00
m_reporter - > testRunStarting ( m_runInfo ) ;
2011-05-24 09:23:02 +02:00
}
2012-08-23 21:08:50 +02:00
virtual ~ Runner ( ) {
2013-01-16 10:44:43 +01:00
m_reporter - > testRunEnded ( TestRunStats ( m_runInfo , m_totals , aborting ( ) ) ) ;
2012-08-23 21:08:50 +02:00
m_context . setRunner ( m_prevRunner ) ;
m_context . setConfig ( NULL ) ;
m_context . setResultCapture ( m_prevResultCapture ) ;
m_context . setConfig ( m_prevConfig ) ;
2011-05-24 09:23:02 +02:00
}
2013-01-16 10:44:43 +01:00
void testGroupStarting ( std : : string const & testSpec , std : : size_t groupIndex , std : : size_t groupsCount ) {
m_reporter - > testGroupStarting ( GroupInfo ( testSpec , groupIndex , groupsCount ) ) ;
2012-12-02 00:57:18 +01:00
}
2013-01-16 10:44:43 +01:00
void testGroupEnded ( std : : string const & testSpec , Totals const & totals , std : : size_t groupIndex , std : : size_t groupsCount ) {
m_reporter - > testGroupEnded ( TestGroupStats ( GroupInfo ( testSpec , groupIndex , groupsCount ) , totals , aborting ( ) ) ) ;
2012-12-02 00:57:18 +01:00
}
2013-01-16 10:44:43 +01:00
Totals runMatching ( const std : : string & testSpec , std : : size_t groupIndex , std : : size_t groupsCount ) {
2011-05-24 09:23:02 +02:00
2012-12-02 00:57:18 +01:00
std : : vector < TestCase > matchingTests = getRegistryHub ( ) . getTestCaseRegistry ( ) . getMatchingTestCases ( testSpec ) ;
2012-08-23 21:08:50 +02:00
Totals totals ;
2013-01-16 10:44:43 +01:00
testGroupStarting ( testSpec , groupIndex , groupsCount ) ;
2012-08-23 21:08:50 +02:00
2012-12-02 00:57:18 +01:00
std : : vector < TestCase > : : const_iterator it = matchingTests . begin ( ) ;
std : : vector < TestCase > : : const_iterator itEnd = matchingTests . end ( ) ;
2012-08-23 21:08:50 +02:00
for ( ; it ! = itEnd ; + + it )
totals + = runTest ( * it ) ;
2013-01-16 10:44:43 +01:00
testGroupEnded ( testSpec , totals , groupIndex , groupsCount ) ;
2012-08-23 21:08:50 +02:00
return totals ;
2011-05-24 09:23:02 +02:00
}
2012-12-02 00:57:18 +01:00
Totals runTest ( const TestCase & testCase ) {
2012-08-23 21:08:50 +02:00
Totals prevTotals = m_totals ;
2012-08-13 08:46:10 +02:00
2012-08-23 21:08:50 +02:00
std : : string redirectedCout ;
std : : string redirectedCerr ;
2012-08-13 08:46:10 +02:00
2012-12-02 00:57:18 +01:00
TestCaseInfo testInfo = testCase . getTestCaseInfo ( ) ;
m_reporter - > testCaseStarting ( testInfo ) ;
2011-05-24 09:23:02 +02:00
2012-12-02 00:57:18 +01:00
m_runningTest = new RunningTest ( testCase ) ;
2012-08-23 21:08:50 +02:00
do {
do {
runCurrentTest ( redirectedCout , redirectedCerr ) ;
}
while ( m_runningTest - > hasUntestedSections ( ) & & ! aborting ( ) ) ;
2011-05-24 09:23:02 +02:00
}
2012-08-23 21:08:50 +02:00
while ( getCurrentContext ( ) . advanceGeneratorsForCurrentTest ( ) & & ! aborting ( ) ) ;
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
Totals deltaTotals = m_totals . delta ( prevTotals ) ;
2012-12-02 00:57:18 +01:00
bool missingAssertions = false ;
2012-11-21 19:06:13 +01:00
if ( deltaTotals . assertions . total ( ) = = 0 & &
( m_config . data ( ) . warnings & ConfigData : : WarnAbout : : NoAssertions ) ) {
m_totals . assertions . failed + + ;
deltaTotals = m_totals . delta ( prevTotals ) ;
2012-12-02 00:57:18 +01:00
missingAssertions = true ;
2012-11-21 19:06:13 +01:00
}
2012-12-02 00:57:18 +01:00
2012-08-23 21:08:50 +02:00
m_totals . testCases + = deltaTotals . testCases ;
2012-11-21 19:06:13 +01:00
2013-01-16 10:44:43 +01:00
m_reporter - > testCaseEnded ( TestCaseStats ( testInfo ,
deltaTotals ,
redirectedCout ,
redirectedCerr ,
missingAssertions ,
aborting ( ) ) ) ;
2012-11-21 19:06:13 +01:00
delete m_runningTest ;
m_runningTest = NULL ;
2012-08-23 21:08:50 +02:00
return deltaTotals ;
2011-05-24 09:23:02 +02:00
}
2012-08-23 21:08:50 +02:00
const Config & config ( ) const {
return m_config ;
}
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
private : // IResultCapture
2011-05-24 09:23:02 +02:00
2013-02-02 21:37:58 +01:00
virtual void acceptMessage ( const MessageBuilder & messageBuilder ) {
m_messages . push_back ( messageBuilder . build ( ) ) ;
}
2012-10-29 21:49:22 +01:00
virtual ResultAction : : Value acceptExpression ( const ExpressionResultBuilder & assertionResult , const AssertionInfo & assertionInfo ) {
2012-11-04 22:39:38 +01:00
m_lastAssertionInfo = assertionInfo ;
return actOnCurrentResult ( assertionResult . buildResult ( assertionInfo ) ) ;
2012-08-23 21:08:50 +02:00
}
2011-05-24 09:23:02 +02:00
2013-02-02 21:37:58 +01:00
virtual void assertionEnded ( const AssertionResult & result ) {
2012-08-23 21:08:50 +02:00
if ( result . getResultType ( ) = = ResultWas : : Ok ) {
m_totals . assertions . passed + + ;
}
2012-11-13 10:44:52 +01:00
else if ( ! result . isOk ( ) ) {
2012-08-23 21:08:50 +02:00
m_totals . assertions . failed + + ;
}
2011-05-24 09:23:02 +02:00
2013-02-02 21:37:58 +01:00
m_reporter - > assertionEnded ( AssertionStats ( result , m_messages , m_totals ) ) ;
2012-11-19 20:59:10 +01:00
2013-02-02 21:37:58 +01:00
// Reset working state
m_lastAssertionInfo = AssertionInfo ( " " , m_lastAssertionInfo . lineInfo , " {Unknown expression after the reported line} " , m_lastAssertionInfo . resultDisposition ) ;
m_messages . clear ( ) ;
2012-08-23 21:08:50 +02:00
}
2012-06-01 20:40:27 +02:00
2012-08-23 21:08:50 +02:00
virtual bool sectionStarted (
2012-12-02 00:57:18 +01:00
SectionInfo const & sectionInfo ,
2012-08-23 21:08:50 +02:00
Counts & assertions
)
{
std : : ostringstream oss ;
2012-12-02 00:57:18 +01:00
oss < < sectionInfo . name < < " @ " < < sectionInfo . lineInfo ;
2012-06-01 20:40:27 +02:00
2012-08-23 21:08:50 +02:00
if ( ! m_runningTest - > addSection ( oss . str ( ) ) )
return false ;
2011-05-24 09:23:02 +02:00
2012-12-02 00:57:18 +01:00
m_lastAssertionInfo . lineInfo = sectionInfo . lineInfo ;
m_reporter - > sectionStarting ( sectionInfo ) ;
2012-11-04 22:39:38 +01:00
2012-08-23 21:08:50 +02:00
assertions = m_totals . assertions ;
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
return true ;
}
2011-05-24 09:23:02 +02:00
2012-12-02 00:57:18 +01:00
virtual void sectionEnded ( SectionInfo const & info , Counts const & prevAssertions ) {
2013-02-19 20:47:18 +01:00
if ( std : : uncaught_exception ( ) ) {
m_unfinishedSections . push_back ( UnfinishedSections ( info , prevAssertions ) ) ;
return ;
}
2012-08-31 09:10:36 +02:00
Counts assertions = m_totals . assertions - prevAssertions ;
2012-12-02 00:57:18 +01:00
bool missingAssertions = false ;
2012-11-21 19:06:13 +01:00
if ( assertions . total ( ) = = 0 & &
2012-08-31 09:10:36 +02:00
( m_config . data ( ) . warnings & ConfigData : : WarnAbout : : NoAssertions ) & &
! m_runningTest - > isBranchSection ( ) ) {
m_totals . assertions . failed + + ;
assertions . failed + + ;
2012-12-02 00:57:18 +01:00
missingAssertions = true ;
2012-08-31 09:10:36 +02:00
}
2013-03-04 12:19:15 +01:00
m_runningTest - > endSection ( info . name , false ) ;
2012-12-02 00:57:18 +01:00
2013-01-16 10:44:43 +01:00
m_reporter - > sectionEnded ( SectionStats ( info , assertions , missingAssertions ) ) ;
2013-02-02 21:37:58 +01:00
m_messages . clear ( ) ;
2012-08-23 21:08:50 +02:00
}
2012-05-21 19:52:09 +02:00
2013-02-02 21:37:58 +01:00
virtual void pushScopedMessage ( ScopedMessageBuilder const & _builder ) {
m_messages . push_back ( _builder . build ( ) ) ;
2012-08-13 08:46:10 +02:00
}
2011-05-24 09:23:02 +02:00
2013-02-02 21:37:58 +01:00
virtual void popScopedMessage ( ScopedMessageBuilder const & _builder ) {
m_messages . erase ( std : : remove ( m_messages . begin ( ) , m_messages . end ( ) , _builder ) , m_messages . end ( ) ) ;
2012-08-23 21:08:50 +02:00
}
2012-05-16 16:09:17 +02:00
2012-08-23 21:08:50 +02:00
virtual bool shouldDebugBreak ( ) const {
return m_config . shouldDebugBreak ( ) ;
2012-08-13 08:46:10 +02:00
}
2012-05-16 16:09:17 +02:00
2012-08-23 21:08:50 +02:00
virtual std : : string getCurrentTestName ( ) const {
return m_runningTest
2012-12-02 00:57:18 +01:00
? m_runningTest - > getTestCase ( ) . getTestCaseInfo ( ) . name
2012-08-23 21:08:50 +02:00
: " " ;
}
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
virtual const AssertionResult * getLastResult ( ) const {
2012-08-23 21:08:50 +02:00
return & m_lastResult ;
2011-05-24 09:23:02 +02:00
}
2012-08-23 21:08:50 +02: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 . getCutoff ( ) ) ;
2011-05-24 09:23:02 +02:00
}
2012-08-23 21:08:50 +02:00
private :
2012-08-09 08:47:30 +02:00
2012-11-04 22:39:38 +01:00
ResultAction : : Value actOnCurrentResult ( const AssertionResult & result ) {
m_lastResult = result ;
2013-02-02 21:37:58 +01:00
assertionEnded ( m_lastResult ) ;
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
ResultAction : : Value action = ResultAction : : None ;
2011-05-24 09:23:02 +02:00
2012-11-13 10:44:52 +01:00
if ( ! m_lastResult . isOk ( ) ) {
2012-08-23 21:08:50 +02:00
action = ResultAction : : Failed ;
if ( shouldDebugBreak ( ) )
action = ( ResultAction : : Value ) ( action | ResultAction : : Debug ) ;
if ( aborting ( ) )
action = ( ResultAction : : Value ) ( action | ResultAction : : Abort ) ;
2012-08-13 08:46:10 +02:00
}
2012-08-23 21:08:50 +02:00
return action ;
2011-05-24 09:23:02 +02:00
}
2012-08-23 21:08:50 +02:00
void runCurrentTest ( std : : string & redirectedCout , std : : string & redirectedCerr ) {
try {
2012-12-02 00:57:18 +01:00
m_lastAssertionInfo = AssertionInfo ( " TEST_CASE " , m_runningTest - > getTestCase ( ) . getTestCaseInfo ( ) . lineInfo , " " , ResultDisposition : : Normal ) ;
2012-08-23 21:08:50 +02:00
m_runningTest - > reset ( ) ;
2013-02-04 01:05:16 +01:00
2012-12-02 00:57:18 +01:00
if ( m_reporter - > getPreferences ( ) . shouldRedirectStdOut ) {
2012-08-23 21:08:50 +02:00
StreamRedirect coutRedir ( std : : cout , redirectedCout ) ;
StreamRedirect cerrRedir ( std : : cerr , redirectedCerr ) ;
2012-12-02 00:57:18 +01:00
m_runningTest - > getTestCase ( ) . invoke ( ) ;
2012-08-23 21:08:50 +02:00
}
else {
2012-12-02 00:57:18 +01:00
m_runningTest - > getTestCase ( ) . invoke ( ) ;
2012-08-23 21:08:50 +02:00
}
m_runningTest - > ranToCompletion ( ) ;
}
catch ( TestFailureException & ) {
// This just means the test was aborted due to failure
}
catch ( . . . ) {
2012-11-04 22:39:38 +01:00
ExpressionResultBuilder exResult ( ResultWas : : ThrewException ) ;
exResult < < translateActiveException ( ) ;
actOnCurrentResult ( exResult . buildResult ( m_lastAssertionInfo ) ) ;
2012-08-23 21:08:50 +02:00
}
2013-02-19 20:47:18 +01:00
for ( std : : vector < UnfinishedSections > : : const_iterator it = m_unfinishedSections . begin ( ) ,
itEnd = m_unfinishedSections . end ( ) ;
it ! = itEnd ;
+ + it )
sectionEnded ( it - > info , it - > prevAssertions ) ;
m_unfinishedSections . clear ( ) ;
2013-02-04 01:05:16 +01:00
m_messages . clear ( ) ;
2011-05-24 09:23:02 +02:00
}
2012-08-23 21:08:50 +02:00
private :
2013-02-19 20:47:18 +01:00
struct UnfinishedSections {
UnfinishedSections ( SectionInfo const & _info , Counts const & _prevAssertions )
: info ( _info ) , prevAssertions ( _prevAssertions )
{ }
SectionInfo info ;
Counts prevAssertions ;
} ;
2012-12-02 00:57:18 +01:00
TestRunInfo m_runInfo ;
2012-08-23 21:08:50 +02:00
IMutableContext & m_context ;
RunningTest * m_runningTest ;
2012-10-28 13:07:17 +01:00
AssertionResult m_lastResult ;
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
const Config & m_config ;
Totals m_totals ;
2012-12-02 00:57:18 +01:00
Ptr < IStreamingReporter > m_reporter ;
2013-02-02 21:37:58 +01:00
std : : vector < MessageInfo > m_messages ;
2012-08-23 21:08:50 +02:00
IRunner * m_prevRunner ;
IResultCapture * m_prevResultCapture ;
const IConfig * m_prevConfig ;
2012-11-04 22:39:38 +01:00
AssertionInfo m_lastAssertionInfo ;
2013-02-19 20:47:18 +01:00
std : : vector < UnfinishedSections > m_unfinishedSections ;
2012-08-23 21:08:50 +02:00
} ;
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
} // end namespace Catch
2011-05-24 09:23:02 +02:00
2012-11-15 23:15:41 +01:00
// #included from: internal/catch_version.h
# define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED
namespace Catch {
// Versioning information
struct Version {
2012-12-02 00:57:18 +01:00
Version ( unsigned int _majorVersion ,
unsigned int _minorVersion ,
unsigned int _buildNumber ,
std : : string const & _branchName )
: majorVersion ( _majorVersion ) ,
minorVersion ( _minorVersion ) ,
buildNumber ( _buildNumber ) ,
branchName ( _branchName )
{ }
const unsigned int majorVersion ;
const unsigned int minorVersion ;
const unsigned int buildNumber ;
const std : : string branchName ;
2012-11-15 23:15:41 +01:00
} ;
extern Version libraryVersion ;
}
2013-01-16 10:44:43 +01:00
// #included from: internal/catch_line_wrap.h
# define TWOBLUECUBES_CATCH_LINE_WRAP_H_INCLUDED
# include <string>
namespace Catch {
void wrapLongStrings ( std : : ostream & stream , const std : : string & str , std : : size_t columns , std : : size_t indent = 0 ) ;
std : : string wrapLongStrings ( const std : : string & str , std : : size_t columns , std : : size_t indent = 0 ) ;
} // end namespace Catch
2012-08-23 21:08:50 +02:00
# include <fstream>
# include <stdlib.h>
# include <limits>
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
namespace Catch {
2012-02-28 21:04:42 +01:00
2012-08-23 21:08:50 +02:00
class Runner2 { // This will become Runner when Runner becomes Context
2012-02-28 21:04:42 +01:00
2012-08-23 21:08:50 +02:00
public :
Runner2 ( Config & configWrapper )
: m_configWrapper ( configWrapper ) ,
m_config ( configWrapper . data ( ) )
{
2012-09-26 19:38:26 +02:00
openStream ( ) ;
2012-08-23 21:08:50 +02:00
makeReporter ( ) ;
2012-08-09 08:47:30 +02:00
}
2012-05-16 16:09:17 +02:00
2012-08-23 21:08:50 +02:00
Totals runTests ( ) {
std : : vector < TestCaseFilters > filterGroups = m_config . filters ;
if ( filterGroups . empty ( ) ) {
TestCaseFilters filterGroup ( " " ) ;
filterGroups . push_back ( filterGroup ) ;
}
2012-02-28 21:04:42 +01:00
2012-08-23 21:08:50 +02:00
Runner context ( m_configWrapper , m_reporter ) ; // This Runner will be renamed Context
Totals totals ;
2012-02-28 21:04:42 +01:00
2013-01-16 10:44:43 +01:00
for ( std : : size_t i = 0 ; i < filterGroups . size ( ) & & ! context . aborting ( ) ; + + i ) {
context . testGroupStarting ( filterGroups [ i ] . getName ( ) , i , filterGroups . size ( ) ) ;
totals + = runTestsForGroup ( context , filterGroups [ i ] ) ;
context . testGroupEnded ( filterGroups [ i ] . getName ( ) , totals , i , filterGroups . size ( ) ) ;
2012-08-13 08:46:10 +02:00
}
2012-08-23 21:08:50 +02:00
return totals ;
2012-08-09 08:47:30 +02:00
}
2012-02-28 21:04:42 +01:00
2012-08-23 21:08:50 +02:00
Totals runTestsForGroup ( Runner & context , const TestCaseFilters & filterGroup ) {
Totals totals ;
2012-12-02 00:57:18 +01:00
std : : vector < TestCase > : : const_iterator it = getRegistryHub ( ) . getTestCaseRegistry ( ) . getAllTests ( ) . begin ( ) ;
std : : vector < TestCase > : : const_iterator itEnd = getRegistryHub ( ) . getTestCaseRegistry ( ) . getAllTests ( ) . end ( ) ;
2012-08-23 21:08:50 +02:00
int testsRunForGroup = 0 ;
2012-08-13 08:46:10 +02:00
for ( ; it ! = itEnd ; + + it ) {
2012-08-23 21:08:50 +02:00
if ( filterGroup . shouldInclude ( * it ) ) {
testsRunForGroup + + ;
if ( m_testsAlreadyRun . find ( * it ) = = m_testsAlreadyRun . end ( ) ) {
2012-02-28 21:04:42 +01:00
2012-08-23 21:08:50 +02:00
if ( context . aborting ( ) )
break ;
totals + = context . runTest ( * it ) ;
m_testsAlreadyRun . insert ( * it ) ;
}
2012-08-13 08:46:10 +02:00
}
2012-08-09 08:47:30 +02:00
}
2013-02-19 20:47:18 +01:00
if ( testsRunForGroup = = 0 & & ! filterGroup . getName ( ) . empty ( ) )
2012-08-23 21:08:50 +02:00
std : : cerr < < " \n [No test cases matched with: " < < filterGroup . getName ( ) < < " ] " < < std : : endl ;
return totals ;
2012-08-09 08:47:30 +02:00
}
2012-02-28 21:04:42 +01:00
2012-08-13 08:46:10 +02:00
private :
2012-09-26 19:38:26 +02:00
void openStream ( ) {
if ( ! m_config . stream . empty ( ) )
m_configWrapper . useStream ( m_config . stream ) ;
2012-08-23 21:08:50 +02:00
// Open output file, if specified
if ( ! m_config . outputFilename . empty ( ) ) {
m_ofs . open ( m_config . outputFilename . c_str ( ) ) ;
if ( m_ofs . fail ( ) ) {
std : : ostringstream oss ;
oss < < " Unable to open file: ' " < < m_config . outputFilename < < " ' " ;
throw std : : domain_error ( oss . str ( ) ) ;
}
m_configWrapper . setStreamBuf ( m_ofs . rdbuf ( ) ) ;
}
}
void makeReporter ( ) {
std : : string reporterName = m_config . reporter . empty ( )
2012-12-10 09:54:57 +01:00
? " console "
2012-08-23 21:08:50 +02:00
: m_config . reporter ;
2012-02-28 21:04:42 +01:00
2012-12-02 00:57:18 +01:00
ReporterConfig reporterConfig ( m_configWrapper . stream ( ) , m_config ) ;
2012-08-23 21:08:50 +02:00
m_reporter = getRegistryHub ( ) . getReporterRegistry ( ) . create ( reporterName , reporterConfig ) ;
if ( ! m_reporter ) {
std : : ostringstream oss ;
oss < < " No reporter registered with name: ' " < < reporterName < < " ' " ;
throw std : : domain_error ( oss . str ( ) ) ;
}
}
private :
Config & m_configWrapper ;
const ConfigData & m_config ;
std : : ofstream m_ofs ;
2012-12-02 00:57:18 +01:00
Ptr < IStreamingReporter > m_reporter ;
std : : set < TestCase > m_testsAlreadyRun ;
2012-08-13 08:46:10 +02:00
} ;
2012-02-28 21:04:42 +01:00
2012-08-23 21:08:50 +02:00
inline int Main ( Config & configWrapper ) {
int result = 0 ;
try
{
Runner2 runner ( configWrapper ) ;
2012-02-28 21:04:42 +01:00
2012-08-23 21:08:50 +02:00
const ConfigData & config = configWrapper . data ( ) ;
2012-02-28 21:04:42 +01:00
2012-08-23 21:08:50 +02:00
// Handle list request
if ( config . listSpec ! = List : : None ) {
List ( config ) ;
2012-09-24 09:30:13 +02:00
Catch : : cleanUp ( ) ;
2012-08-23 21:08:50 +02:00
return 0 ;
}
2012-02-28 21:04:42 +01:00
2012-08-23 21:08:50 +02:00
result = static_cast < int > ( runner . runTests ( ) . assertions . failed ) ;
2012-05-16 16:09:17 +02:00
2012-08-23 21:08:50 +02:00
}
catch ( std : : exception & ex ) {
std : : cerr < < ex . what ( ) < < std : : endl ;
result = ( std : : numeric_limits < int > : : max ) ( ) ;
}
2012-05-16 16:09:17 +02:00
2012-08-23 21:08:50 +02:00
Catch : : cleanUp ( ) ;
return result ;
}
2012-05-16 16:09:17 +02:00
2012-08-23 21:08:50 +02:00
inline void showUsage ( std : : ostream & os ) {
2012-08-27 22:42:55 +02:00
AllOptions options ;
2012-09-07 18:52:35 +02:00
2012-08-27 22:42:55 +02:00
for ( AllOptions : : const_iterator it = options . begin ( ) ; it ! = options . end ( ) ; + + it ) {
OptionParser & opt = * * it ;
os < < " " < < opt . optionNames ( ) < < " " < < opt . argsSynopsis ( ) < < " \n " ;
}
os < < " \n For more detail usage please see: https://github.com/philsquared/Catch/wiki/Command-line \n " < < std : : endl ;
2012-08-23 21:08:50 +02:00
}
2012-09-07 18:52:35 +02:00
inline void showHelp ( const CommandParser & parser ) {
AllOptions options ;
Options : : HelpOptionParser helpOpt ;
bool displayedSpecificOption = false ;
for ( AllOptions : : const_iterator it = options . begin ( ) ; it ! = options . end ( ) ; + + it ) {
OptionParser & opt = * * it ;
if ( opt . find ( parser ) & & opt . optionNames ( ) ! = helpOpt . optionNames ( ) ) {
displayedSpecificOption = true ;
std : : cout < < " \n " < < opt . optionNames ( ) < < " " < < opt . argsSynopsis ( ) < < " \n \n "
< < opt . optionSummary ( ) < < " \n \n "
2013-01-16 10:44:43 +01:00
< < wrapLongStrings ( opt . optionDescription ( ) , 80 , 2 ) < < " \n " < < std : : endl ;
2012-09-07 18:52:35 +02:00
}
}
if ( ! displayedSpecificOption ) {
2013-01-16 10:44:43 +01:00
std : : cout < < " \n CATCH v " < < libraryVersion . majorVersion < < " . "
2012-12-02 00:57:18 +01:00
< < libraryVersion . minorVersion < < " build "
< < libraryVersion . buildNumber ;
if ( libraryVersion . branchName ! = " master " )
std : : cout < < " ( " < < libraryVersion . branchName < < " branch) " ;
2012-11-15 23:15:41 +01:00
2012-11-19 20:59:10 +01:00
std : : cout < < " \n \n " < < parser . exeName ( ) < < " is a CATCH host application. Options are as follows: \n \n " ;
2012-09-07 18:52:35 +02:00
showUsage ( std : : cout ) ;
}
2012-08-23 21:08:50 +02:00
}
2012-02-28 21:04:42 +01:00
2012-08-23 21:08:50 +02:00
inline int Main ( int argc , char * const argv [ ] , Config & config ) {
2012-02-28 21:04:42 +01:00
2012-08-23 21:08:50 +02:00
try {
CommandParser parser ( argc , argv ) ;
2012-05-11 09:17:16 +02:00
2012-08-27 22:42:55 +02:00
if ( Command cmd = Options : : HelpOptionParser ( ) . find ( parser ) ) {
2012-08-23 21:08:50 +02:00
if ( cmd . argsCount ( ) ! = 0 )
cmd . raiseError ( " Does not accept arguments " ) ;
2012-05-21 22:51:16 +02:00
2012-09-07 18:52:35 +02:00
showHelp ( parser ) ;
2012-08-23 21:08:50 +02:00
Catch : : cleanUp ( ) ;
return 0 ;
}
2012-05-16 16:09:17 +02:00
2012-08-27 22:42:55 +02:00
AllOptions options ;
options . parseIntoConfig ( parser , config . data ( ) ) ;
2012-08-23 21:08:50 +02:00
}
catch ( std : : exception & ex ) {
std : : cerr < < ex . what ( ) < < " \n \n Usage: ... \n \n " ;
showUsage ( std : : cerr ) ;
Catch : : cleanUp ( ) ;
return ( std : : numeric_limits < int > : : max ) ( ) ;
}
2012-05-11 09:17:16 +02:00
2012-08-23 21:08:50 +02:00
return Main ( config ) ;
}
2012-05-11 09:17:16 +02:00
2012-08-23 21:08:50 +02:00
inline int Main ( int argc , char * const argv [ ] ) {
Config config ;
// !TBD: This doesn't always work, for some reason
// if( isDebuggerActive() )
// config.useStream( "debug" );
return Main ( argc , argv , config ) ;
}
2012-08-09 08:47:30 +02:00
2012-08-23 21:08:50 +02:00
} // end namespace Catch
2012-05-11 09:17:16 +02:00
2012-08-23 21:08:50 +02:00
// #included from: catch_registry_hub.hpp
2012-09-17 07:42:29 +02:00
# define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED
2012-05-11 09:17:16 +02:00
2012-08-23 21:08:50 +02:00
// #included from: catch_test_case_registry_impl.hpp
2012-09-17 07:42:29 +02:00
# define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
2012-05-11 09:17:16 +02:00
2012-08-23 21:08:50 +02:00
# include <vector>
# include <set>
# include <sstream>
# include <iostream>
2012-05-11 09:17:16 +02:00
2012-08-23 21:08:50 +02:00
namespace Catch {
2012-05-11 09:17:16 +02:00
2012-08-23 21:08:50 +02:00
class TestRegistry : public ITestCaseRegistry {
public :
TestRegistry ( ) : m_unnamedCount ( 0 ) { }
virtual ~ TestRegistry ( ) ;
2012-05-16 16:09:17 +02:00
2012-12-02 00:57:18 +01:00
virtual void registerTest ( const TestCase & testCase ) {
std : : string name = testCase . getTestCaseInfo ( ) . name ;
if ( name = = " " ) {
2012-08-23 21:08:50 +02:00
std : : ostringstream oss ;
2012-12-02 00:57:18 +01:00
oss < < name < < " unnamed/ " < < + + m_unnamedCount ;
return registerTest ( testCase . withName ( oss . str ( ) ) ) ;
2012-08-23 21:08:50 +02:00
}
2012-05-16 16:09:17 +02:00
2012-12-02 00:57:18 +01:00
if ( m_functions . find ( testCase ) = = m_functions . end ( ) ) {
m_functions . insert ( testCase ) ;
m_functionsInOrder . push_back ( testCase ) ;
if ( ! testCase . isHidden ( ) )
m_nonHiddenFunctions . push_back ( testCase ) ;
2012-08-23 21:08:50 +02:00
}
else {
2012-12-02 00:57:18 +01:00
const TestCase & prev = * m_functions . find ( testCase ) ;
std : : cerr < < " error: TEST_CASE( \" " < < name < < " \" ) already defined. \n "
< < " \t First seen at " < < SourceLineInfo ( prev . getTestCaseInfo ( ) . lineInfo ) < < " \n "
< < " \t Redefined at " < < SourceLineInfo ( testCase . getTestCaseInfo ( ) . lineInfo ) < < std : : endl ;
2012-08-23 21:08:50 +02:00
exit ( 1 ) ;
}
2012-08-13 08:46:10 +02:00
}
2012-05-11 09:17:16 +02:00
2012-12-02 00:57:18 +01:00
virtual const std : : vector < TestCase > & getAllTests ( ) const {
2012-08-23 21:08:50 +02:00
return m_functionsInOrder ;
2012-08-13 08:46:10 +02:00
}
2012-05-11 09:17:16 +02:00
2012-12-02 00:57:18 +01:00
virtual const std : : vector < TestCase > & getAllNonHiddenTests ( ) const {
2012-08-23 21:08:50 +02:00
return m_nonHiddenFunctions ;
2012-08-13 08:46:10 +02:00
}
2012-05-11 09:17:16 +02:00
2012-08-23 21:08:50 +02:00
// !TBD deprecated
2012-12-02 00:57:18 +01:00
virtual std : : vector < TestCase > getMatchingTestCases ( const std : : string & rawTestSpec ) const {
std : : vector < TestCase > matchingTests ;
2012-08-23 21:08:50 +02:00
getMatchingTestCases ( rawTestSpec , matchingTests ) ;
return matchingTests ;
2012-08-13 08:46:10 +02:00
}
2012-05-11 09:17:16 +02:00
2012-08-23 21:08:50 +02:00
// !TBD deprecated
2012-12-02 00:57:18 +01:00
virtual void getMatchingTestCases ( const std : : string & rawTestSpec , std : : vector < TestCase > & matchingTestsOut ) const {
2012-08-23 21:08:50 +02:00
TestCaseFilter filter ( rawTestSpec ) ;
2012-08-09 08:47:30 +02:00
2012-12-02 00:57:18 +01:00
std : : vector < TestCase > : : const_iterator it = m_functionsInOrder . begin ( ) ;
std : : vector < TestCase > : : const_iterator itEnd = m_functionsInOrder . end ( ) ;
2012-08-23 21:08:50 +02:00
for ( ; it ! = itEnd ; + + it ) {
if ( filter . shouldInclude ( * it ) ) {
matchingTestsOut . push_back ( * it ) ;
}
}
2012-08-13 08:46:10 +02:00
}
2012-12-02 00:57:18 +01:00
virtual void getMatchingTestCases ( const TestCaseFilters & filters , std : : vector < TestCase > & matchingTestsOut ) const {
std : : vector < TestCase > : : const_iterator it = m_functionsInOrder . begin ( ) ;
std : : vector < TestCase > : : const_iterator itEnd = m_functionsInOrder . end ( ) ;
2012-08-23 21:08:50 +02:00
// !TBD: replace with algorithm
for ( ; it ! = itEnd ; + + it )
if ( filters . shouldInclude ( * it ) )
matchingTestsOut . push_back ( * it ) ;
2012-08-13 08:46:10 +02:00
}
2012-05-11 09:17:16 +02:00
2012-08-23 21:08:50 +02:00
private :
2011-05-24 09:23:02 +02:00
2012-12-02 00:57:18 +01:00
std : : set < TestCase > m_functions ;
std : : vector < TestCase > m_functionsInOrder ;
std : : vector < TestCase > m_nonHiddenFunctions ;
2012-08-23 21:08:50 +02:00
size_t m_unnamedCount ;
} ;
///////////////////////////////////////////////////////////////////////////
2012-05-16 16:09:17 +02:00
2012-08-23 21:08:50 +02:00
class FreeFunctionTestCase : public SharedImpl < ITestCase > {
public :
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
FreeFunctionTestCase ( TestFunction fun ) : m_fun ( fun ) { }
virtual void invoke ( ) const {
m_fun ( ) ;
2011-05-24 09:23:02 +02:00
}
2012-08-13 08:46:10 +02:00
private :
2012-08-23 21:08:50 +02:00
virtual ~ FreeFunctionTestCase ( ) ;
2012-08-13 08:46:10 +02:00
2012-08-23 21:08:50 +02:00
TestFunction m_fun ;
2012-08-09 08:47:30 +02:00
} ;
2011-05-24 09:23:02 +02:00
2012-11-04 22:39:38 +01:00
inline std : : string extractClassName ( const std : : string & classOrQualifiedMethodName ) {
std : : string className = classOrQualifiedMethodName ;
if ( className [ 0 ] = = ' & ' )
{
std : : size_t lastColons = className . rfind ( " :: " ) ;
std : : size_t penultimateColons = className . rfind ( " :: " , lastColons - 1 ) ;
if ( penultimateColons = = std : : string : : npos )
penultimateColons = 1 ;
className = className . substr ( penultimateColons , lastColons - penultimateColons ) ;
}
return className ;
}
2012-08-23 21:08:50 +02:00
///////////////////////////////////////////////////////////////////////////
AutoReg : : AutoReg ( TestFunction function ,
const char * name ,
const char * description ,
const SourceLineInfo & lineInfo ) {
2012-11-04 22:39:38 +01:00
registerTestCase ( new FreeFunctionTestCase ( function ) , " global " , name , description , lineInfo ) ;
2012-08-23 21:08:50 +02:00
}
AutoReg : : ~ AutoReg ( ) { }
void AutoReg : : registerTestCase ( ITestCase * testCase ,
2012-11-04 22:39:38 +01:00
const char * classOrQualifiedMethodName ,
2012-08-23 21:08:50 +02:00
const char * name ,
const char * description ,
const SourceLineInfo & lineInfo ) {
2012-11-04 22:39:38 +01:00
2012-12-02 00:57:18 +01:00
getMutableRegistryHub ( ) . registerTest ( makeTestCase ( testCase , extractClassName ( classOrQualifiedMethodName ) , name , description , lineInfo ) ) ;
2012-08-23 21:08:50 +02:00
}
2012-08-13 08:46:10 +02:00
} // end namespace Catch
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
// #included from: catch_reporter_registry.hpp
# define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED
# include <map>
2012-08-13 08:46:10 +02:00
namespace Catch {
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
class ReporterRegistry : public IReporterRegistry {
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
public :
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
virtual ~ ReporterRegistry ( ) {
deleteAllValues ( m_factories ) ;
2012-08-13 08:46:10 +02:00
}
2011-05-24 09:23:02 +02:00
2012-12-02 00:57:18 +01:00
virtual IStreamingReporter * create ( const std : : string & name , const ReporterConfig & config ) const {
2012-08-23 21:08:50 +02:00
FactoryMap : : const_iterator it = m_factories . find ( name ) ;
if ( it = = m_factories . end ( ) )
return NULL ;
return it - > second - > create ( config ) ;
2012-08-13 08:46:10 +02:00
}
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
void registerReporter ( const std : : string & name , IReporterFactory * factory ) {
m_factories . insert ( std : : make_pair ( name , factory ) ) ;
}
2012-05-11 09:17:16 +02:00
2012-08-23 21:08:50 +02:00
const FactoryMap & getFactories ( ) const {
return m_factories ;
2011-05-24 09:23:02 +02:00
}
2012-05-31 20:40:26 +02:00
2012-08-09 08:47:30 +02:00
private :
2012-08-23 21:08:50 +02:00
FactoryMap m_factories ;
2012-08-13 08:46:10 +02:00
} ;
2012-08-23 21:08:50 +02:00
}
2012-05-31 20:40:26 +02:00
2012-08-23 21:08:50 +02:00
// #included from: catch_exception_translator_registry.hpp
2012-09-17 07:42:29 +02:00
# define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED
2012-05-31 20:40:26 +02:00
2012-08-23 21:08:50 +02:00
# ifdef __OBJC__
# import "Foundation / Foundation.h"
# endif
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
namespace Catch {
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry {
public :
~ ExceptionTranslatorRegistry ( ) {
deleteAll ( m_translators ) ;
2012-05-31 20:40:26 +02:00
}
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
virtual void registerTranslator ( const IExceptionTranslator * translator ) {
m_translators . push_back ( translator ) ;
}
2012-05-31 20:40:26 +02:00
2012-08-23 21:08:50 +02:00
virtual std : : string translateActiveException ( ) const {
try {
# ifdef __OBJC__
// In Objective-C try objective-c exceptions first
@ try {
throw ;
}
@ catch ( NSException * exception ) {
return toString ( [ exception description ] ) ;
}
# else
throw ;
# endif
}
catch ( std : : exception & ex ) {
return ex . what ( ) ;
}
catch ( std : : string & msg ) {
return msg ;
}
catch ( const char * msg ) {
return msg ;
}
catch ( . . . ) {
return tryTranslators ( m_translators . begin ( ) ) ;
}
}
2012-08-13 08:46:10 +02:00
2012-08-23 21:08:50 +02:00
std : : string tryTranslators ( std : : vector < const IExceptionTranslator * > : : const_iterator it ) const {
if ( it = = m_translators . end ( ) )
return " Unknown exception " ;
2012-08-13 08:46:10 +02:00
2012-08-23 21:08:50 +02:00
try {
return ( * it ) - > translate ( ) ;
2012-08-13 08:46:10 +02:00
}
2012-08-23 21:08:50 +02:00
catch ( . . . ) {
return tryTranslators ( it + 1 ) ;
2012-05-31 20:40:26 +02:00
}
2012-07-05 19:37:58 +02:00
}
2012-05-31 20:40:26 +02:00
2012-08-23 21:08:50 +02:00
private :
std : : vector < const IExceptionTranslator * > m_translators ;
} ;
}
2012-05-31 20:40:26 +02:00
2012-08-23 21:08:50 +02:00
namespace Catch {
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
namespace {
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
class RegistryHub : public IRegistryHub , public IMutableRegistryHub {
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
RegistryHub ( const RegistryHub & ) ;
void operator = ( const RegistryHub & ) ;
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
public : // IRegistryHub
RegistryHub ( ) {
}
virtual const IReporterRegistry & getReporterRegistry ( ) const {
return m_reporterRegistry ;
}
virtual const ITestCaseRegistry & getTestCaseRegistry ( ) const {
return m_testCaseRegistry ;
}
virtual IExceptionTranslatorRegistry & getExceptionTranslatorRegistry ( ) {
return m_exceptionTranslatorRegistry ;
}
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
public : // IMutableRegistryHub
virtual void registerReporter ( const std : : string & name , IReporterFactory * factory ) {
m_reporterRegistry . registerReporter ( name , factory ) ;
2011-05-24 09:23:02 +02:00
}
2012-12-02 00:57:18 +01:00
virtual void registerTest ( const TestCase & testInfo ) {
2012-08-23 21:08:50 +02:00
m_testCaseRegistry . registerTest ( testInfo ) ;
}
virtual void registerTranslator ( const IExceptionTranslator * translator ) {
m_exceptionTranslatorRegistry . registerTranslator ( translator ) ;
}
private :
TestRegistry m_testCaseRegistry ;
ReporterRegistry m_reporterRegistry ;
ExceptionTranslatorRegistry m_exceptionTranslatorRegistry ;
} ;
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
// Single, global, instance
inline RegistryHub * & getTheRegistryHub ( ) {
static RegistryHub * theRegistryHub = NULL ;
if ( ! theRegistryHub )
theRegistryHub = new RegistryHub ( ) ;
return theRegistryHub ;
2011-05-24 09:23:02 +02:00
}
2012-08-23 21:08:50 +02:00
}
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
IRegistryHub & getRegistryHub ( ) {
return * getTheRegistryHub ( ) ;
}
IMutableRegistryHub & getMutableRegistryHub ( ) {
return * getTheRegistryHub ( ) ;
}
void cleanUp ( ) {
delete getTheRegistryHub ( ) ;
getTheRegistryHub ( ) = NULL ;
cleanUpContext ( ) ;
2012-08-13 08:46:10 +02:00
}
2012-10-28 13:07:17 +01:00
std : : string translateActiveException ( ) {
return getRegistryHub ( ) . getExceptionTranslatorRegistry ( ) . translateActiveException ( ) ;
}
2012-08-09 08:47:30 +02:00
2012-08-13 08:46:10 +02:00
} // end namespace Catch
2012-09-17 07:42:29 +02:00
2012-08-23 21:08:50 +02:00
// #included from: catch_notimplemented_exception.hpp
# define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED
2012-08-09 08:47:30 +02:00
2012-08-23 21:08:50 +02:00
# include <ostream>
2012-08-09 08:47:30 +02:00
2012-08-13 08:46:10 +02:00
namespace Catch {
2012-08-09 08:47:30 +02:00
2012-08-23 21:08:50 +02:00
NotImplementedException : : NotImplementedException ( const SourceLineInfo & lineInfo )
: m_lineInfo ( lineInfo ) {
std : : ostringstream oss ;
2013-01-16 10:44:43 +01:00
oss < < lineInfo < < " : function " ;
2012-08-23 21:08:50 +02:00
oss < < " not implemented " ;
m_what = oss . str ( ) ;
}
2012-08-09 08:47:30 +02:00
2012-08-23 21:08:50 +02:00
const char * NotImplementedException : : what ( ) const throw ( ) {
return m_what . c_str ( ) ;
2012-08-13 08:46:10 +02:00
}
2012-08-09 08:47:30 +02:00
} // end namespace Catch
2012-08-23 21:08:50 +02:00
// #included from: catch_context_impl.hpp
2012-09-17 07:42:29 +02:00
# define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED
2012-08-13 08:46:10 +02:00
namespace Catch {
2012-08-09 08:47:30 +02:00
2012-08-23 21:08:50 +02:00
class Context : public IMutableContext {
2012-08-09 08:47:30 +02:00
2012-08-23 21:08:50 +02:00
Context ( ) : m_config ( NULL ) { }
Context ( const Context & ) ;
void operator = ( const Context & ) ;
2012-08-09 08:47:30 +02:00
2012-08-23 21:08:50 +02:00
public : // IContext
virtual IResultCapture & getResultCapture ( ) {
return * m_resultCapture ;
2012-08-09 08:47:30 +02:00
}
2012-08-23 21:08:50 +02:00
virtual IRunner & getRunner ( ) {
return * m_runner ;
2012-08-09 08:47:30 +02:00
}
2012-08-23 21:08:50 +02:00
virtual size_t getGeneratorIndex ( const std : : string & fileInfo , size_t totalSize ) {
return getGeneratorsForCurrentTest ( )
. getGeneratorInfo ( fileInfo , totalSize )
. getCurrentIndex ( ) ;
2012-08-09 08:47:30 +02:00
}
2012-08-23 21:08:50 +02:00
virtual bool advanceGeneratorsForCurrentTest ( ) {
IGeneratorsForTest * generators = findGeneratorsForCurrentTest ( ) ;
return generators & & generators - > moveNext ( ) ;
2012-08-09 08:47:30 +02:00
}
2012-08-23 21:08:50 +02:00
virtual const IConfig * getConfig ( ) const {
return m_config ;
2012-08-09 08:47:30 +02:00
}
2012-08-23 21:08:50 +02:00
public : // IMutableContext
virtual void setResultCapture ( IResultCapture * resultCapture ) {
m_resultCapture = resultCapture ;
}
virtual void setRunner ( IRunner * runner ) {
m_runner = runner ;
}
virtual void setConfig ( const IConfig * config ) {
m_config = config ;
}
2012-08-16 19:48:50 +02:00
2012-08-23 21:08:50 +02:00
friend IMutableContext & getCurrentMutableContext ( ) ;
2012-08-16 19:48:50 +02:00
2012-08-23 21:08:50 +02:00
private :
IGeneratorsForTest * findGeneratorsForCurrentTest ( ) {
std : : string testName = getResultCapture ( ) . getCurrentTestName ( ) ;
2012-08-16 19:48:50 +02:00
2012-08-23 21:08:50 +02:00
std : : map < std : : string , IGeneratorsForTest * > : : const_iterator it =
m_generatorsByTestName . find ( testName ) ;
return it ! = m_generatorsByTestName . end ( )
? it - > second
: NULL ;
2012-08-16 19:48:50 +02:00
}
2012-08-23 21:08:50 +02: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 ;
2012-08-16 19:48:50 +02:00
}
private :
2012-08-23 21:08:50 +02:00
IRunner * m_runner ;
IResultCapture * m_resultCapture ;
const IConfig * m_config ;
std : : map < std : : string , IGeneratorsForTest * > m_generatorsByTestName ;
2012-08-16 19:48:50 +02:00
} ;
2012-08-23 21:08:50 +02:00
namespace {
Context * currentContext = NULL ;
}
IMutableContext & getCurrentMutableContext ( ) {
if ( ! currentContext )
currentContext = new Context ( ) ;
return * currentContext ;
}
IContext & getCurrentContext ( ) {
return getCurrentMutableContext ( ) ;
}
2012-08-09 08:47:30 +02:00
2012-09-26 19:38:26 +02:00
Stream createStream ( const std : : string & streamName ) {
if ( streamName = = " stdout " ) return Stream ( std : : cout . rdbuf ( ) , false ) ;
if ( streamName = = " stderr " ) return Stream ( std : : cerr . rdbuf ( ) , false ) ;
if ( streamName = = " debug " ) return Stream ( new StreamBufImpl < OutputDebugWriter > , true ) ;
2012-08-09 08:47:30 +02:00
2012-08-23 21:08:50 +02:00
throw std : : domain_error ( " Unknown stream: " + streamName ) ;
}
2012-08-13 08:46:10 +02:00
2012-08-23 21:08:50 +02:00
void cleanUpContext ( ) {
delete currentContext ;
currentContext = NULL ;
}
}
2012-09-17 07:42:29 +02:00
2012-08-23 21:08:50 +02:00
// #included from: catch_console_colour_impl.hpp
# define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED
2012-08-09 08:47:30 +02:00
2012-08-23 21:08:50 +02:00
// #included from: catch_console_colour.hpp
# define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED
2012-08-09 08:47:30 +02:00
2012-08-23 21:08:50 +02:00
namespace Catch {
2012-08-09 08:47:30 +02:00
2013-03-11 19:38:29 +01:00
struct IConsoleColourCodes : NonCopyable {
2012-08-23 21:08:50 +02:00
enum Colours {
None ,
2012-08-09 08:47:30 +02:00
2012-08-23 21:08:50 +02:00
FileName ,
ResultError ,
ResultSuccess ,
2012-08-09 08:47:30 +02:00
2012-08-23 21:08:50 +02:00
Error ,
Success ,
2012-08-09 08:47:30 +02:00
2012-08-23 21:08:50 +02:00
OriginalExpression ,
ReconstructedExpression
} ;
2012-08-09 08:47:30 +02:00
2013-03-11 19:38:29 +01:00
virtual void set ( Colours colour ) = 0 ;
} ;
class TextColour : public IConsoleColourCodes {
public :
2012-08-23 21:08:50 +02:00
TextColour ( Colours colour = None ) ;
void set ( Colours colour ) ;
~ TextColour ( ) ;
2012-08-09 08:47:30 +02:00
2012-08-23 21:08:50 +02:00
private :
2013-03-11 19:38:29 +01:00
IConsoleColourCodes * m_impl ;
2012-08-23 21:08:50 +02:00
} ;
2012-08-09 08:47:30 +02:00
2012-08-23 21:08:50 +02:00
} // end namespace Catch
2012-08-09 08:47:30 +02:00
2013-03-11 19:38:29 +01:00
# if defined ( CATCH_PLATFORM_WINDOWS ) /////////////////////////////////////////
# include <windows.h>
namespace {
using namespace Catch ;
WORD mapConsoleColour ( IConsoleColourCodes : : Colours colour ) {
switch ( colour ) {
case IConsoleColourCodes : : FileName :
return FOREGROUND_INTENSITY ; // greyed out
case IConsoleColourCodes : : ResultError :
return FOREGROUND_RED | FOREGROUND_INTENSITY ; // bright red
case IConsoleColourCodes : : ResultSuccess :
return FOREGROUND_GREEN | FOREGROUND_INTENSITY ; // bright green
case IConsoleColourCodes : : Error :
return FOREGROUND_RED | FOREGROUND_INTENSITY ; // bright red
case IConsoleColourCodes : : Success :
return FOREGROUND_GREEN ; // dark green
case IConsoleColourCodes : : OriginalExpression :
return FOREGROUND_BLUE | FOREGROUND_GREEN ; // turquoise
case IConsoleColourCodes : : ReconstructedExpression :
return FOREGROUND_RED | FOREGROUND_GREEN ; // greeny-yellow
default : return 0 ;
}
}
2013-03-04 12:19:15 +01:00
2013-03-11 19:38:29 +01:00
struct WindowsConsoleColourCodes : IConsoleColourCodes {
WindowsConsoleColourCodes ( )
: hStdout ( GetStdHandle ( STD_OUTPUT_HANDLE ) ) ,
wOldColorAttrs ( 0 )
{
GetConsoleScreenBufferInfo ( hStdout , & csbiInfo ) ;
wOldColorAttrs = csbiInfo . wAttributes ;
}
~ WindowsConsoleColourCodes ( ) {
SetConsoleTextAttribute ( hStdout , wOldColorAttrs ) ;
}
void set ( Colours colour ) {
WORD consoleColour = mapConsoleColour ( colour ) ;
if ( consoleColour > 0 )
SetConsoleTextAttribute ( hStdout , consoleColour ) ;
}
HANDLE hStdout ;
CONSOLE_SCREEN_BUFFER_INFO csbiInfo ;
WORD wOldColorAttrs ;
} ;
inline bool shouldUseColourForPlatform ( ) {
return true ;
}
typedef WindowsConsoleColourCodes PlatformConsoleColourCodes ;
} // end anon namespace
# else // Not Windows - assumed to be POSIX compatible //////////////////////////
2012-10-31 19:04:22 +01:00
# include <unistd.h>
2012-08-09 08:47:30 +02:00
2013-03-11 19:38:29 +01:00
namespace {
using namespace Catch ;
2012-08-16 19:48:50 +02:00
2012-10-31 19:04:22 +01:00
// use POSIX/ ANSI console terminal codes
2012-10-29 21:49:22 +01:00
// Implementation contributed by Adam Strzelecki (http://github.com/nanoant)
// https://github.com/philsquared/Catch/pull/131
2013-03-11 19:38:29 +01:00
struct AnsiConsoleColourCodes : IConsoleColourCodes {
2012-10-29 21:49:22 +01:00
2013-03-11 19:38:29 +01:00
~ AnsiConsoleColourCodes ( ) {
set ( None ) ;
}
2012-10-31 19:04:22 +01:00
2013-03-11 19:38:29 +01:00
void set ( Colours colour ) {
const char colourEscape = ' \033 ' ;
2012-10-29 21:49:22 +01:00
switch ( colour ) {
2013-03-11 19:38:29 +01:00
case FileName :
2012-11-04 22:39:38 +01:00
std : : cout < < colourEscape < < " [0m " ; // white/ normal
2012-10-29 21:49:22 +01:00
break ;
2013-03-11 19:38:29 +01:00
case ResultError :
2013-03-12 19:49:37 +01:00
std : : cout < < colourEscape < < " [1;31m " ; // bold red
2012-10-29 21:49:22 +01:00
break ;
2013-03-11 19:38:29 +01:00
case ResultSuccess :
2013-03-12 19:49:37 +01:00
std : : cout < < colourEscape < < " [1;32m " ; // bold green
2012-10-29 21:49:22 +01:00
break ;
2013-03-11 19:38:29 +01:00
case Error :
std : : cout < < colourEscape < < " [1;31m " ; // bold red
break ;
case Success :
2013-03-12 19:49:37 +01:00
std : : cout < < colourEscape < < " [0;32m " ; // green
2013-03-11 19:38:29 +01:00
break ;
case OriginalExpression :
2012-10-31 19:04:22 +01:00
std : : cout < < colourEscape < < " [0;36m " ; // cyan
2012-10-29 21:49:22 +01:00
break ;
2013-03-11 19:38:29 +01:00
case ReconstructedExpression :
2012-10-31 19:04:22 +01:00
std : : cout < < colourEscape < < " [0;33m " ; // yellow
2012-10-29 21:49:22 +01:00
break ;
2013-03-11 19:38:29 +01:00
case None :
2012-11-04 22:39:38 +01:00
std : : cout < < colourEscape < < " [0m " ; // reset
2012-10-29 21:49:22 +01:00
}
}
2013-03-11 19:38:29 +01:00
} ;
inline bool shouldUseColourForPlatform ( ) {
return isatty ( fileno ( stdout ) ) ;
2012-10-29 21:49:22 +01:00
}
2013-03-11 19:38:29 +01:00
typedef AnsiConsoleColourCodes PlatformConsoleColourCodes ;
2012-10-31 19:04:22 +01:00
} // namespace Catch
2013-03-11 19:38:29 +01:00
# endif // not Windows
2012-10-29 21:49:22 +01:00
2013-03-11 19:38:29 +01:00
namespace {
struct NoConsoleColourCodes : IConsoleColourCodes {
void set ( Colours ) { }
} ;
}
2012-08-16 19:48:50 +02:00
2012-10-31 19:04:22 +01:00
namespace Catch {
2013-03-11 19:38:29 +01:00
TextColour : : TextColour ( Colours colour ) : m_impl ( NULL ) {
static bool s_shouldUseColour = shouldUseColourForPlatform ( ) & &
! isDebuggerActive ( ) ;
if ( s_shouldUseColour )
m_impl = new PlatformConsoleColourCodes ( ) ;
else
m_impl = new NoConsoleColourCodes ( ) ;
2012-08-09 08:47:30 +02:00
2012-08-23 21:08:50 +02:00
if ( colour )
2013-03-11 19:38:29 +01:00
set ( colour ) ;
2012-08-23 21:08:50 +02:00
}
2012-08-09 08:47:30 +02:00
2012-08-23 21:08:50 +02:00
TextColour : : ~ TextColour ( ) {
delete m_impl ;
}
2012-08-09 08:47:30 +02:00
2012-08-23 21:08:50 +02:00
void TextColour : : set ( Colours colour ) {
m_impl - > set ( colour ) ;
}
2012-08-09 08:47:30 +02:00
2012-10-31 19:04:22 +01:00
} // end namespace Catch
2012-08-23 21:08:50 +02:00
// #included from: catch_generators_impl.hpp
# define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED
2012-08-09 08:47:30 +02:00
2012-08-23 21:08:50 +02:00
# include <vector>
# include <string>
# include <map>
2012-08-09 08:47:30 +02:00
2012-08-23 21:08:50 +02:00
namespace Catch {
2012-08-09 08:47:30 +02:00
2012-08-23 21:08:50 +02:00
struct GeneratorInfo : IGeneratorInfo {
2012-08-13 08:46:10 +02:00
2012-08-23 21:08:50 +02:00
GeneratorInfo ( std : : size_t size )
: m_size ( size ) ,
m_currentIndex ( 0 )
{ }
2012-08-13 08:46:10 +02:00
2012-08-23 21:08:50 +02:00
bool moveNext ( ) {
if ( + + m_currentIndex = = m_size ) {
m_currentIndex = 0 ;
return false ;
}
2012-08-13 08:46:10 +02:00
return true ;
2012-08-09 08:47:30 +02:00
}
2012-08-23 21:08:50 +02:00
std : : size_t getCurrentIndex ( ) const {
return m_currentIndex ;
2012-08-09 08:47:30 +02:00
}
2012-08-23 21:08:50 +02:00
std : : size_t m_size ;
std : : size_t m_currentIndex ;
} ;
2012-08-09 08:47:30 +02:00
2012-08-23 21:08:50 +02:00
///////////////////////////////////////////////////////////////////////////
2012-08-09 08:47:30 +02:00
2012-08-23 21:08:50 +02:00
class GeneratorsForTest : public IGeneratorsForTest {
public :
~ GeneratorsForTest ( ) {
deleteAll ( m_generatorsInOrder ) ;
2012-08-13 08:46:10 +02:00
}
2012-08-09 08:47:30 +02:00
2012-08-23 21:08:50 +02:00
IGeneratorInfo & getGeneratorInfo ( const std : : string & 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 ;
2012-08-13 08:46:10 +02:00
}
2012-08-09 08:47:30 +02:00
2012-08-23 21:08:50 +02: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 ;
}
return false ;
2012-08-13 08:46:10 +02:00
}
2012-08-09 08:47:30 +02:00
2012-08-13 08:46:10 +02:00
private :
2012-08-23 21:08:50 +02:00
std : : map < std : : string , IGeneratorInfo * > m_generatorsByName ;
std : : vector < IGeneratorInfo * > m_generatorsInOrder ;
} ;
2012-08-09 08:47:30 +02:00
2012-08-23 21:08:50 +02:00
IGeneratorsForTest * createGeneratorsForTest ( )
{
return new GeneratorsForTest ( ) ;
}
2012-08-09 08:47:30 +02:00
2012-08-23 21:08:50 +02:00
} // end namespace Catch
2012-08-09 08:47:30 +02:00
2012-10-28 13:07:17 +01:00
// #included from: catch_assertionresult.hpp
# define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED
2012-08-09 08:47:30 +02:00
2012-08-23 21:08:50 +02:00
namespace Catch {
2012-08-13 08:46:10 +02:00
2012-11-13 10:44:52 +01:00
AssertionInfo : : AssertionInfo ( const std : : string & _macroName ,
const SourceLineInfo & _lineInfo ,
const std : : string & _capturedExpression ,
ResultDisposition : : Flags _resultDisposition )
: macroName ( _macroName ) ,
lineInfo ( _lineInfo ) ,
capturedExpression ( _capturedExpression ) ,
resultDisposition ( _resultDisposition )
{
if ( shouldNegate ( resultDisposition ) )
capturedExpression = " ! " + _capturedExpression ;
}
2012-10-28 13:07:17 +01:00
AssertionResult : : AssertionResult ( ) { }
2012-08-09 08:47:30 +02:00
2012-10-28 13:07:17 +01:00
AssertionResult : : AssertionResult ( const AssertionInfo & info , const AssertionResultData & data )
: m_info ( info ) ,
m_resultData ( data )
{ }
2012-08-09 08:47:30 +02:00
2012-10-28 13:07:17 +01:00
AssertionResult : : ~ AssertionResult ( ) { }
2012-08-09 08:47:30 +02:00
2012-11-13 10:44:52 +01:00
// Result was a success
bool AssertionResult : : succeeded ( ) const {
return Catch : : isOk ( m_resultData . resultType ) ;
}
// Result was a success, or failure is suppressed
bool AssertionResult : : isOk ( ) const {
return Catch : : isOk ( m_resultData . resultType ) | | shouldSuppressFailure ( m_info . resultDisposition ) ;
2012-08-23 21:08:50 +02:00
}
2012-08-09 08:47:30 +02:00
2012-10-28 13:07:17 +01:00
ResultWas : : OfType AssertionResult : : getResultType ( ) const {
return m_resultData . resultType ;
2012-08-23 21:08:50 +02:00
}
2012-08-09 08:47:30 +02:00
2012-10-28 13:07:17 +01:00
bool AssertionResult : : hasExpression ( ) const {
return ! m_info . capturedExpression . empty ( ) ;
2012-08-23 21:08:50 +02:00
}
2012-08-09 08:47:30 +02:00
2012-10-28 13:07:17 +01:00
bool AssertionResult : : hasMessage ( ) const {
return ! m_resultData . message . empty ( ) ;
2012-08-23 21:08:50 +02:00
}
2012-08-09 08:47:30 +02:00
2012-10-28 13:07:17 +01:00
std : : string AssertionResult : : getExpression ( ) const {
return m_info . capturedExpression ;
2012-08-23 21:08:50 +02:00
}
2012-08-09 08:47:30 +02:00
2012-10-28 13:07:17 +01:00
bool AssertionResult : : hasExpandedExpression ( ) const {
2012-10-09 12:48:55 +02:00
return hasExpression ( ) & & getExpandedExpression ( ) ! = getExpression ( ) ;
2012-08-23 21:08:50 +02:00
}
2012-08-16 19:48:50 +02:00
2012-10-28 13:07:17 +01:00
std : : string AssertionResult : : getExpandedExpression ( ) const {
return m_resultData . reconstructedExpression ;
2012-08-16 19:48:50 +02:00
}
2012-10-28 13:07:17 +01:00
std : : string AssertionResult : : getMessage ( ) const {
return m_resultData . message ;
2012-08-23 21:08:50 +02:00
}
2012-10-28 13:07:17 +01:00
SourceLineInfo AssertionResult : : getSourceInfo ( ) const {
return m_info . lineInfo ;
2012-08-23 21:08:50 +02:00
}
2012-10-28 13:07:17 +01:00
std : : string AssertionResult : : getTestMacroName ( ) const {
return m_info . macroName ;
2012-08-16 19:48:50 +02:00
}
2012-08-23 21:08:50 +02:00
} // end namespace Catch
2012-08-16 19:48:50 +02:00
2012-10-28 13:07:17 +01:00
// #included from: catch_expressionresult_builder.hpp
# define TWOBLUECUBES_CATCH_EXPRESSIONRESULT_BUILDER_HPP_INCLUDED
2012-08-09 08:47:30 +02:00
2012-10-28 13:07:17 +01:00
# include <assert.h>
2012-08-09 08:47:30 +02:00
2012-10-28 13:07:17 +01:00
namespace Catch {
2012-10-04 09:14:48 +02:00
2012-10-28 13:07:17 +01:00
ExpressionResultBuilder : : ExpressionResultBuilder ( ResultWas : : OfType resultType ) {
m_data . resultType = resultType ;
2012-10-09 12:48:55 +02:00
}
2012-10-28 13:07:17 +01:00
ExpressionResultBuilder : : ExpressionResultBuilder ( const ExpressionResultBuilder & other )
: m_data ( other . m_data ) ,
m_exprComponents ( other . m_exprComponents )
{
m_stream < < other . m_stream . str ( ) ;
2012-10-09 12:48:55 +02:00
}
2012-10-28 13:07:17 +01:00
ExpressionResultBuilder & ExpressionResultBuilder : : operator = ( const ExpressionResultBuilder & other ) {
m_data = other . m_data ;
m_exprComponents = other . m_exprComponents ;
m_stream . str ( " " ) ;
m_stream < < other . m_stream . str ( ) ;
2012-10-04 09:14:48 +02:00
return * this ;
2012-08-09 08:47:30 +02:00
}
2012-10-28 13:07:17 +01:00
ExpressionResultBuilder & ExpressionResultBuilder : : setResultType ( ResultWas : : OfType result ) {
m_data . resultType = result ;
2012-10-04 09:14:48 +02:00
return * this ;
2012-08-09 08:47:30 +02:00
}
2012-10-28 13:07:17 +01:00
ExpressionResultBuilder & ExpressionResultBuilder : : setResultType ( bool result ) {
m_data . resultType = result ? ResultWas : : Ok : ResultWas : : ExpressionFailed ;
2012-10-09 12:48:55 +02:00
return * this ;
}
2012-11-10 19:46:39 +01:00
ExpressionResultBuilder & ExpressionResultBuilder : : endExpression ( ResultDisposition : : Flags resultDisposition ) {
2012-11-13 10:44:52 +01:00
m_exprComponents . shouldNegate = shouldNegate ( resultDisposition ) ;
2012-10-04 09:14:48 +02:00
return * this ;
2012-08-09 08:47:30 +02:00
}
2012-10-28 13:07:17 +01:00
ExpressionResultBuilder & ExpressionResultBuilder : : setLhs ( const std : : string & lhs ) {
m_exprComponents . lhs = lhs ;
2012-10-04 09:14:48 +02:00
return * this ;
2012-08-23 21:08:50 +02:00
}
2012-10-28 13:07:17 +01:00
ExpressionResultBuilder & ExpressionResultBuilder : : setRhs ( const std : : string & rhs ) {
m_exprComponents . rhs = rhs ;
2012-10-04 09:14:48 +02:00
return * this ;
2012-08-23 21:08:50 +02:00
}
2012-10-28 13:07:17 +01:00
ExpressionResultBuilder & ExpressionResultBuilder : : setOp ( const std : : string & op ) {
m_exprComponents . op = op ;
2012-10-04 09:14:48 +02:00
return * this ;
}
2012-10-28 13:07:17 +01:00
AssertionResult ExpressionResultBuilder : : buildResult ( const AssertionInfo & info ) const
2012-10-09 12:48:55 +02:00
{
2012-10-28 13:07:17 +01:00
assert ( m_data . resultType ! = ResultWas : : Unknown ) ;
AssertionResultData data = m_data ;
// Flip bool results if shouldNegate is set
if ( m_exprComponents . shouldNegate & & data . resultType = = ResultWas : : Ok )
data . resultType = ResultWas : : ExpressionFailed ;
else if ( m_exprComponents . shouldNegate & & data . resultType = = ResultWas : : ExpressionFailed )
data . resultType = ResultWas : : Ok ;
data . message = m_stream . str ( ) ;
data . reconstructedExpression = reconstructExpression ( info ) ;
if ( m_exprComponents . shouldNegate ) {
if ( m_exprComponents . op = = " " )
2012-10-09 12:48:55 +02:00
data . reconstructedExpression = " ! " + data . reconstructedExpression ;
2012-10-28 13:07:17 +01:00
else
2012-10-09 12:48:55 +02:00
data . reconstructedExpression = " !( " + data . reconstructedExpression + " ) " ;
}
2012-10-28 13:07:17 +01:00
return AssertionResult ( info , data ) ;
}
std : : string ExpressionResultBuilder : : reconstructExpression ( const AssertionInfo & info ) const {
if ( m_exprComponents . op = = " " )
return m_exprComponents . lhs . empty ( ) ? info . capturedExpression : m_exprComponents . op + m_exprComponents . lhs ;
else if ( m_exprComponents . op = = " matches " )
return m_exprComponents . lhs + " " + m_exprComponents . rhs ;
else if ( m_exprComponents . op ! = " ! " ) {
2013-03-04 12:19:15 +01:00
if ( m_exprComponents . lhs . size ( ) + m_exprComponents . rhs . size ( ) < 40 )
2012-10-28 13:07:17 +01:00
return m_exprComponents . lhs + " " + m_exprComponents . op + " " + m_exprComponents . rhs ;
2012-10-09 12:48:55 +02:00
else
2013-03-04 12:19:15 +01:00
return m_exprComponents . lhs + " \n " + m_exprComponents . op + " \n " + m_exprComponents . rhs ;
2012-10-09 12:48:55 +02:00
}
else
2012-10-28 13:07:17 +01:00
return " {can't expand - use " + info . macroName + " _FALSE( " + info . capturedExpression . substr ( 1 ) + " ) instead of " + info . macroName + " ( " + info . capturedExpression + " ) for better diagnostics} " ;
2012-08-09 08:47:30 +02:00
}
2011-05-24 09:23:02 +02:00
} // end namespace Catch
2012-08-23 21:08:50 +02:00
// #included from: catch_test_case_info.hpp
2012-09-17 07:42:29 +02:00
# define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED
2011-05-24 09:23:02 +02:00
2012-05-16 16:09:17 +02:00
namespace Catch {
2012-12-02 00:57:18 +01:00
TestCase makeTestCase ( ITestCase * _testCase ,
const std : : string & _className ,
const std : : string & _name ,
const std : : string & _descOrTags ,
const SourceLineInfo & _lineInfo )
2012-09-15 18:53:27 +02:00
{
2012-12-02 00:57:18 +01:00
std : : string desc = _descOrTags ;
bool isHidden ( startsWith ( _name , " ./ " ) ) ;
std : : set < std : : string > tags ;
TagExtracter ( tags ) . parse ( desc ) ;
if ( tags . find ( " hide " ) ! = tags . end ( ) )
isHidden = true ;
TestCaseInfo info ( _name , _className , desc , tags , isHidden , _lineInfo ) ;
return TestCase ( _testCase , info ) ;
}
TestCaseInfo : : TestCaseInfo ( const std : : string & _name ,
const std : : string & _className ,
const std : : string & _description ,
const std : : set < std : : string > & _tags ,
bool _isHidden ,
const SourceLineInfo & _lineInfo )
: name ( _name ) ,
className ( _className ) ,
description ( _description ) ,
tags ( _tags ) ,
2012-12-06 09:44:51 +01:00
lineInfo ( _lineInfo ) ,
isHidden ( _isHidden )
2012-08-23 21:08:50 +02:00
{ }
2012-08-09 08:47:30 +02:00
2012-12-02 00:57:18 +01:00
TestCaseInfo : : TestCaseInfo ( const TestCaseInfo & other )
: name ( other . name ) ,
className ( other . className ) ,
description ( other . description ) ,
tags ( other . tags ) ,
2012-12-06 09:44:51 +01:00
lineInfo ( other . lineInfo ) ,
isHidden ( other . isHidden )
2012-08-23 21:08:50 +02:00
{ }
2012-08-16 19:48:50 +02:00
2012-12-02 00:57:18 +01:00
TestCase : : TestCase ( ITestCase * testCase , const TestCaseInfo & info ) : TestCaseInfo ( info ) , test ( testCase ) { }
TestCase : : TestCase ( const TestCase & other )
: TestCaseInfo ( other ) ,
test ( other . test )
2012-08-23 21:08:50 +02:00
{ }
2012-08-09 08:47:30 +02:00
2012-12-02 00:57:18 +01:00
TestCase TestCase : : withName ( const std : : string & _newName ) const {
TestCase other ( * this ) ;
other . name = _newName ;
return other ;
2012-08-23 21:08:50 +02:00
}
2012-08-16 19:48:50 +02:00
2012-12-02 00:57:18 +01:00
void TestCase : : invoke ( ) const {
test - > invoke ( ) ;
2012-08-23 21:08:50 +02:00
}
2011-05-24 09:23:02 +02:00
2012-12-02 00:57:18 +01:00
bool TestCase : : isHidden ( ) const {
return TestCaseInfo : : isHidden ;
2012-09-15 18:53:27 +02:00
}
2012-12-02 00:57:18 +01:00
bool TestCase : : hasTag ( const std : : string & tag ) const {
return tags . find ( tag ) ! = tags . end ( ) ;
2012-09-15 18:53:27 +02:00
}
2012-12-02 00:57:18 +01:00
bool TestCase : : matchesTags ( const std : : string & tagPattern ) const {
2012-09-24 09:30:13 +02:00
TagExpression exp ;
TagExpressionParser ( exp ) . parse ( tagPattern ) ;
2012-12-02 00:57:18 +01:00
return exp . matches ( tags ) ;
2012-09-24 09:30:13 +02:00
}
2012-12-02 00:57:18 +01:00
const std : : set < std : : string > & TestCase : : getTags ( ) const {
return tags ;
2012-08-23 21:08:50 +02:00
}
2011-05-24 09:23:02 +02:00
2012-12-02 00:57:18 +01:00
void TestCase : : swap ( TestCase & other ) {
test . swap ( other . test ) ;
className . swap ( other . className ) ;
name . swap ( other . name ) ;
description . swap ( other . description ) ;
std : : swap ( lineInfo , other . lineInfo ) ;
2012-08-23 21:08:50 +02:00
}
2011-05-24 09:23:02 +02:00
2012-12-02 00:57:18 +01:00
bool TestCase : : operator = = ( const TestCase & other ) const {
return test . get ( ) = = other . test . get ( ) & &
name = = other . name & &
className = = other . className ;
2012-08-23 21:08:50 +02:00
}
2011-05-24 09:23:02 +02:00
2012-12-02 00:57:18 +01:00
bool TestCase : : operator < ( const TestCase & other ) const {
return name < other . name ;
2012-08-23 21:08:50 +02:00
}
2012-12-02 00:57:18 +01:00
TestCase & TestCase : : operator = ( const TestCase & other ) {
TestCase temp ( other ) ;
2012-08-23 21:08:50 +02:00
swap ( temp ) ;
return * this ;
}
2012-09-24 09:30:13 +02:00
2012-12-02 00:57:18 +01:00
const TestCaseInfo & TestCase : : getTestCaseInfo ( ) const
{
return * this ;
}
2012-09-24 09:30:13 +02:00
} // end namespace Catch
2011-05-24 09:23:02 +02:00
2012-11-15 23:15:41 +01:00
// #included from: catch_version.hpp
# define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED
namespace Catch {
// These numbers are maintained by a script
2013-03-12 19:49:37 +01:00
Version libraryVersion ( 0 , 9 , 24 , " integration " ) ;
2012-11-15 23:15:41 +01:00
}
2013-01-16 10:44:43 +01:00
// #included from: catch_line_wrap.hpp
# define TWOBLUECUBES_CATCH_LINE_WRAP_HPP_INCLUDED
namespace Catch {
namespace {
inline void addIndent ( std : : ostream & os , std : : size_t indent ) {
while ( indent - - > 0 )
os < < ' ' ;
}
inline void recursivelyWrapLine ( std : : ostream & os , std : : string paragraph , std : : size_t columns , std : : size_t indent ) {
std : : size_t width = columns - indent ;
std : : size_t tab = 0 ;
std : : size_t wrapPoint = width ;
for ( std : : size_t pos = 0 ; pos < paragraph . size ( ) ; + + pos ) {
if ( pos = = width ) {
addIndent ( os , indent ) ;
os < < paragraph . substr ( 0 , wrapPoint ) < < " \n " ;
return recursivelyWrapLine ( os , paragraph . substr ( wrapPoint + 1 ) , columns , indent + tab ) ;
}
if ( paragraph [ pos ] = = ' \t ' ) {
tab = pos ;
paragraph = paragraph . substr ( 0 , tab ) + paragraph . substr ( tab + 1 ) ;
pos - - ;
}
else if ( paragraph [ pos ] = = ' ' ) {
wrapPoint = pos ;
}
}
addIndent ( os , indent ) ;
os < < paragraph ;
}
}
void wrapLongStrings ( std : : ostream & stream , const std : : string & str , std : : size_t columns , std : : size_t indent ) {
std : : string : : size_type pos = 0 ;
std : : string : : size_type newline = str . find_first_of ( ' \n ' ) ;
while ( newline ! = std : : string : : npos ) {
std : : string paragraph = str . substr ( pos , newline - pos ) ;
recursivelyWrapLine ( stream , paragraph , columns , indent ) ;
stream < < " \n " ;
pos = newline + 1 ;
newline = str . find_first_of ( ' \n ' , pos ) ;
}
if ( pos ! = str . size ( ) )
recursivelyWrapLine ( stream , str . substr ( pos , str . size ( ) - pos ) , columns , indent ) ;
}
std : : string wrapLongStrings ( const std : : string & str , std : : size_t columns , std : : size_t indent ) {
std : : ostringstream oss ;
wrapLongStrings ( oss , str , columns , indent ) ;
return oss . str ( ) ;
}
} // end namespace Catch
2013-02-02 21:37:58 +01:00
// #included from: catch_message.hpp
# define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED
namespace Catch {
MessageInfo : : MessageInfo ( std : : string const & _macroName ,
SourceLineInfo const & _lineInfo ,
ResultWas : : OfType _type )
: macroName ( _macroName ) ,
lineInfo ( _lineInfo ) ,
type ( _type ) ,
sequence ( + + globalCount )
{ }
// This may need protecting if threading support is added
unsigned int MessageInfo : : globalCount = 0 ;
////////////////////////////////////////////////////////////////////////////
MessageBuilder : : MessageBuilder ( std : : string const & _macroName ,
SourceLineInfo const & _lineInfo ,
ResultWas : : OfType _type )
: MessageInfo ( _macroName , _lineInfo , _type )
{ }
MessageInfo MessageBuilder : : build ( ) const {
MessageInfo message = * this ;
message . message = stream . str ( ) ;
return message ;
}
////////////////////////////////////////////////////////////////////////////
ScopedMessageBuilder : : ScopedMessageBuilder
( std : : string const & _macroName ,
SourceLineInfo const & _lineInfo ,
ResultWas : : OfType _type )
: MessageBuilder ( _macroName , _lineInfo , _type )
{ }
ScopedMessageBuilder : : ~ ScopedMessageBuilder ( ) {
getResultCapture ( ) . popScopedMessage ( * this ) ;
}
} // end namespace Catch
2012-08-23 21:08:50 +02:00
// #included from: ../reporters/catch_reporter_basic.hpp
# define TWOBLUECUBES_CATCH_REPORTER_BASIC_HPP_INCLUDED
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
// #included from: ../internal/catch_reporter_registrars.hpp
# define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
2012-08-16 19:48:50 +02:00
2012-08-23 21:08:50 +02:00
namespace Catch {
2011-05-24 09:23:02 +02:00
2012-12-02 00:57:18 +01:00
template < typename T >
class LegacyReporterRegistrar {
class ReporterFactory : public IReporterFactory {
virtual IStreamingReporter * create ( const ReporterConfig & config ) const {
return new LegacyReporterAdapter ( new T ( config ) , config ) ;
}
virtual std : : string getDescription ( ) const {
return T : : getDescription ( ) ;
}
} ;
public :
LegacyReporterRegistrar ( const std : : string & name ) {
getMutableRegistryHub ( ) . registerReporter ( name , new ReporterFactory ( ) ) ;
}
} ;
2012-08-23 21:08:50 +02:00
template < typename T >
class ReporterRegistrar {
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
class ReporterFactory : public IReporterFactory {
2012-08-09 08:47:30 +02:00
2012-12-02 00:57:18 +01: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 ( const ReporterConfig & config ) const {
2012-08-23 21:08:50 +02:00
return new T ( config ) ;
}
2012-08-09 08:47:30 +02:00
2012-08-23 21:08:50 +02:00
virtual std : : string getDescription ( ) const {
return T : : getDescription ( ) ;
}
} ;
2012-08-09 08:47:30 +02:00
2012-08-23 21:08:50 +02:00
public :
2012-08-09 08:47:30 +02:00
2012-08-23 21:08:50 +02:00
ReporterRegistrar ( const std : : string & name ) {
getMutableRegistryHub ( ) . registerReporter ( name , new ReporterFactory ( ) ) ;
}
} ;
}
2012-08-09 08:47:30 +02:00
2012-12-02 00:57:18 +01:00
# define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \
Catch : : LegacyReporterRegistrar < reporterType > catch_internal_RegistrarFor # # reporterType ( name ) ;
2012-08-23 21:08:50 +02:00
# define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \
Catch : : ReporterRegistrar < reporterType > catch_internal_RegistrarFor # # reporterType ( name ) ;
2012-08-09 08:47:30 +02:00
namespace Catch {
2012-08-23 21:08:50 +02:00
class BasicReporter : public SharedImpl < IReporter > {
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
struct SpanInfo {
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
SpanInfo ( )
: emitted ( false )
{ }
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
SpanInfo ( const std : : string & spanName )
: name ( spanName ) ,
emitted ( false )
{ }
2012-08-09 08:47:30 +02:00
2012-08-23 21:08:50 +02:00
SpanInfo ( const SpanInfo & other )
: name ( other . name ) ,
emitted ( other . emitted )
{ }
2012-08-09 08:47:30 +02:00
2012-08-23 21:08:50 +02:00
std : : string name ;
bool emitted ;
} ;
2012-08-09 08:47:30 +02:00
public :
2012-08-23 21:08:50 +02:00
BasicReporter ( const ReporterConfig & config )
: m_config ( config ) ,
m_firstSectionInTestCase ( true ) ,
m_aborted ( false )
{ }
virtual ~ BasicReporter ( ) ;
static std : : string getDescription ( ) {
return " Reports test results as lines of text " ;
2011-05-24 09:23:02 +02:00
}
2012-08-23 21:08:50 +02:00
private :
void ReportCounts ( const std : : string & label , const Counts & counts , const std : : string & allPrefix = " All " ) {
if ( counts . passed )
2012-12-02 00:57:18 +01:00
m_config . stream ( ) < < counts . failed < < " of " < < counts . total ( ) < < " " < < label < < " s failed " ;
2012-08-23 21:08:50 +02:00
else
2012-12-02 00:57:18 +01:00
m_config . stream ( ) < < ( counts . failed > 1 ? allPrefix : " " ) < < pluralise ( counts . failed , label ) < < " failed " ;
2011-05-24 09:23:02 +02:00
}
2012-08-23 21:08:50 +02:00
void ReportCounts ( const Totals & totals , const std : : string & allPrefix = " All " ) {
if ( totals . assertions . total ( ) = = 0 ) {
2012-12-02 00:57:18 +01:00
m_config . stream ( ) < < " No tests ran " ;
2012-08-09 08:47:30 +02:00
}
2012-08-23 21:08:50 +02:00
else if ( totals . assertions . failed ) {
TextColour colour ( TextColour : : ResultError ) ;
ReportCounts ( " test case " , totals . testCases , allPrefix ) ;
if ( totals . testCases . failed > 0 ) {
2012-12-02 00:57:18 +01:00
m_config . stream ( ) < < " ( " ;
2012-08-23 21:08:50 +02:00
ReportCounts ( " assertion " , totals . assertions , allPrefix ) ;
2012-12-02 00:57:18 +01:00
m_config . stream ( ) < < " ) " ;
2012-08-23 21:08:50 +02:00
}
2012-08-09 08:47:30 +02:00
}
2012-08-23 21:08:50 +02:00
else {
TextColour colour ( TextColour : : ResultSuccess ) ;
2012-12-02 00:57:18 +01:00
m_config . stream ( ) < < allPrefix < < " tests passed ( "
2012-08-23 21:08:50 +02:00
< < pluralise ( totals . assertions . passed , " assertion " ) < < " in "
< < pluralise ( totals . testCases . passed , " test case " ) < < " ) " ;
2011-05-24 09:23:02 +02:00
}
}
2012-08-23 21:08:50 +02:00
private : // IReporter
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
virtual bool shouldRedirectStdout ( ) const {
return false ;
2011-05-24 09:23:02 +02:00
}
2012-08-23 21:08:50 +02:00
virtual void StartTesting ( ) {
m_testingSpan = SpanInfo ( ) ;
}
2012-02-17 20:50:59 +01:00
2012-08-23 21:08:50 +02:00
virtual void Aborted ( ) {
m_aborted = true ;
}
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
virtual void EndTesting ( const Totals & totals ) {
// Output the overall test results even if "Started Testing" was not emitted
if ( m_aborted ) {
2012-12-02 00:57:18 +01:00
m_config . stream ( ) < < " \n [Testing aborted. " ;
2012-08-23 21:08:50 +02:00
ReportCounts ( totals , " The first " ) ;
2012-08-09 08:47:30 +02:00
}
2012-08-23 21:08:50 +02:00
else {
2012-12-02 00:57:18 +01:00
m_config . stream ( ) < < " \n [Testing completed. " ;
2012-08-23 21:08:50 +02:00
ReportCounts ( totals ) ;
2012-08-09 08:47:30 +02:00
}
2012-12-02 00:57:18 +01:00
m_config . stream ( ) < < " ] \n " < < std : : endl ;
2011-05-24 09:23:02 +02:00
}
2012-08-23 21:08:50 +02:00
virtual void StartGroup ( const std : : string & groupName ) {
m_groupSpan = groupName ;
}
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
virtual void EndGroup ( const std : : string & groupName , const Totals & totals ) {
if ( m_groupSpan . emitted & & ! groupName . empty ( ) ) {
2012-12-02 00:57:18 +01:00
m_config . stream ( ) < < " [End of group: ' " < < groupName < < " '. " ;
2012-08-23 21:08:50 +02:00
ReportCounts ( totals ) ;
2012-12-02 00:57:18 +01:00
m_config . stream ( ) < < " ] \n " < < std : : endl ;
2012-08-23 21:08:50 +02:00
m_groupSpan = SpanInfo ( ) ;
}
}
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
virtual void StartTestCase ( const TestCaseInfo & testInfo ) {
2012-12-02 00:57:18 +01:00
m_testSpan = testInfo . name ;
2012-08-23 21:08:50 +02:00
}
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
virtual void StartSection ( const std : : string & sectionName , const std : : string & ) {
m_sectionSpans . push_back ( SpanInfo ( sectionName ) ) ;
}
2011-05-24 09:23:02 +02:00
2012-08-31 09:10:36 +02:00
virtual void NoAssertionsInSection ( const std : : string & sectionName ) {
2012-09-07 18:52:35 +02:00
startSpansLazily ( ) ;
2012-08-31 09:10:36 +02:00
TextColour colour ( TextColour : : ResultError ) ;
2012-12-02 00:57:18 +01:00
m_config . stream ( ) < < " \n No assertions in section, ' " < < sectionName < < " ' \n " < < std : : endl ;
2012-08-31 09:10:36 +02:00
}
virtual void NoAssertionsInTestCase ( const std : : string & testName ) {
2012-09-07 18:52:35 +02:00
startSpansLazily ( ) ;
2012-08-31 09:10:36 +02:00
TextColour colour ( TextColour : : ResultError ) ;
2012-12-02 00:57:18 +01:00
m_config . stream ( ) < < " \n No assertions in test case, ' " < < testName < < " ' \n " < < std : : endl ;
2012-08-31 09:10:36 +02:00
}
2012-08-23 21:08:50 +02:00
virtual void EndSection ( const std : : string & sectionName , const Counts & assertions ) {
2012-08-31 09:10:36 +02:00
2012-08-23 21:08:50 +02:00
SpanInfo & sectionSpan = m_sectionSpans . back ( ) ;
if ( sectionSpan . emitted & & ! sectionSpan . name . empty ( ) ) {
2012-12-02 00:57:18 +01:00
m_config . stream ( ) < < " [End of section: ' " < < sectionName < < " ' " ;
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
if ( assertions . failed ) {
TextColour colour ( TextColour : : ResultError ) ;
ReportCounts ( " assertion " , assertions ) ;
}
else {
TextColour colour ( TextColour : : ResultSuccess ) ;
2012-12-02 00:57:18 +01:00
m_config . stream ( ) < < ( assertions . passed > 1 ? " All " : " " )
2012-08-23 21:08:50 +02:00
< < pluralise ( assertions . passed , " assertion " ) < < " passed " ;
}
2012-12-02 00:57:18 +01:00
m_config . stream ( ) < < " ] \n " < < std : : endl ;
2012-08-23 21:08:50 +02:00
}
m_sectionSpans . pop_back ( ) ;
}
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
virtual void Result ( const AssertionResult & assertionResult ) {
2012-12-02 00:57:18 +01:00
if ( ! m_config . includeSuccessfulResults ( ) & & assertionResult . getResultType ( ) = = ResultWas : : Ok )
2012-08-23 21:08:50 +02:00
return ;
2012-08-09 08:47:30 +02:00
2012-09-07 18:52:35 +02:00
startSpansLazily ( ) ;
2012-08-09 08:47:30 +02:00
2012-10-28 13:07:17 +01:00
if ( ! assertionResult . getSourceInfo ( ) . empty ( ) ) {
2012-08-23 21:08:50 +02:00
TextColour colour ( TextColour : : FileName ) ;
2013-01-16 10:44:43 +01:00
m_config . stream ( ) < < assertionResult . getSourceInfo ( ) < < " : " ;
2012-08-23 21:08:50 +02:00
}
2012-08-09 08:47:30 +02:00
2012-10-28 13:07:17 +01:00
if ( assertionResult . hasExpression ( ) ) {
2012-08-23 21:08:50 +02:00
TextColour colour ( TextColour : : OriginalExpression ) ;
2012-12-02 00:57:18 +01:00
m_config . stream ( ) < < assertionResult . getExpression ( ) ;
2012-11-13 10:44:52 +01:00
if ( assertionResult . succeeded ( ) ) {
2012-08-23 21:08:50 +02:00
TextColour successColour ( TextColour : : Success ) ;
2012-12-02 00:57:18 +01:00
m_config . stream ( ) < < " succeeded " ;
2012-08-23 21:08:50 +02:00
}
else {
TextColour errorColour ( TextColour : : Error ) ;
2012-12-02 00:57:18 +01:00
m_config . stream ( ) < < " failed " ;
2012-11-13 10:44:52 +01:00
if ( assertionResult . isOk ( ) ) {
TextColour okAnywayColour ( TextColour : : Success ) ;
2012-12-02 00:57:18 +01:00
m_config . stream ( ) < < " - but was ok " ;
2012-11-13 10:44:52 +01:00
}
2012-08-23 21:08:50 +02:00
}
}
2012-10-28 13:07:17 +01:00
switch ( assertionResult . getResultType ( ) ) {
2012-08-23 21:08:50 +02:00
case ResultWas : : ThrewException :
2012-10-31 19:04:22 +01:00
{
TextColour colour ( TextColour : : Error ) ;
if ( assertionResult . hasExpression ( ) )
2012-12-02 00:57:18 +01:00
m_config . stream ( ) < < " with unexpected " ;
2012-10-31 19:04:22 +01:00
else
2012-12-02 00:57:18 +01:00
m_config . stream ( ) < < " Unexpected " ;
m_config . stream ( ) < < " exception with message: ' " < < assertionResult . getMessage ( ) < < " ' " ;
2012-10-31 19:04:22 +01:00
}
2012-08-23 21:08:50 +02:00
break ;
case ResultWas : : DidntThrowException :
2012-10-31 19:04:22 +01:00
{
TextColour colour ( TextColour : : Error ) ;
if ( assertionResult . hasExpression ( ) )
2012-12-02 00:57:18 +01:00
m_config . stream ( ) < < " because no exception was thrown where one was expected " ;
2012-10-31 19:04:22 +01:00
else
2012-12-02 00:57:18 +01:00
m_config . stream ( ) < < " No exception thrown where one was expected " ;
2012-10-31 19:04:22 +01:00
}
2012-08-23 21:08:50 +02:00
break ;
case ResultWas : : Info :
2012-10-31 19:04:22 +01:00
{
TextColour colour ( TextColour : : ReconstructedExpression ) ;
streamVariableLengthText ( " info " , assertionResult . getMessage ( ) ) ;
}
2012-08-23 21:08:50 +02:00
break ;
case ResultWas : : Warning :
2012-10-31 19:04:22 +01:00
{
TextColour colour ( TextColour : : ReconstructedExpression ) ;
streamVariableLengthText ( " warning " , assertionResult . getMessage ( ) ) ;
}
2012-08-23 21:08:50 +02:00
break ;
case ResultWas : : ExplicitFailure :
2012-10-31 19:04:22 +01:00
{
TextColour colour ( TextColour : : Error ) ;
2012-12-02 00:57:18 +01:00
m_config . stream ( ) < < " failed with message: ' " < < assertionResult . getMessage ( ) < < " ' " ;
2012-10-31 19:04:22 +01:00
}
2012-08-23 21:08:50 +02:00
break ;
case ResultWas : : Unknown : // These cases are here to prevent compiler warnings
case ResultWas : : Ok :
case ResultWas : : FailureBit :
case ResultWas : : ExpressionFailed :
case ResultWas : : Exception :
2012-10-28 13:07:17 +01:00
if ( ! assertionResult . hasExpression ( ) ) {
2012-11-13 10:44:52 +01:00
if ( assertionResult . succeeded ( ) ) {
2012-08-23 21:08:50 +02:00
TextColour colour ( TextColour : : Success ) ;
2012-12-02 00:57:18 +01:00
m_config . stream ( ) < < " succeeded " ;
2012-08-23 21:08:50 +02:00
}
else {
TextColour colour ( TextColour : : Error ) ;
2012-12-02 00:57:18 +01:00
m_config . stream ( ) < < " failed " ;
2012-11-13 10:44:52 +01:00
if ( assertionResult . isOk ( ) ) {
TextColour okAnywayColour ( TextColour : : Success ) ;
2012-12-02 00:57:18 +01:00
m_config . stream ( ) < < " - but was ok " ;
2012-11-13 10:44:52 +01:00
}
2012-08-23 21:08:50 +02:00
}
}
2012-11-21 19:06:13 +01:00
if ( assertionResult . hasMessage ( ) ) {
2012-12-02 00:57:18 +01:00
m_config . stream ( ) < < " \n " ;
2012-11-21 19:06:13 +01:00
TextColour colour ( TextColour : : ReconstructedExpression ) ;
streamVariableLengthText ( " with message " , assertionResult . getMessage ( ) ) ;
}
2012-08-23 21:08:50 +02:00
break ;
}
2012-08-09 08:47:30 +02:00
2012-10-28 13:07:17 +01:00
if ( assertionResult . hasExpandedExpression ( ) ) {
2012-12-02 00:57:18 +01:00
m_config . stream ( ) < < " for: " ;
2012-10-29 21:49:22 +01:00
if ( assertionResult . getExpandedExpression ( ) . size ( ) > 40 ) {
2012-12-02 00:57:18 +01:00
m_config . stream ( ) < < " \n " ;
2012-10-29 21:49:22 +01:00
if ( assertionResult . getExpandedExpression ( ) . size ( ) < 70 )
2012-12-02 00:57:18 +01:00
m_config . stream ( ) < < " \t " ;
2012-10-29 21:49:22 +01:00
}
2012-08-23 21:08:50 +02:00
TextColour colour ( TextColour : : ReconstructedExpression ) ;
2012-12-02 00:57:18 +01:00
m_config . stream ( ) < < assertionResult . getExpandedExpression ( ) ;
2012-08-23 21:08:50 +02:00
}
2012-12-02 00:57:18 +01:00
m_config . stream ( ) < < std : : endl ;
2012-08-23 21:08:50 +02:00
}
2012-08-09 08:47:30 +02:00
2012-08-23 21:08:50 +02:00
virtual void EndTestCase ( const TestCaseInfo & testInfo ,
const Totals & totals ,
const std : : string & stdOut ,
const std : : string & stdErr ) {
if ( ! stdOut . empty ( ) ) {
2012-09-07 18:52:35 +02:00
startSpansLazily ( ) ;
2012-08-23 21:08:50 +02:00
streamVariableLengthText ( " stdout " , stdOut ) ;
}
2012-08-09 08:47:30 +02:00
2012-08-23 21:08:50 +02:00
if ( ! stdErr . empty ( ) ) {
2012-09-07 18:52:35 +02:00
startSpansLazily ( ) ;
2012-08-23 21:08:50 +02:00
streamVariableLengthText ( " stderr " , stdErr ) ;
}
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
if ( m_testSpan . emitted ) {
2012-12-02 00:57:18 +01:00
m_config . stream ( ) < < " [Finished: ' " < < testInfo . name < < " ' " ;
2012-08-23 21:08:50 +02:00
ReportCounts ( totals ) ;
2012-12-02 00:57:18 +01:00
m_config . stream ( ) < < " ] " < < std : : endl ;
2012-08-23 21:08:50 +02:00
}
2012-06-01 20:40:27 +02:00
}
2012-08-23 21:08:50 +02:00
private : // helpers
2012-08-09 08:47:30 +02:00
2012-09-07 18:52:35 +02:00
void startSpansLazily ( ) {
2012-08-23 21:08:50 +02:00
if ( ! m_testingSpan . emitted ) {
2012-12-02 00:57:18 +01:00
if ( m_config . name ( ) . empty ( ) )
m_config . stream ( ) < < " [Started testing] " < < std : : endl ;
2012-08-09 08:47:30 +02:00
else
2012-12-02 00:57:18 +01:00
m_config . stream ( ) < < " [Started testing: " < < m_config . name ( ) < < " ] " < < std : : endl ;
2012-08-23 21:08:50 +02:00
m_testingSpan . emitted = true ;
2012-08-09 08:47:30 +02:00
}
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
if ( ! m_groupSpan . emitted & & ! m_groupSpan . name . empty ( ) ) {
2012-12-02 00:57:18 +01:00
m_config . stream ( ) < < " [Started group: ' " < < m_groupSpan . name < < " '] " < < std : : endl ;
2012-08-23 21:08:50 +02:00
m_groupSpan . emitted = true ;
2012-08-09 08:47:30 +02:00
}
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
if ( ! m_testSpan . emitted ) {
2012-12-02 00:57:18 +01:00
m_config . stream ( ) < < std : : endl < < " [Running: " < < m_testSpan . name < < " ] " < < std : : endl ;
2012-08-23 21:08:50 +02:00
m_testSpan . emitted = true ;
}
2012-08-09 08:47:30 +02:00
2012-08-23 21:08:50 +02:00
if ( ! m_sectionSpans . empty ( ) ) {
SpanInfo & sectionSpan = m_sectionSpans . back ( ) ;
if ( ! sectionSpan . emitted & & ! sectionSpan . name . empty ( ) ) {
if ( m_firstSectionInTestCase ) {
2012-12-02 00:57:18 +01:00
m_config . stream ( ) < < " \n " ;
2012-08-23 21:08:50 +02:00
m_firstSectionInTestCase = false ;
}
std : : vector < SpanInfo > : : iterator it = m_sectionSpans . begin ( ) ;
std : : vector < SpanInfo > : : iterator itEnd = m_sectionSpans . end ( ) ;
for ( ; it ! = itEnd ; + + it ) {
SpanInfo & prevSpan = * it ;
if ( ! prevSpan . emitted & & ! prevSpan . name . empty ( ) ) {
2012-12-02 00:57:18 +01:00
m_config . stream ( ) < < " [Started section: ' " < < prevSpan . name < < " '] " < < std : : endl ;
2012-08-23 21:08:50 +02:00
prevSpan . emitted = true ;
}
}
}
}
2012-08-09 08:47:30 +02:00
}
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
void streamVariableLengthText ( const std : : string & prefix , const std : : string & text ) {
std : : string trimmed = trim ( text ) ;
if ( trimmed . find_first_of ( " \r \n " ) = = std : : string : : npos ) {
2012-12-02 00:57:18 +01:00
m_config . stream ( ) < < " [ " < < prefix < < " : " < < trimmed < < " ] " ;
2012-08-23 21:08:50 +02:00
}
else {
2012-12-02 00:57:18 +01:00
m_config . stream ( ) < < " \n [ " < < prefix < < " ] >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> \n " < < trimmed
2012-08-23 21:08:50 +02:00
< < " \n [end of " < < prefix < < " ] <<<<<<<<<<<<<<<<<<<<<<<< \n " ;
}
}
2012-05-16 16:09:17 +02:00
2012-08-23 21:08:50 +02:00
private :
ReporterConfig m_config ;
bool m_firstSectionInTestCase ;
2012-05-16 16:09:17 +02:00
2012-08-23 21:08:50 +02:00
SpanInfo m_testingSpan ;
SpanInfo m_groupSpan ;
SpanInfo m_testSpan ;
std : : vector < SpanInfo > m_sectionSpans ;
bool m_aborted ;
} ;
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
} // end namespace Catch
2012-05-16 16:09:17 +02:00
2012-08-23 21:08:50 +02:00
// #included from: ../reporters/catch_reporter_xml.hpp
# define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
// #included from: ../internal/catch_xmlwriter.hpp
# define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
# include <sstream>
2012-09-29 21:54:03 +02:00
# include <iostream>
2012-08-23 21:08:50 +02:00
# include <string>
# include <vector>
2012-05-16 16:09:17 +02:00
2012-08-23 21:08:50 +02:00
namespace Catch {
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
class XmlWriter {
public :
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
class ScopedElement {
public :
ScopedElement ( XmlWriter * writer )
: m_writer ( writer )
{ }
ScopedElement ( const ScopedElement & other )
: m_writer ( other . m_writer ) {
other . m_writer = NULL ;
2012-08-09 08:47:30 +02:00
}
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
~ ScopedElement ( ) {
if ( m_writer )
m_writer - > endElement ( ) ;
}
2011-05-24 09:23:02 +02:00
2012-12-02 00:57:18 +01:00
ScopedElement & writeText ( const std : : string & text , bool indent = true ) {
m_writer - > writeText ( text , indent ) ;
2012-08-23 21:08:50 +02:00
return * this ;
}
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
template < typename T >
ScopedElement & writeAttribute ( const std : : string & name , const T & attribute ) {
m_writer - > writeAttribute ( name , attribute ) ;
return * this ;
}
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
private :
mutable XmlWriter * m_writer ;
} ;
2012-08-09 08:47:30 +02:00
2012-08-23 21:08:50 +02:00
XmlWriter ( )
: m_tagIsOpen ( false ) ,
m_needsNewline ( false ) ,
m_os ( & std : : cout )
{ }
2012-08-09 08:47:30 +02:00
2012-08-23 21:08:50 +02:00
XmlWriter ( std : : ostream & os )
: m_tagIsOpen ( false ) ,
m_needsNewline ( false ) ,
m_os ( & os )
{ }
2012-08-09 08:47:30 +02:00
2012-08-23 21:08:50 +02:00
~ XmlWriter ( ) {
while ( ! m_tags . empty ( ) )
endElement ( ) ;
}
2012-08-09 08:47:30 +02:00
2012-08-23 21:08:50 +02:00
XmlWriter & operator = ( const XmlWriter & other ) {
XmlWriter temp ( other ) ;
swap ( temp ) ;
return * this ;
}
2012-08-09 08:47:30 +02:00
2012-08-23 21:08:50 +02:00
void swap ( XmlWriter & other ) {
std : : swap ( m_tagIsOpen , other . m_tagIsOpen ) ;
std : : swap ( m_needsNewline , other . m_needsNewline ) ;
std : : swap ( m_tags , other . m_tags ) ;
std : : swap ( m_indent , other . m_indent ) ;
std : : swap ( m_os , other . m_os ) ;
}
2012-08-09 08:47:30 +02:00
2012-08-23 21:08:50 +02:00
XmlWriter & startElement ( const std : : string & name ) {
ensureTagClosed ( ) ;
newlineIfNecessary ( ) ;
stream ( ) < < m_indent < < " < " < < name ;
m_tags . push_back ( name ) ;
m_indent + = " " ;
m_tagIsOpen = true ;
return * this ;
2012-02-17 20:50:59 +01:00
}
2012-08-23 21:08:50 +02:00
ScopedElement scopedElement ( const std : : string & name ) {
ScopedElement scoped ( this ) ;
startElement ( name ) ;
return scoped ;
}
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02: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 ;
2011-05-24 09:23:02 +02:00
}
2012-08-23 21:08:50 +02:00
XmlWriter & writeAttribute ( const std : : string & name , const std : : string & attribute ) {
if ( ! name . empty ( ) & & ! attribute . empty ( ) ) {
stream ( ) < < " " < < name < < " = \" " ;
writeEncodedText ( attribute ) ;
stream ( ) < < " \" " ;
}
return * this ;
2011-05-24 09:23:02 +02:00
}
2012-08-23 21:08:50 +02:00
XmlWriter & writeAttribute ( const std : : string & name , bool attribute ) {
stream ( ) < < " " < < name < < " = \" " < < ( attribute ? " true " : " false " ) < < " \" " ;
return * this ;
2012-08-09 08:47:30 +02:00
}
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
template < typename T >
XmlWriter & writeAttribute ( const std : : string & name , const T & attribute ) {
if ( ! name . empty ( ) )
stream ( ) < < " " < < name < < " = \" " < < attribute < < " \" " ;
return * this ;
}
2011-05-24 09:23:02 +02:00
2012-12-02 00:57:18 +01:00
XmlWriter & writeText ( const std : : string & text , bool indent = true ) {
2012-08-23 21:08:50 +02:00
if ( ! text . empty ( ) ) {
bool tagWasOpen = m_tagIsOpen ;
ensureTagClosed ( ) ;
2012-12-02 00:57:18 +01:00
if ( tagWasOpen & & indent )
2012-08-23 21:08:50 +02:00
stream ( ) < < m_indent ;
writeEncodedText ( text ) ;
m_needsNewline = true ;
}
return * this ;
}
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
XmlWriter & writeComment ( const std : : string & text ) {
ensureTagClosed ( ) ;
stream ( ) < < m_indent < < " <!-- " < < text < < " --> " ;
m_needsNewline = true ;
return * this ;
}
2012-05-16 16:09:17 +02:00
2012-08-23 21:08:50 +02:00
XmlWriter & writeBlankLine ( ) {
ensureTagClosed ( ) ;
stream ( ) < < " \n " ;
return * this ;
}
2012-08-09 08:47:30 +02:00
2012-08-23 21:08:50 +02:00
private :
2012-08-09 08:47:30 +02:00
2012-08-23 21:08:50 +02:00
std : : ostream & stream ( ) {
return * m_os ;
}
2012-08-09 08:47:30 +02:00
2012-08-23 21:08:50 +02:00
void ensureTagClosed ( ) {
if ( m_tagIsOpen ) {
stream ( ) < < " > \n " ;
m_tagIsOpen = false ;
}
}
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
void newlineIfNecessary ( ) {
if ( m_needsNewline ) {
stream ( ) < < " \n " ;
m_needsNewline = false ;
}
}
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
void writeEncodedText ( const std : : string & text ) {
static const char * charsToEncode = " <& \" " ;
std : : string mtext = text ;
std : : string : : size_type pos = mtext . find_first_of ( charsToEncode ) ;
while ( pos ! = std : : string : : npos ) {
stream ( ) < < mtext . substr ( 0 , pos ) ;
2012-06-01 20:40:27 +02:00
2012-08-23 21:08:50 +02:00
switch ( mtext [ pos ] ) {
case ' < ' :
stream ( ) < < " < " ;
break ;
case ' & ' :
stream ( ) < < " & " ;
break ;
case ' \" ' :
stream ( ) < < " " " ;
break ;
}
mtext = mtext . substr ( pos + 1 ) ;
pos = mtext . find_first_of ( charsToEncode ) ;
}
stream ( ) < < mtext ;
}
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
bool m_tagIsOpen ;
bool m_needsNewline ;
std : : vector < std : : string > m_tags ;
std : : string m_indent ;
std : : ostream * m_os ;
} ;
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
}
2012-08-09 08:47:30 +02:00
namespace Catch {
2012-08-23 21:08:50 +02:00
class XmlReporter : public SharedImpl < IReporter > {
public :
XmlReporter ( const ReporterConfig & config ) : m_config ( config ) { }
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
static std : : string getDescription ( ) {
return " Reports test results as an XML document " ;
}
virtual ~ XmlReporter ( ) ;
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
private : // IReporter
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
virtual bool shouldRedirectStdout ( ) const {
2012-08-09 08:47:30 +02:00
return true ;
2011-05-24 09:23:02 +02:00
}
2012-08-23 21:08:50 +02:00
virtual void StartTesting ( ) {
2012-12-02 00:57:18 +01:00
m_xml = XmlWriter ( m_config . stream ( ) ) ;
2012-08-23 21:08:50 +02:00
m_xml . startElement ( " Catch " ) ;
2012-12-02 00:57:18 +01:00
if ( ! m_config . name ( ) . empty ( ) )
m_xml . writeAttribute ( " name " , m_config . name ( ) ) ;
2012-08-09 08:47:30 +02:00
}
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
virtual void EndTesting ( const Totals & totals ) {
m_xml . scopedElement ( " OverallResults " )
. writeAttribute ( " successes " , totals . assertions . passed )
. writeAttribute ( " failures " , totals . assertions . failed ) ;
m_xml . endElement ( ) ;
}
2012-08-09 08:47:30 +02:00
2012-08-23 21:08:50 +02:00
virtual void StartGroup ( const std : : string & groupName ) {
m_xml . startElement ( " Group " )
. writeAttribute ( " name " , groupName ) ;
2012-08-09 08:47:30 +02:00
}
2012-08-23 21:08:50 +02:00
virtual void EndGroup ( const std : : string & , const Totals & totals ) {
m_xml . scopedElement ( " OverallResults " )
. writeAttribute ( " successes " , totals . assertions . passed )
. writeAttribute ( " failures " , totals . assertions . failed ) ;
m_xml . endElement ( ) ;
2011-05-24 09:23:02 +02:00
}
2012-08-23 21:08:50 +02:00
virtual void StartSection ( const std : : string & sectionName , const std : : string & description ) {
m_xml . startElement ( " Section " )
. writeAttribute ( " name " , sectionName )
. writeAttribute ( " description " , description ) ;
2011-05-24 09:23:02 +02:00
}
2012-08-31 09:10:36 +02:00
virtual void NoAssertionsInSection ( const std : : string & ) { }
virtual void NoAssertionsInTestCase ( const std : : string & ) { }
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
virtual void EndSection ( const std : : string & /*sectionName*/ , const Counts & assertions ) {
m_xml . scopedElement ( " OverallResults " )
. writeAttribute ( " successes " , assertions . passed )
. writeAttribute ( " failures " , assertions . failed ) ;
m_xml . endElement ( ) ;
}
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
virtual void StartTestCase ( const Catch : : TestCaseInfo & testInfo ) {
2012-12-02 00:57:18 +01:00
m_xml . startElement ( " TestCase " ) . writeAttribute ( " name " , testInfo . name ) ;
2012-08-23 21:08:50 +02:00
m_currentTestSuccess = true ;
}
2012-08-09 08:47:30 +02:00
2012-10-28 13:07:17 +01:00
virtual void Result ( const Catch : : AssertionResult & assertionResult ) {
2012-12-02 00:57:18 +01:00
if ( ! m_config . includeSuccessfulResults ( ) & & assertionResult . getResultType ( ) = = ResultWas : : Ok )
2012-08-23 21:08:50 +02:00
return ;
2011-05-24 09:23:02 +02:00
2012-10-28 13:07:17 +01:00
if ( assertionResult . hasExpression ( ) ) {
2012-08-23 21:08:50 +02:00
m_xml . startElement ( " Expression " )
2012-11-13 10:44:52 +01:00
. writeAttribute ( " success " , assertionResult . succeeded ( ) )
2012-10-28 13:07:17 +01:00
. writeAttribute ( " filename " , assertionResult . getSourceInfo ( ) . file )
. writeAttribute ( " line " , assertionResult . getSourceInfo ( ) . line ) ;
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
m_xml . scopedElement ( " Original " )
2012-10-28 13:07:17 +01:00
. writeText ( assertionResult . getExpression ( ) ) ;
2012-08-23 21:08:50 +02:00
m_xml . scopedElement ( " Expanded " )
2012-10-28 13:07:17 +01:00
. writeText ( assertionResult . getExpandedExpression ( ) ) ;
2012-11-13 10:44:52 +01:00
m_currentTestSuccess & = assertionResult . succeeded ( ) ;
2012-08-23 21:08:50 +02:00
}
2012-05-16 16:09:17 +02:00
2012-10-28 13:07:17 +01:00
switch ( assertionResult . getResultType ( ) ) {
2012-08-23 21:08:50 +02:00
case ResultWas : : ThrewException :
m_xml . scopedElement ( " Exception " )
2012-10-28 13:07:17 +01:00
. writeAttribute ( " filename " , assertionResult . getSourceInfo ( ) . file )
. writeAttribute ( " line " , assertionResult . getSourceInfo ( ) . line )
. writeText ( assertionResult . getMessage ( ) ) ;
2012-08-23 21:08:50 +02:00
m_currentTestSuccess = false ;
break ;
case ResultWas : : Info :
m_xml . scopedElement ( " Info " )
2012-10-28 13:07:17 +01:00
. writeText ( assertionResult . getMessage ( ) ) ;
2012-08-23 21:08:50 +02:00
break ;
case ResultWas : : Warning :
m_xml . scopedElement ( " Warning " )
2012-10-28 13:07:17 +01:00
. writeText ( assertionResult . getMessage ( ) ) ;
2012-08-23 21:08:50 +02:00
break ;
case ResultWas : : ExplicitFailure :
m_xml . scopedElement ( " Failure " )
2012-10-28 13:07:17 +01:00
. writeText ( assertionResult . getMessage ( ) ) ;
2012-08-23 21:08:50 +02:00
m_currentTestSuccess = false ;
break ;
case ResultWas : : Unknown :
case ResultWas : : Ok :
case ResultWas : : FailureBit :
case ResultWas : : ExpressionFailed :
case ResultWas : : Exception :
case ResultWas : : DidntThrowException :
break ;
}
2012-10-28 13:07:17 +01:00
if ( assertionResult . hasExpression ( ) )
2012-08-23 21:08:50 +02:00
m_xml . endElement ( ) ;
}
2012-05-31 20:40:26 +02:00
2012-08-23 21:08:50 +02:00
virtual void Aborted ( ) {
// !TBD
2012-08-09 08:47:30 +02:00
}
2012-05-16 16:09:17 +02:00
2012-08-23 21:08:50 +02:00
virtual void EndTestCase ( const Catch : : TestCaseInfo & , const Totals & , const std : : string & , const std : : string & ) {
m_xml . scopedElement ( " OverallResult " ) . writeAttribute ( " success " , m_currentTestSuccess ) ;
m_xml . endElement ( ) ;
}
2012-07-20 20:07:42 +02:00
2012-08-23 21:08:50 +02:00
private :
ReporterConfig m_config ;
bool m_currentTestSuccess ;
XmlWriter m_xml ;
} ;
2012-07-20 20:07:42 +02:00
2012-08-23 21:08:50 +02:00
} // end namespace Catch
2012-07-17 09:04:19 +02:00
2012-08-23 21:08:50 +02:00
// #included from: ../reporters/catch_reporter_junit.hpp
# define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED
2012-07-28 21:37:07 +02:00
2012-12-02 01:05:51 +01:00
# include <assert.h>
2012-08-23 21:08:50 +02:00
namespace Catch {
2012-07-17 09:04:19 +02:00
2012-08-23 21:08:50 +02:00
class JunitReporter : public SharedImpl < IReporter > {
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
struct TestStats {
std : : string m_element ;
std : : string m_resultType ;
std : : string m_message ;
std : : string m_content ;
} ;
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
struct TestCaseStats {
2011-05-24 09:23:02 +02:00
2012-11-04 22:39:38 +01:00
TestCaseStats ( const std : : string & className , const std : : string & name )
: m_className ( className ) ,
m_name ( name )
{ }
2012-05-25 09:52:05 +02:00
2012-08-23 21:08:50 +02:00
double m_timeInSeconds ;
std : : string m_status ;
std : : string m_className ;
std : : string m_name ;
2012-11-21 19:06:13 +01:00
std : : string m_stdOut ;
std : : string m_stdErr ;
2012-08-23 21:08:50 +02:00
std : : vector < TestStats > m_testStats ;
2012-12-02 00:57:18 +01:00
std : : vector < TestCaseStats > m_sections ;
2012-08-23 21:08:50 +02:00
} ;
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
struct Stats {
2012-08-09 08:47:30 +02:00
2012-08-23 21:08:50 +02:00
Stats ( const std : : string & name = std : : string ( ) )
: m_testsCount ( 0 ) ,
m_failuresCount ( 0 ) ,
m_disabledCount ( 0 ) ,
m_errorsCount ( 0 ) ,
m_timeInSeconds ( 0 ) ,
m_name ( name )
{ }
2012-08-09 08:47:30 +02:00
2012-08-23 21:08:50 +02:00
std : : size_t m_testsCount ;
std : : size_t m_failuresCount ;
std : : size_t m_disabledCount ;
std : : size_t m_errorsCount ;
double m_timeInSeconds ;
std : : string m_name ;
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
std : : vector < TestCaseStats > m_testCaseStats ;
} ;
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
public :
JunitReporter ( const ReporterConfig & config )
: m_config ( config ) ,
m_testSuiteStats ( " AllTests " ) ,
m_currentStats ( & m_testSuiteStats )
{ }
virtual ~ JunitReporter ( ) ;
2012-05-31 20:40:26 +02:00
2012-08-23 21:08:50 +02:00
static std : : string getDescription ( ) {
return " Reports test results in an XML format that looks like Ant's junitreport target " ;
}
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
private : // IReporter
2012-07-05 19:37:58 +02:00
2012-08-23 21:08:50 +02:00
virtual bool shouldRedirectStdout ( ) const {
return true ;
}
2012-07-05 19:37:58 +02:00
2012-08-23 21:08:50 +02:00
virtual void StartTesting ( ) { }
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
virtual void StartGroup ( const std : : string & groupName ) {
2012-11-16 09:47:03 +01:00
if ( groupName . empty ( ) )
2012-12-02 00:57:18 +01:00
m_statsForSuites . push_back ( Stats ( m_config . name ( ) ) ) ;
2012-11-16 09:47:03 +01:00
else
m_statsForSuites . push_back ( Stats ( groupName ) ) ;
2012-08-23 21:08:50 +02:00
m_currentStats = & m_statsForSuites . back ( ) ;
}
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
virtual void EndGroup ( const std : : string & , const Totals & totals ) {
m_currentStats - > m_testsCount = totals . assertions . total ( ) ;
m_currentStats = & m_testSuiteStats ;
}
2012-08-09 08:47:30 +02:00
2012-08-23 21:08:50 +02:00
virtual void StartSection ( const std : : string & , const std : : string & ) { }
2012-08-09 08:47:30 +02:00
2012-08-31 09:10:36 +02:00
virtual void NoAssertionsInSection ( const std : : string & ) { }
virtual void NoAssertionsInTestCase ( const std : : string & ) { }
virtual void EndSection ( const std : : string & , const Counts & ) { }
2012-08-09 08:47:30 +02:00
2012-08-23 21:08:50 +02:00
virtual void StartTestCase ( const Catch : : TestCaseInfo & testInfo ) {
2012-12-02 00:57:18 +01:00
m_currentStats - > m_testCaseStats . push_back ( TestCaseStats ( testInfo . className , testInfo . name ) ) ;
m_currentTestCaseStats . push_back ( & m_currentStats - > m_testCaseStats . back ( ) ) ;
2012-08-23 21:08:50 +02:00
}
2012-08-09 08:47:30 +02:00
2012-10-28 13:07:17 +01:00
virtual void Result ( const Catch : : AssertionResult & assertionResult ) {
2012-12-02 00:57:18 +01:00
if ( assertionResult . getResultType ( ) ! = ResultWas : : Ok | | m_config . includeSuccessfulResults ( ) ) {
2012-08-23 21:08:50 +02:00
TestCaseStats & testCaseStats = m_currentStats - > m_testCaseStats . back ( ) ;
TestStats stats ;
std : : ostringstream oss ;
2012-10-28 13:07:17 +01:00
if ( ! assertionResult . getMessage ( ) . empty ( ) )
oss < < assertionResult . getMessage ( ) < < " at " ;
oss < < assertionResult . getSourceInfo ( ) ;
2012-08-23 21:08:50 +02:00
stats . m_content = oss . str ( ) ;
2012-10-28 13:07:17 +01:00
stats . m_message = assertionResult . getExpandedExpression ( ) ;
stats . m_resultType = assertionResult . getTestMacroName ( ) ;
2012-08-09 08:47:30 +02:00
2012-10-28 13:07:17 +01:00
switch ( assertionResult . getResultType ( ) ) {
2012-08-23 21:08:50 +02:00
case ResultWas : : ThrewException :
stats . m_element = " error " ;
m_currentStats - > m_errorsCount + + ;
break ;
case ResultWas : : Info :
stats . m_element = " info " ; // !TBD ?
break ;
case ResultWas : : Warning :
stats . m_element = " warning " ; // !TBD ?
break ;
case ResultWas : : ExplicitFailure :
stats . m_element = " failure " ;
m_currentStats - > m_failuresCount + + ;
break ;
case ResultWas : : ExpressionFailed :
stats . m_element = " failure " ;
m_currentStats - > m_failuresCount + + ;
break ;
case ResultWas : : Ok :
stats . m_element = " success " ;
break ;
case ResultWas : : Unknown :
case ResultWas : : FailureBit :
case ResultWas : : Exception :
case ResultWas : : DidntThrowException :
break ;
}
testCaseStats . m_testStats . push_back ( stats ) ;
}
}
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
virtual void EndTestCase ( const Catch : : TestCaseInfo & , const Totals & , const std : : string & stdOut , const std : : string & stdErr ) {
2012-12-02 00:57:18 +01:00
m_currentTestCaseStats . pop_back ( ) ;
assert ( m_currentTestCaseStats . empty ( ) ) ;
2012-11-21 19:06:13 +01:00
TestCaseStats & testCaseStats = m_currentStats - > m_testCaseStats . back ( ) ;
testCaseStats . m_stdOut = stdOut ;
testCaseStats . m_stdErr = stdErr ;
2012-08-23 21:08:50 +02:00
if ( ! stdOut . empty ( ) )
m_stdOut < < stdOut < < " \n " ;
if ( ! stdErr . empty ( ) )
m_stdErr < < stdErr < < " \n " ;
}
2011-05-24 09:23:02 +02:00
2012-08-23 21:08:50 +02:00
virtual void Aborted ( ) {
// !TBD
}
2012-08-16 19:48:50 +02:00
2012-08-23 21:08:50 +02:00
virtual void EndTesting ( const Totals & ) {
2012-12-02 00:57:18 +01:00
XmlWriter xml ( m_config . stream ( ) ) ;
2012-08-16 19:48:50 +02:00
2012-12-02 00:57:18 +01:00
if ( m_statsForSuites . size ( ) > 0 )
xml . startElement ( " testsuites " ) ;
2012-08-16 19:48:50 +02:00
2012-12-02 00:57:18 +01:00
std : : vector < Stats > : : const_iterator it = m_statsForSuites . begin ( ) ;
std : : vector < Stats > : : const_iterator itEnd = m_statsForSuites . end ( ) ;
2012-08-16 19:48:50 +02:00
2012-12-02 00:57:18 +01:00
for ( ; it ! = itEnd ; + + it ) {
XmlWriter : : ScopedElement e = xml . scopedElement ( " testsuite " ) ;
xml . writeAttribute ( " name " , it - > m_name ) ;
xml . writeAttribute ( " errors " , it - > m_errorsCount ) ;
xml . writeAttribute ( " failures " , it - > m_failuresCount ) ;
xml . writeAttribute ( " tests " , it - > m_testsCount ) ;
xml . writeAttribute ( " hostname " , " tbd " ) ;
xml . writeAttribute ( " time " , " tbd " ) ;
xml . writeAttribute ( " timestamp " , " tbd " ) ;
2012-08-23 20:48:57 +02:00
2012-12-02 00:57:18 +01:00
OutputTestCases ( xml , * it ) ;
2012-08-23 21:08:50 +02:00
}
2012-12-02 00:57:18 +01:00
xml . scopedElement ( " system-out " ) . writeText ( trim ( m_stdOut . str ( ) ) , false ) ;
xml . scopedElement ( " system-err " ) . writeText ( trim ( m_stdErr . str ( ) ) , false ) ;
2012-08-23 21:08:50 +02:00
}
2012-08-16 19:48:50 +02:00
2012-08-23 21:08:50 +02:00
void OutputTestCases ( XmlWriter & xml , const Stats & stats ) {
std : : vector < TestCaseStats > : : const_iterator it = stats . m_testCaseStats . begin ( ) ;
std : : vector < TestCaseStats > : : const_iterator itEnd = stats . m_testCaseStats . end ( ) ;
for ( ; it ! = itEnd ; + + it ) {
2012-08-16 19:48:50 +02:00
2012-08-23 21:08:50 +02:00
XmlWriter : : ScopedElement e = xml . scopedElement ( " testcase " ) ;
xml . writeAttribute ( " classname " , it - > m_className ) ;
xml . writeAttribute ( " name " , it - > m_name ) ;
xml . writeAttribute ( " time " , " tbd " ) ;
2012-08-16 19:48:50 +02:00
2012-08-23 21:08:50 +02:00
OutputTestResult ( xml , * it ) ;
2012-11-21 19:06:13 +01:00
std : : string stdOut = trim ( it - > m_stdOut ) ;
if ( ! stdOut . empty ( ) )
2012-12-02 00:57:18 +01:00
xml . scopedElement ( " system-out " ) . writeText ( stdOut , false ) ;
2012-11-21 19:06:13 +01:00
std : : string stdErr = trim ( it - > m_stdErr ) ;
if ( ! stdErr . empty ( ) )
2012-12-02 00:57:18 +01:00
xml . scopedElement ( " system-err " ) . writeText ( stdErr , false ) ;
2012-08-23 21:08:50 +02:00
}
}
2012-08-16 19:48:50 +02:00
2012-08-23 21:08:50 +02:00
void OutputTestResult ( XmlWriter & xml , const TestCaseStats & stats ) {
std : : vector < TestStats > : : const_iterator it = stats . m_testStats . begin ( ) ;
std : : vector < TestStats > : : const_iterator itEnd = stats . m_testStats . end ( ) ;
for ( ; it ! = itEnd ; + + it ) {
if ( it - > m_element ! = " success " ) {
XmlWriter : : ScopedElement e = xml . scopedElement ( it - > m_element ) ;
2012-08-16 19:48:50 +02:00
2012-08-23 21:08:50 +02:00
xml . writeAttribute ( " message " , it - > m_message ) ;
xml . writeAttribute ( " type " , it - > m_resultType ) ;
if ( ! it - > m_content . empty ( ) )
xml . writeText ( it - > m_content ) ;
}
}
}
2012-08-16 19:48:50 +02:00
2012-08-23 21:08:50 +02:00
private :
ReporterConfig m_config ;
bool m_currentTestSuccess ;
2012-08-16 19:48:50 +02:00
2012-08-23 21:08:50 +02:00
Stats m_testSuiteStats ;
Stats * m_currentStats ;
std : : vector < Stats > m_statsForSuites ;
2012-12-02 00:57:18 +01:00
std : : vector < const TestCaseStats * > m_currentTestCaseStats ;
2012-08-23 21:08:50 +02:00
std : : ostringstream m_stdOut ;
std : : ostringstream m_stdErr ;
} ;
} // end namespace Catch
2012-08-16 19:48:50 +02:00
2012-12-06 09:44:51 +01:00
// #included from: ../reporters/catch_reporter_console.hpp
# define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED
namespace Catch {
2013-01-16 10:44:43 +01:00
struct ConsoleReporter : StreamingReporterBase {
2012-12-06 09:44:51 +01:00
ConsoleReporter ( ReporterConfig const & _config )
2013-01-16 10:44:43 +01:00
: StreamingReporterBase ( _config ) ,
2013-03-08 10:30:25 +01:00
m_headerPrinted ( false ) ,
2012-12-14 08:50:08 +01:00
m_atLeastOneTestCasePrinted ( false )
2012-12-06 09:44:51 +01:00
{ }
virtual ~ ConsoleReporter ( ) ;
static std : : string getDescription ( ) {
return " Reports test results as plain lines of text " ;
}
virtual ReporterPreferences getPreferences ( ) const {
ReporterPreferences prefs ;
prefs . shouldRedirectStdOut = false ;
return prefs ;
}
2013-01-16 10:44:43 +01:00
virtual void assertionStarting ( AssertionInfo const & ) {
2012-12-06 09:44:51 +01:00
}
2013-01-16 10:44:43 +01:00
virtual void assertionEnded ( AssertionStats const & _assertionStats ) {
AssertionResult const & result = _assertionStats . assertionResult ;
// Drop out if result was successful and we're not printing those
if ( ! m_config . includeSuccessfulResults ( ) & & result . isOk ( ) )
return ;
lazyPrint ( ) ;
2013-01-26 21:18:30 +01:00
AssertionPrinter printer ( stream , _assertionStats ) ;
printer . print ( ) ;
stream < < std : : endl ;
}
virtual void sectionStarting ( SectionInfo const & _sectionInfo ) {
2013-03-08 10:30:25 +01:00
m_headerPrinted = false ;
2013-01-26 21:18:30 +01:00
StreamingReporterBase : : sectionStarting ( _sectionInfo ) ;
}
virtual void sectionEnded ( SectionStats const & _sectionStats ) {
if ( _sectionStats . missingAssertions ) {
lazyPrint ( ) ;
TextColour colour ( TextColour : : ResultError ) ;
stream < < " \n No assertions in section, ' " < < _sectionStats . sectionInfo . name < < " ' \n " < < std : : endl ;
2013-01-16 10:44:43 +01:00
}
2013-03-08 10:30:25 +01:00
m_headerPrinted = false ;
2013-01-26 21:18:30 +01:00
StreamingReporterBase : : sectionEnded ( _sectionStats ) ;
}
2013-01-17 13:07:34 +01:00
2013-01-26 21:18:30 +01:00
virtual void testCaseEnded ( TestCaseStats const & _testCaseStats ) {
if ( _testCaseStats . missingAssertions ) {
lazyPrint ( ) ;
TextColour colour ( TextColour : : ResultError ) ;
stream < < " \n No assertions in test case, ' " < < _testCaseStats . testInfo . name < < " ' \n " < < std : : endl ;
}
StreamingReporterBase : : testCaseEnded ( _testCaseStats ) ;
2013-03-08 10:30:25 +01:00
m_headerPrinted = false ;
2013-01-26 21:18:30 +01:00
}
virtual void testGroupEnded ( TestGroupStats const & _testGroupStats ) {
if ( ! unusedGroupInfo ) {
printSummaryDivider ( ) ;
stream < < " Summary for group ' " < < _testGroupStats . groupInfo . name < < " ': \n " ;
printTotals ( _testGroupStats . totals ) ;
stream < < " \n " < < std : : endl ;
}
StreamingReporterBase : : testGroupEnded ( _testGroupStats ) ;
2012-12-06 09:44:51 +01:00
}
2013-01-26 21:18:30 +01:00
virtual void testRunEnded ( TestRunStats const & _testRunStats ) {
if ( m_atLeastOneTestCasePrinted )
printTotalsDivider ( ) ;
printTotals ( _testRunStats . totals ) ;
stream < < " \n " < < std : : endl ;
StreamingReporterBase : : testRunEnded ( _testRunStats ) ;
2013-01-17 13:07:34 +01:00
}
2012-12-10 09:54:57 +01:00
2013-01-26 21:18:30 +01:00
private :
class AssertionPrinter {
public :
AssertionPrinter ( std : : ostream & _stream , AssertionStats const & _stats )
: stream ( _stream ) ,
stats ( _stats ) ,
result ( _stats . assertionResult ) ,
colour ( TextColour : : None ) ,
2013-02-02 21:37:58 +01:00
message ( result . getMessage ( ) ) ,
messages ( _stats . infoMessages )
2013-01-16 10:44:43 +01:00
{
2013-01-26 21:18:30 +01:00
switch ( result . getResultType ( ) ) {
2013-01-16 10:44:43 +01:00
case ResultWas : : Ok :
colour = TextColour : : Success ;
2013-01-17 13:07:34 +01:00
passOrFail = " PASSED " ;
2013-02-02 21:37:58 +01:00
//if( result.hasMessage() )
if ( _stats . infoMessages . size ( ) = = 1 )
2013-01-16 10:44:43 +01:00
messageLabel = " with message " ;
2013-02-02 21:37:58 +01:00
if ( _stats . infoMessages . size ( ) > 1 )
messageLabel = " with messages " ;
2013-01-16 10:44:43 +01:00
break ;
case ResultWas : : ExpressionFailed :
2013-01-26 21:18:30 +01:00
if ( result . isOk ( ) ) {
2013-01-16 10:44:43 +01:00
colour = TextColour : : Success ;
2013-01-17 13:07:34 +01:00
passOrFail = " FAILED - but was ok " ;
2013-01-16 10:44:43 +01:00
}
else {
colour = TextColour : : Error ;
2013-01-17 13:07:34 +01:00
passOrFail = " FAILED " ;
2013-01-16 10:44:43 +01:00
}
2013-02-02 21:37:58 +01:00
if ( _stats . infoMessages . size ( ) = = 1 )
2013-01-16 10:44:43 +01:00
messageLabel = " with message " ;
2013-02-02 21:37:58 +01:00
if ( _stats . infoMessages . size ( ) > 1 )
messageLabel = " with messages " ;
// if( result.hasMessage() ){
// messageLabel = "with message";
// }
2013-01-16 10:44:43 +01:00
break ;
case ResultWas : : ThrewException :
colour = TextColour : : Error ;
2013-01-17 13:07:34 +01:00
passOrFail = " FAILED " ;
2013-01-16 10:44:43 +01:00
messageLabel = " due to unexpected exception with message " ;
break ;
case ResultWas : : DidntThrowException :
colour = TextColour : : Error ;
2013-01-17 13:07:34 +01:00
passOrFail = " FAILED " ;
2013-01-16 10:44:43 +01:00
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 :
2013-01-17 13:07:34 +01:00
passOrFail = " FAILED " ;
2013-01-16 10:44:43 +01:00
colour = TextColour : : Error ;
2013-02-02 21:37:58 +01:00
// messageLabel = "explicitly with message";
if ( _stats . infoMessages . size ( ) = = 1 )
messageLabel = " explicitly with message " ;
if ( _stats . infoMessages . size ( ) > 1 )
messageLabel = " explicitly with messages " ;
2013-01-16 10:44:43 +01:00
break ;
case ResultWas : : Exception :
2013-01-17 13:07:34 +01:00
passOrFail = " FAILED " ;
2013-01-16 10:44:43 +01:00
colour = TextColour : : Error ;
2013-02-02 21:37:58 +01:00
if ( _stats . infoMessages . size ( ) = = 1 )
2013-01-16 10:44:43 +01:00
messageLabel = " with message " ;
2013-02-02 21:37:58 +01:00
if ( _stats . infoMessages . size ( ) > 1 )
messageLabel = " with messages " ;
// if( result.hasMessage() )
// messageLabel = "with message";
2013-01-16 10:44:43 +01:00
break ;
// These cases are here to prevent compiler warnings
case ResultWas : : Unknown :
case ResultWas : : FailureBit :
passOrFail = " ** internal error ** " ;
colour = TextColour : : Error ;
break ;
}
}
2013-01-26 21:18:30 +01:00
void print ( ) const {
2013-03-04 12:19:15 +01:00
printSourceInfo ( ) ;
2013-01-26 21:18:30 +01:00
if ( stats . totals . assertions . total ( ) > 0 ) {
2013-03-04 12:19:15 +01:00
if ( result . isOk ( ) )
stream < < " \n " ;
2013-01-26 21:18:30 +01:00
printResultType ( ) ;
printOriginalExpression ( ) ;
printReconstructedExpression ( ) ;
}
2013-03-04 12:19:15 +01:00
else {
stream < < " \n " ;
}
2013-01-26 21:18:30 +01:00
printMessage ( ) ;
2012-12-10 09:54:57 +01:00
}
2013-01-26 21:18:30 +01:00
private :
void printResultType ( ) const {
if ( ! passOrFail . empty ( ) ) {
TextColour colourGuard ( colour ) ;
stream < < passOrFail < < " : \n " ;
}
2013-01-16 10:44:43 +01:00
}
2013-01-26 21:18:30 +01:00
void printOriginalExpression ( ) const {
if ( result . hasExpression ( ) ) {
TextColour colourGuard ( TextColour : : OriginalExpression ) ;
stream < < " " ;
if ( ! result . getTestMacroName ( ) . empty ( ) )
stream < < result . getTestMacroName ( ) < < " ( " ;
stream < < result . getExpression ( ) ;
if ( ! result . getTestMacroName ( ) . empty ( ) )
stream < < " ) " ;
stream < < " \n " ;
}
2013-01-16 10:44:43 +01:00
}
2013-01-26 21:18:30 +01:00
void printReconstructedExpression ( ) const {
if ( result . hasExpandedExpression ( ) ) {
stream < < " with expansion: \n " ;
TextColour colourGuard ( TextColour : : ReconstructedExpression ) ;
stream < < wrapLongStrings ( result . getExpandedExpression ( ) ) < < " \n " ;
}
2013-01-16 10:44:43 +01:00
}
2013-01-26 21:18:30 +01:00
void printMessage ( ) const {
if ( ! messageLabel . empty ( ) )
stream < < messageLabel < < " : " < < " \n " ;
2013-02-02 21:37:58 +01:00
for ( std : : vector < MessageInfo > : : const_iterator it = messages . begin ( ) , itEnd = messages . end ( ) ;
it ! = itEnd ;
+ + it ) {
stream < < wrapLongStrings ( it - > message ) < < " \n " ;
}
// if( !message.empty() )
// stream << wrapLongStrings( message ) << "\n";
2013-01-16 10:44:43 +01:00
}
2013-01-26 21:18:30 +01:00
void printSourceInfo ( ) const {
TextColour colourGuard ( TextColour : : FileName ) ;
2013-03-04 12:19:15 +01:00
stream < < result . getSourceInfo ( ) < < " : " ;
2013-01-16 10:44:43 +01:00
}
2013-01-26 21:18:30 +01:00
static std : : string wrapLongStrings ( std : : string const & _string ) {
return Catch : : wrapLongStrings ( _string , CATCH_CONFIG_CONSOLE_WIDTH - 1 , 2 ) ;
2013-01-16 10:44:43 +01:00
}
2012-12-14 08:50:08 +01:00
2013-01-26 21:18:30 +01:00
std : : ostream & stream ;
AssertionStats const & stats ;
AssertionResult const & result ;
TextColour : : Colours colour ;
std : : string passOrFail ;
std : : string messageLabel ;
std : : string message ;
2013-02-02 21:37:58 +01:00
std : : vector < MessageInfo > messages ;
2013-01-26 21:18:30 +01:00
} ;
2012-12-14 08:50:08 +01:00
2012-12-06 09:44:51 +01:00
void lazyPrint ( ) {
2013-01-16 10:44:43 +01:00
2012-12-06 09:44:51 +01:00
if ( testRunInfo )
lazyPrintRunInfo ( ) ;
if ( unusedGroupInfo )
lazyPrintGroupInfo ( ) ;
2013-03-08 10:30:25 +01:00
if ( ! m_headerPrinted ) {
printTestCaseAndSectionHeader ( ) ;
m_headerPrinted = true ;
}
2013-01-16 10:44:43 +01:00
m_atLeastOneTestCasePrinted = true ;
2012-12-06 09:44:51 +01:00
}
2013-01-16 10:44:43 +01:00
void lazyPrintRunInfo ( ) {
stream < < " \n " < < testRunInfo - > name
< < " is a CATCH v " < < libraryVersion . majorVersion < < " . "
< < libraryVersion . minorVersion < < " b "
< < libraryVersion . buildNumber ;
if ( libraryVersion . branchName ! = " master " )
stream < < " ( " < < libraryVersion . branchName < < " ) " ;
stream < < " host application. \n "
< < " Run with -? for options \n \n " ;
2012-12-10 09:54:57 +01:00
2013-01-16 10:44:43 +01:00
testRunInfo . reset ( ) ;
}
void lazyPrintGroupInfo ( ) {
if ( ! unusedGroupInfo - > name . empty ( ) & & unusedGroupInfo - > groupsCounts > 1 ) {
2013-03-08 10:30:25 +01:00
printClosedHeader ( " Group: " + unusedGroupInfo - > name ) ;
2013-01-16 10:44:43 +01:00
unusedGroupInfo . reset ( ) ;
}
}
void lazyPrintTestCaseInfo ( ) {
if ( ! currentSectionInfo ) {
2013-03-08 10:30:25 +01:00
printClosedHeader ( unusedTestCaseInfo - > name ) ;
2013-01-16 10:44:43 +01:00
stream < < std : : endl ;
}
}
2013-03-08 10:30:25 +01:00
void printTestCaseAndSectionHeader ( ) {
printOpenHeader ( unusedTestCaseInfo - > name ) ;
if ( currentSectionInfo ) {
std : : vector < ThreadedSectionInfo * > sections ;
for ( ThreadedSectionInfo * section = currentSectionInfo . get ( ) ;
section ;
section = section - > parent )
sections . push_back ( section ) ;
// Sections
if ( ! sections . empty ( ) ) {
typedef std : : vector < ThreadedSectionInfo * > : : const_reverse_iterator It ;
for ( It it = sections . rbegin ( ) , itEnd = sections . rend ( ) ; it ! = itEnd ; + + it )
stream < < " " < < ( * it ) - > name < < " \n " ;
}
2012-12-10 09:54:57 +01:00
}
2013-03-08 10:30:25 +01:00
stream < < getDots ( ) < < " \n " < < std : : endl ;
2013-01-16 10:44:43 +01:00
}
2012-12-10 09:54:57 +01:00
2013-03-08 10:30:25 +01:00
void printClosedHeader ( std : : string const & _name ) {
printOpenHeader ( _name ) ;
stream < < getDots ( ) < < " \n " ;
}
void printOpenHeader ( std : : string const & _name ) {
2013-01-16 10:44:43 +01:00
stream < < getDashes ( ) < < " \n "
2013-01-17 13:07:34 +01:00
< < _name < < " \n " ;
2012-12-10 09:54:57 +01:00
}
2013-01-16 10:44:43 +01:00
void printTotals ( const Totals & totals ) {
if ( totals . assertions . total ( ) = = 0 ) {
stream < < " No tests ran " ;
}
else if ( totals . assertions . failed ) {
TextColour colour ( TextColour : : ResultError ) ;
printCounts ( " test case " , totals . testCases ) ;
if ( totals . testCases . failed > 0 ) {
stream < < " ( " ;
printCounts ( " assertion " , totals . assertions ) ;
stream < < " ) " ;
}
2012-12-10 09:54:57 +01:00
}
else {
2013-01-16 10:44:43 +01:00
TextColour colour ( TextColour : : ResultSuccess ) ;
stream < < " All tests passed ( "
< < pluralise ( totals . assertions . passed , " assertion " ) < < " in "
< < pluralise ( totals . testCases . passed , " test case " ) < < " ) " ;
2012-12-10 09:54:57 +01:00
}
2012-12-06 09:44:51 +01:00
}
2013-01-16 10:44:43 +01:00
void printCounts ( std : : string const & label , Counts const & counts ) {
2012-12-11 10:03:14 +01:00
if ( counts . total ( ) = = 1 ) {
stream < < " 1 " < < label < < " - " ;
if ( counts . failed )
stream < < " failed " ;
else
stream < < " passed " ;
}
else {
stream < < counts . total ( ) < < " " < < label < < " s " ;
if ( counts . passed ) {
if ( counts . failed )
stream < < " - " < < counts . failed < < " failed " ;
else if ( counts . passed = = 2 )
stream < < " - both passed " ;
else
stream < < " - all passed " ;
}
else {
if ( counts . failed = = 2 )
stream < < " - both failed " ;
else
stream < < " - all failed " ;
}
}
2012-12-06 09:44:51 +01:00
}
2013-01-16 10:44:43 +01:00
void printTotalsDivider ( ) {
stream < < getDoubleDashes ( ) < < " \n " ;
2012-12-06 09:44:51 +01:00
}
2013-01-16 10:44:43 +01:00
void printSummaryDivider ( ) {
stream < < getDashes ( ) < < " \n " ;
2012-12-06 09:44:51 +01:00
}
2013-01-16 10:44:43 +01:00
static std : : string const & getDashes ( ) {
2013-01-26 21:18:30 +01:00
static const std : : string dashes ( CATCH_CONFIG_CONSOLE_WIDTH - 1 , ' - ' ) ;
2013-01-16 10:44:43 +01:00
return dashes ;
2012-12-06 09:44:51 +01:00
}
2013-01-18 09:09:28 +01:00
static std : : string const & getDots ( ) {
2013-01-26 21:18:30 +01:00
static const std : : string dots ( CATCH_CONFIG_CONSOLE_WIDTH - 1 , ' . ' ) ;
2013-01-18 09:09:28 +01:00
return dots ;
}
2013-01-16 10:44:43 +01:00
static std : : string const & getDoubleDashes ( ) {
2013-01-26 21:18:30 +01:00
static const std : : string doubleDashes ( CATCH_CONFIG_CONSOLE_WIDTH - 1 , ' = ' ) ;
2013-01-16 10:44:43 +01:00
return doubleDashes ;
2012-12-06 09:44:51 +01:00
}
2012-12-14 08:50:08 +01:00
private :
2013-03-08 10:30:25 +01:00
bool m_headerPrinted ;
2012-12-14 08:50:08 +01:00
bool m_atLeastOneTestCasePrinted ;
2012-12-06 09:44:51 +01:00
} ;
INTERNAL_CATCH_REGISTER_REPORTER ( " console " , ConsoleReporter )
} // end namespace Catch
2012-08-13 08:46:10 +02:00
namespace Catch {
NonCopyable : : ~ NonCopyable ( ) { }
IShared : : ~ IShared ( ) { }
StreamBufBase : : ~ StreamBufBase ( ) { }
IContext : : ~ IContext ( ) { }
IResultCapture : : ~ IResultCapture ( ) { }
ITestCase : : ~ ITestCase ( ) { }
ITestCaseRegistry : : ~ ITestCaseRegistry ( ) { }
IRegistryHub : : ~ IRegistryHub ( ) { }
IMutableRegistryHub : : ~ IMutableRegistryHub ( ) { }
IExceptionTranslator : : ~ IExceptionTranslator ( ) { }
IExceptionTranslatorRegistry : : ~ IExceptionTranslatorRegistry ( ) { }
IReporter : : ~ IReporter ( ) { }
IReporterFactory : : ~ IReporterFactory ( ) { }
IReporterRegistry : : ~ IReporterRegistry ( ) { }
2012-12-02 00:57:18 +01:00
IStreamingReporter : : ~ IStreamingReporter ( ) { }
LegacyReporterAdapter : : ~ LegacyReporterAdapter ( ) { }
AssertionStats : : ~ AssertionStats ( ) { }
SectionStats : : ~ SectionStats ( ) { }
TestCaseStats : : ~ TestCaseStats ( ) { }
TestGroupStats : : ~ TestGroupStats ( ) { }
TestRunStats : : ~ TestRunStats ( ) { }
2012-12-06 09:44:51 +01:00
ThreadedSectionInfo : : ~ ThreadedSectionInfo ( ) { }
2013-01-16 10:44:43 +01:00
TestGroupNode : : ~ TestGroupNode ( ) { }
TestRunNode : : ~ TestRunNode ( ) { }
2012-12-02 00:57:18 +01:00
2012-08-13 08:46:10 +02:00
BasicReporter : : ~ BasicReporter ( ) { }
2013-01-16 10:44:43 +01:00
StreamingReporterBase : : ~ StreamingReporterBase ( ) { }
CumulativeReporterBase : : ~ CumulativeReporterBase ( ) { }
2012-12-06 09:44:51 +01:00
ConsoleReporter : : ~ ConsoleReporter ( ) { }
2012-08-13 08:46:10 +02:00
IRunner : : ~ IRunner ( ) { }
IMutableContext : : ~ IMutableContext ( ) { }
IConfig : : ~ IConfig ( ) { }
XmlReporter : : ~ XmlReporter ( ) { }
JunitReporter : : ~ JunitReporter ( ) { }
TestRegistry : : ~ TestRegistry ( ) { }
FreeFunctionTestCase : : ~ FreeFunctionTestCase ( ) { }
IGeneratorInfo : : ~ IGeneratorInfo ( ) { }
IGeneratorsForTest : : ~ IGeneratorsForTest ( ) { }
2012-09-24 09:30:13 +02:00
TagParser : : ~ TagParser ( ) { }
TagExtracter : : ~ TagExtracter ( ) { }
TagExpressionParser : : ~ TagExpressionParser ( ) { }
2012-08-13 08:46:10 +02:00
2012-10-12 08:58:17 +02:00
Matchers : : Impl : : StdString : : Equals : : ~ Equals ( ) { }
Matchers : : Impl : : StdString : : Contains : : ~ Contains ( ) { }
Matchers : : Impl : : StdString : : StartsWith : : ~ StartsWith ( ) { }
Matchers : : Impl : : StdString : : EndsWith : : ~ EndsWith ( ) { }
2012-08-13 08:46:10 +02:00
void Config : : dummy ( ) { }
2012-12-02 00:57:18 +01:00
INTERNAL_CATCH_REGISTER_LEGACY_REPORTER ( " basic " , BasicReporter )
INTERNAL_CATCH_REGISTER_LEGACY_REPORTER ( " xml " , XmlReporter )
INTERNAL_CATCH_REGISTER_LEGACY_REPORTER ( " junit " , JunitReporter )
2012-08-23 21:08:50 +02:00
2012-08-13 08:46:10 +02:00
}
2012-08-16 19:48:50 +02:00
# ifdef __clang__
2012-08-13 08:46:10 +02:00
# pragma clang diagnostic pop
2011-05-24 09:23:02 +02:00
# endif
2012-09-17 07:42:29 +02:00
2012-08-16 19:48:50 +02:00
# endif
2011-05-24 09:23:02 +02:00
# ifdef CATCH_CONFIG_MAIN
// #included from: internal/catch_default_main.hpp
2012-08-09 08:47:30 +02:00
# define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED
2011-05-24 09:23:02 +02:00
2012-05-11 09:17:16 +02:00
# ifndef __OBJC__
// Standard C/C++ main entry point
int main ( int argc , char * const argv [ ] ) {
return Catch : : Main ( argc , argv ) ;
}
# else // __OBJC__
2011-05-24 09:23:02 +02:00
2012-05-11 09:17:16 +02:00
// Objective-C entry point
int main ( int argc , char * const argv [ ] ) {
2012-03-17 19:20:06 +01:00
# if !CATCH_ARC_ENABLED
2011-05-24 09:23:02 +02:00
NSAutoreleasePool * pool = [ [ NSAutoreleasePool alloc ] init ] ;
2012-03-17 19:20:06 +01:00
# endif
2011-05-24 09:23:02 +02:00
Catch : : registerTestMethods ( ) ;
int result = Catch : : Main ( argc , ( char * const * ) argv ) ;
2012-03-17 19:20:06 +01:00
# if !CATCH_ARC_ENABLED
2011-05-24 09:23:02 +02:00
[ pool drain ] ;
2012-03-17 19:20:06 +01:00
# endif
2011-05-24 09:23:02 +02:00
2012-02-18 10:58:30 +01:00
return result ;
2011-05-24 09:23:02 +02:00
}
2012-05-11 09:17:16 +02:00
# endif // __OBJC__
2011-05-24 09:23:02 +02:00
# endif
//////
2012-07-20 19:43:48 +02:00
// If this config identifier is defined then all CATCH macros are prefixed with CATCH_
# ifdef CATCH_CONFIG_PREFIX_ALL
2012-11-10 19:46:39 +01: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::NegateResult, "CATCH_REQUIRE_FALSE" )
2012-07-20 19:43:48 +02:00
2012-11-10 19:46:39 +01:00
# define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS" )
# define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS_AS" )
# define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_NOTHROW" )
2012-07-20 19:43:48 +02:00
2012-11-10 19:46:39 +01: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::NegateResult, "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" )
2012-11-13 10:45:29 +01:00
# define CATCH_CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CATCH_CHECK_NOFAIL" )
2012-07-20 19:43:48 +02:00
2012-11-10 19:46:39 +01:00
# define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS" )
# define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS_AS" )
# define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" )
2012-07-20 19:43:48 +02:00
2012-11-10 19:46:39 +01:00
# define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" )
# define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THAT" )
2012-07-20 19:43:48 +02:00
2013-02-02 21:37:58 +01:00
# define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" )
2012-11-10 19:46:39 +01:00
# define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "CATCH_WARN" )
# define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL" )
# define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED" )
2012-10-28 13:07:17 +01:00
# define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_SCOPED_INFO( msg, "CATCH_SCOPED_INFO" )
2013-02-02 21:37:58 +01:00
# define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" )
2012-10-28 13:07:17 +01:00
# define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_SCOPED_INFO( #msg " := " << msg, "CATCH_SCOPED_CAPTURE" )
2012-07-20 19:43:48 +02:00
# define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
# define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
# define CATCH_TEST_CASE_NORETURN( name, description ) INTERNAL_CATCH_TESTCASE_NORETURN( name, description )
# define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "Anonymous test case" )
# define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
# define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
2012-12-02 00:57:18 +01:00
# define CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType )
2012-07-20 19:43:48 +02:00
# define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required
# else
2012-11-10 19:46:39 +01:00
# define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "REQUIRE" )
# define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::NegateResult, "REQUIRE_FALSE" )
2011-05-24 09:23:02 +02:00
2012-11-10 19:46:39 +01:00
# define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., Catch::ResultDisposition::Normal, "REQUIRE_THROWS" )
# define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "REQUIRE_THROWS_AS" )
# define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "REQUIRE_NOTHROW" )
2011-05-24 09:23:02 +02:00
2012-11-10 19:46:39 +01:00
# define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" )
# define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::NegateResult, "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" )
2012-11-13 10:44:52 +01:00
# define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CHECK_NOFAIL" )
2011-05-24 09:23:02 +02:00
2012-11-10 19:46:39 +01:00
# define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS" )
# define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS_AS" )
# define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_NOTHROW" )
2011-05-24 09:23:02 +02:00
2012-11-10 19:46:39 +01:00
# define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THAT" )
# define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "REQUIRE_THAT" )
2012-03-04 22:22:36 +01:00
2013-02-02 21:37:58 +01:00
# define INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" )
2012-11-10 19:46:39 +01:00
# define WARN( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "WARN" )
# define FAIL( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL" )
# define SUCCEED( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED" )
2012-10-28 13:07:17 +01:00
# define SCOPED_INFO( msg ) INTERNAL_CATCH_SCOPED_INFO( msg, "SCOPED_INFO" )
2013-02-02 21:37:58 +01:00
# define CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" )
2012-10-28 13:07:17 +01:00
# define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_SCOPED_INFO( #msg " := " << msg, "SCOPED_CAPTURE" )
2011-05-24 09:23:02 +02:00
# define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
# define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
# define TEST_CASE_NORETURN( name, description ) INTERNAL_CATCH_TESTCASE_NORETURN( name, description )
# define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "Anonymous test case" )
2012-07-20 19:43:48 +02:00
# define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
2011-05-24 09:23:02 +02:00
# define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
2012-12-02 00:57:18 +01:00
# define REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType )
2011-05-24 09:23:02 +02:00
# define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
2012-07-20 19:43:48 +02:00
# endif
# define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )
2011-05-24 09:23:02 +02:00
using Catch : : Detail : : Approx ;
2012-08-16 19:48:50 +02:00
# ifdef __clang__
2012-08-13 08:46:10 +02:00
# pragma clang diagnostic pop
2012-08-16 19:48:50 +02:00
# endif
2012-08-13 08:46:10 +02:00
2012-05-09 20:37:51 +02:00
# endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
2011-05-24 09:23:02 +02:00