2011-05-24 08:23:02 +01:00
/*
2012-12-14 07:50:08 +00:00
* CATCH v0.9 build 12 (integration branch)
* Generated: 2012-12-14 07:49:28.360647
2012-05-22 22:22:22 +01:00
* ----------------------------------------------------------
2012-05-09 19:37:51 +01:00
* This file has been merged from multiple headers. Please don't edit it directly
* Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved.
2011-05-24 08:23:02 +01:00
*
* Distributed under the Boost Software License, Version 1.0. (See accompanying
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
2012-05-09 19:37:51 +01:00
#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
2011-05-24 08:23:02 +01:00
2012-08-09 07:47:30 +01:00
#define TWOBLUECUBES_CATCH_HPP_INCLUDED
2012-06-02 23:12:42 +01:00
2012-08-16 18:48:50 +01:00
#ifdef __clang__
2012-10-30 09:09:30 +00:00
#pragma clang diagnostic ignored "-Wglobal-constructors"
2012-08-16 18:48:50 +01:00
2012-08-13 07:46:10 +01:00
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wpadded"
2012-08-16 18:48:50 +01:00
#endif
2012-08-13 07:46:10 +01:00
2012-08-09 07:47:30 +01:00
// #included from: internal/catch_notimplemented_exception.h
#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED
2011-05-24 08:23:02 +01:00
// #included from: catch_common.h
2012-08-09 07:47:30 +01:00
#define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED
2011-05-24 08:23:02 +01:00
#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line )
#define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr
#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr )
#ifdef __GNUC__
2012-08-13 07:46:10 +01:00
#define CATCH_ATTRIBUTE_NORETURN __attribute__ ((noreturn))
2011-05-24 08:23:02 +01:00
#else
2012-08-13 07:46:10 +01:00
#define CATCH_ATTRIBUTE_NORETURN
2011-05-24 08:23:02 +01:00
#endif
#include <sstream>
#include <stdexcept>
#include <algorithm>
2012-05-16 15:09:17 +01:00
namespace Catch {
2012-05-09 19:04:00 +01:00
class NonCopyable {
2011-05-24 08:23:02 +01:00
NonCopyable ( const NonCopyable & );
void operator = ( const NonCopyable & );
protected :
2012-05-09 19:04:00 +01:00
NonCopyable () {}
2012-08-13 07:46:10 +01:00
virtual ~ NonCopyable ();
2011-05-24 08:23:02 +01:00
};
2012-05-31 19:40:26 +01:00
class SafeBool {
public :
typedef void ( SafeBool ::* type )() const ;
static type makeSafe ( bool value ) {
return value ? & SafeBool :: trueValue : 0 ;
}
private :
void trueValue () const {}
};
2011-05-24 08:23:02 +01:00
template < typename ContainerT >
2012-05-09 19:04:00 +01:00
inline void deleteAll ( ContainerT & container ) {
2011-05-24 08:23:02 +01:00
typename ContainerT :: const_iterator it = container . begin ();
typename ContainerT :: const_iterator itEnd = container . end ();
for (; it != itEnd ; ++ it )
delete * it ;
}
template < typename AssociativeContainerT >
2012-05-09 19:04:00 +01:00
inline void deleteAllValues ( AssociativeContainerT & container ) {
2011-05-24 08:23:02 +01:00
typename AssociativeContainerT :: const_iterator it = container . begin ();
typename AssociativeContainerT :: const_iterator itEnd = container . end ();
for (; it != itEnd ; ++ it )
delete it -> second ;
}
template < typename ContainerT , typename Function >
2012-05-09 19:04:00 +01:00
inline void forEach ( ContainerT & container , Function function ) {
2011-05-24 08:23:02 +01:00
std :: for_each ( container . begin (), container . end (), function );
}
template < typename ContainerT , typename Function >
2012-05-09 19:04:00 +01:00
inline void forEach ( const ContainerT & container , Function function ) {
2011-05-24 08:23:02 +01:00
std :: for_each ( container . begin (), container . end (), function );
}
2012-08-23 20:08:50 +01: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 08:23:50 +01: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 ;
}
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 21:39:38 +00:00
os << "s" ;
2012-08-24 08:23:50 +01:00
return os ;
}
std :: size_t m_count ;
std :: string m_label ;
};
2012-08-23 20:08:50 +01:00
2012-05-16 15:09:17 +01:00
struct SourceLineInfo {
2012-05-09 19:04:00 +01:00
SourceLineInfo () : line ( 0 ){}
2012-05-11 19:06:43 +01:00
SourceLineInfo ( const std :: string & _file , std :: size_t _line )
: file ( _file ),
line ( _line )
2012-02-15 18:37:21 +00:00
{}
2012-05-09 19:04:00 +01:00
SourceLineInfo ( const SourceLineInfo & other )
: file ( other . file ),
line ( other . line )
{}
2012-10-28 12:07:17 +00:00
bool empty () const {
return file . empty ();
}
2012-02-15 18:37:21 +00:00
std :: string file ;
std :: size_t line ;
};
2012-05-09 19:04:00 +01:00
inline std :: ostream & operator << ( std :: ostream & os , const SourceLineInfo & info ) {
2012-02-15 18:37:21 +00:00
#ifndef __GNUG__
os << info . file << "(" << info . line << "): " ;
#else
os << info . file << ":" << info . line << ": " ;
#endif
return os ;
}
2012-08-13 07:46:10 +01:00
CATCH_ATTRIBUTE_NORETURN
inline void throwLogicError ( const std :: string & message , const SourceLineInfo & locationInfo ) {
2011-05-24 08:23:02 +01:00
std :: ostringstream oss ;
2012-08-13 07:46:10 +01:00
oss << "Internal Catch error: '" << message << "' at: " << locationInfo ;
2011-05-24 08:23:02 +01:00
throw std :: logic_error ( oss . str () );
}
}
2012-08-13 07:46:10 +01:00
#define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) )
#define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO );
2011-05-24 08:23:02 +01:00
2012-08-09 07:47:30 +01:00
#include <ostream>
namespace Catch {
class NotImplementedException : public std :: exception
{
public :
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 08:10:36 +01:00
// #included from: catch_interfaces_generators.h
#define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED
2012-08-09 07:47:30 +01:00
2012-08-31 08:10:36 +01:00
#include <string>
2012-02-25 09:39:45 +00:00
2012-05-16 15:09:17 +01:00
namespace Catch {
2012-08-31 08:10:36 +01:00
struct IGeneratorInfo {
virtual ~ IGeneratorInfo ();
virtual bool moveNext () = 0 ;
virtual std :: size_t getCurrentIndex () const = 0 ;
2012-02-25 09:39:45 +00:00
};
2012-08-31 08:10:36 +01:00
struct IGeneratorsForTest {
virtual ~ IGeneratorsForTest ();
2012-05-16 15:09:17 +01:00
2012-08-31 08:10:36 +01:00
virtual IGeneratorInfo & getGeneratorInfo ( const std :: string & fileInfo , std :: size_t size ) = 0 ;
virtual bool moveNext () = 0 ;
2012-02-25 09:39:45 +00:00
};
2012-08-31 08:10:36 +01:00
IGeneratorsForTest * createGeneratorsForTest ();
} // end namespace Catch
#include <memory>
#include <vector>
#include <stdlib.h>
namespace Catch {
2012-12-01 23:57:18 +00:00
class TestCase ;
2012-09-26 18:38:26 +01:00
class Stream ;
2012-08-31 08:10:36 +01: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 ;
};
IContext & getCurrentContext ();
IMutableContext & getCurrentMutableContext ();
void cleanUpContext ();
2012-09-26 18:38:26 +01:00
Stream createStream ( const std :: string & streamName );
2012-08-31 08:10:36 +01:00
2012-02-25 09:39:45 +00:00
}
2012-08-31 08:10:36 +01:00
// #included from: internal/catch_test_registry.hpp
2012-09-17 01:42:29 -04:00
#define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED
2012-08-31 08:10:36 +01:00
// #included from: catch_interfaces_testcase.h
#define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED
2012-05-05 19:35:35 +01:00
// #included from: catch_ptr.hpp
2012-08-09 07:47:30 +01:00
#define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED
2012-05-05 19:35:35 +01:00
2012-05-16 15:09:17 +01:00
namespace Catch {
2012-05-05 19:35:35 +01:00
// An intrusive reference counting smart pointer.
// T must implement addRef() and release() methods
// typically implementing the IShared interface
template < typename T >
2012-05-16 15:09:17 +01:00
class Ptr {
2012-05-05 19:35:35 +01:00
public :
Ptr () : m_p ( NULL ){}
Ptr ( T * p ) : m_p ( p ){
2012-07-28 20:37:07 +01:00
if ( m_p )
m_p -> addRef ();
2012-05-05 19:35:35 +01:00
}
2012-12-01 23:57:18 +00:00
Ptr ( Ptr const & other ) : m_p ( other . m_p ){
2012-07-28 20:37:07 +01:00
if ( m_p )
m_p -> addRef ();
2012-05-05 19:35:35 +01:00
}
~ Ptr (){
if ( m_p )
m_p -> release ();
}
2012-12-06 08:44:51 +00:00
void reset () {
if ( m_p )
m_p -> release ();
m_p = NULL ;
}
2012-05-05 19:35:35 +01:00
Ptr & operator = ( T * p ){
Ptr temp ( p );
swap ( temp );
return * this ;
}
2012-12-01 23:57:18 +00:00
Ptr & operator = ( Ptr const & other ){
2012-05-05 19:35:35 +01:00
Ptr temp ( other );
swap ( temp );
return * this ;
}
2012-12-01 23:57:18 +00:00
void swap ( Ptr & other ) { std :: swap ( m_p , other . m_p ); }
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 08:44:51 +00:00
operator SafeBool :: type () const { return SafeBool :: makeSafe ( m_p != NULL ); }
2012-05-05 19:35:35 +01:00
private :
T * m_p ;
};
struct IShared : NonCopyable {
2012-08-13 07:46:10 +01:00
virtual ~ IShared ();
2012-12-01 23:57:18 +00:00
virtual void addRef () const = 0 ;
virtual void release () const = 0 ;
2012-05-05 19:35:35 +01:00
};
2012-12-01 23:57:18 +00:00
template < typename T = IShared >
2012-05-05 19:35:35 +01:00
struct SharedImpl : T {
SharedImpl () : m_rc ( 0 ){}
2012-12-01 23:57:18 +00:00
virtual void addRef () const {
2012-05-05 19:35:35 +01:00
++ m_rc ;
}
2012-12-01 23:57:18 +00:00
virtual void release () const {
2012-05-05 19:35:35 +01:00
if ( -- m_rc == 0 )
delete this ;
}
2012-12-01 23:57:18 +00:00
mutable unsigned int m_rc ;
2012-05-05 19:35:35 +01:00
};
} // end namespace Catch
2012-06-02 23:12:42 +01:00
#include <vector>
namespace Catch {
2012-08-23 20:08:50 +01:00
class TestCaseFilters ;
2012-08-16 18:48:50 +01:00
struct ITestCase : IShared {
2012-06-02 23:12:42 +01:00
virtual void invoke () const = 0 ;
2012-08-16 18:48:50 +01:00
protected :
virtual ~ ITestCase ();
2012-06-02 23:12:42 +01:00
};
2012-12-01 23:57:18 +00:00
class TestCase ;
2012-06-02 23:12:42 +01:00
struct ITestCaseRegistry {
2012-08-13 07:46:10 +01:00
virtual ~ ITestCaseRegistry ();
2012-12-01 23:57:18 +00:00
virtual const std :: vector < TestCase >& getAllTests () const = 0 ;
virtual std :: vector < TestCase > getMatchingTestCases ( const std :: string & rawTestSpec ) const = 0 ;
2012-06-02 23:12:42 +01:00
};
}
2012-05-16 15:09:17 +01:00
namespace Catch {
2011-05-24 08:23:02 +01:00
template < typename C >
2012-08-16 18:48:50 +01:00
class MethodTestCase : public SharedImpl < ITestCase > {
2012-05-16 15:09:17 +01:00
2012-05-11 08:17:16 +01:00
public :
MethodTestCase ( void ( C ::* method )() ) : m_method ( method ) {}
2011-05-24 08:23:02 +01:00
2012-05-11 08:17:16 +01:00
virtual void invoke () const {
2011-05-24 08:23:02 +01:00
C obj ;
( obj . * m_method )();
}
private :
2012-08-16 18:48:50 +01:00
virtual ~ MethodTestCase () {}
2011-05-24 08:23:02 +01:00
void ( C ::* m_method )();
};
typedef void ( * TestFunction )();
2012-05-16 15:09:17 +01:00
struct AutoReg {
2012-05-11 08:17:16 +01:00
AutoReg ( TestFunction function ,
const char * name ,
const char * description ,
const SourceLineInfo & lineInfo );
2011-05-24 08:23:02 +01:00
template < typename C >
2012-05-11 08:17:16 +01:00
AutoReg ( void ( C ::* method )(),
2012-11-04 21:39:38 +00:00
const char * className ,
2012-05-11 08:17:16 +01:00
const char * name ,
const char * description ,
const SourceLineInfo & lineInfo ) {
2012-11-04 21:39:38 +00:00
registerTestCase ( new MethodTestCase < C > ( method ), className , name , description , lineInfo );
2011-05-24 08:23:02 +01:00
}
2012-05-11 08:17:16 +01:00
void registerTestCase ( ITestCase * testCase ,
2012-11-04 21:39:38 +00:00
const char * className ,
2012-05-11 08:17:16 +01:00
const char * name ,
const char * description ,
const SourceLineInfo & lineInfo );
2011-05-24 08:23:02 +01:00
2012-05-11 08:17:16 +01:00
~ AutoReg ();
2011-05-24 08:23:02 +01:00
private :
2012-05-11 08:17:16 +01:00
AutoReg ( const AutoReg & );
void operator = ( const AutoReg & );
2011-05-24 08:23:02 +01:00
};
} // end namespace Catch
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_TESTCASE( Name, Desc ) \
2012-05-09 19:04:00 +01: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 08:23:02 +01:00
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_TESTCASE_NORETURN( Name, Desc ) \
2012-08-13 07:46:10 +01:00
static void INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ )() CATCH_ATTRIBUTE_NORETURN; \
2012-05-09 19:04:00 +01: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 08:23:02 +01:00
///////////////////////////////////////////////////////////////////////////////
2012-07-20 18:43:48 +01:00
#define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \
2012-11-04 21:39:38 +00:00
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Name, Desc, CATCH_INTERNAL_LINEINFO ); }
2011-05-24 08:23:02 +01:00
///////////////////////////////////////////////////////////////////////////////
#define TEST_CASE_METHOD( ClassName, TestName, Desc )\
2011-12-28 19:56:39 +00:00
namespace{ \
2012-05-09 19:04:00 +01:00
struct INTERNAL_CATCH_UNIQUE_NAME( TestCaseMethod_catch_internal_ ) : ClassName{ \
2011-12-28 19:56:39 +00:00
void test(); \
}; \
2012-11-04 21:39:38 +00: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 19:56:39 +00:00
} \
2012-05-09 19:04:00 +01:00
void INTERNAL_CATCH_UNIQUE_NAME( TestCaseMethod_catch_internal_ )::test()
2011-05-24 08:23:02 +01:00
// #included from: internal/catch_capture.hpp
2012-08-09 07:47:30 +01:00
#define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
2011-05-24 08:23:02 +01:00
2012-10-28 12:07:17 +00:00
// #included from: catch_expression_decomposer.hpp
#define TWOBLUECUBES_CATCH_EXPRESSION_DECOMPOSER_HPP_INCLUDED
2012-05-16 15:09:17 +01:00
2012-10-28 12:07:17 +00:00
// #included from: catch_expression_lhs.hpp
#define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED
2012-05-11 08:17:16 +01:00
2012-10-28 12:07:17 +00:00
// #included from: catch_expressionresult_builder.h
#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_BUILDER_H_INCLUDED
2012-05-09 19:04:00 +01:00
// #included from: catch_tostring.hpp
2012-08-09 07:47:30 +01:00
#define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED
2012-05-09 19:04:00 +01:00
#include <sstream>
2012-08-01 08:17:07 +01:00
#ifdef __OBJC__
// #included from: catch_objc_arc.hpp
2012-08-09 07:47:30 +01:00
#define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED
2012-08-01 08:17:07 +01: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 18:48:50 +01:00
#ifdef __clang__
2012-08-01 08:17:07 +01:00
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
2012-08-16 18:48:50 +01:00
#endif
2012-08-01 08:17:07 +01:00
if ( [ obj respondsToSelector : sel ] )
return [ obj performSelector : sel ];
2012-08-16 18:48:50 +01:00
#ifdef __clang__
2012-08-01 08:17:07 +01:00
#pragma clang diagnostic pop
2012-08-16 18:48:50 +01:00
#endif
2012-08-01 08:17:07 +01:00
return nil ;
}
#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained
#define CATCH_ARC_STRONG __strong
#endif
#endif
2012-05-16 15:09:17 +01:00
namespace Catch {
namespace Detail {
2012-05-09 19:04:00 +01:00
struct NonStreamable {
template < typename T > NonStreamable ( const T & ){}
};
// 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 , NonStreamable ){
return ss << "{?}" ;
}
template < typename T >
inline std :: string makeString ( const T & value ) {
std :: ostringstream oss ;
oss << value ;
return oss . str ();
}
template < typename T >
inline std :: string makeString ( T * p ) {
if ( ! p )
return INTERNAL_CATCH_STRINGIFY ( NULL );
std :: ostringstream oss ;
oss << p ;
return oss . str ();
}
template < typename T >
inline std :: string makeString ( const T * p ) {
if ( ! p )
return INTERNAL_CATCH_STRINGIFY ( NULL );
std :: ostringstream oss ;
oss << p ;
return oss . str ();
}
} // 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 ) {
return Detail :: makeString ( value );
}
// 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 19:06:43 +01:00
return toString ( static_cast < unsigned long > ( value ) );
2012-05-09 19:04:00 +01:00
}
inline std :: string toString ( const double value ) {
std :: ostringstream oss ;
oss << value ;
return oss . str ();
}
inline std :: string toString ( bool value ) {
return value ? "true" : "false" ;
}
2012-06-06 08:06:40 +01:00
inline std :: string toString ( char value ) {
return value < ' '
2012-12-14 07:50:08 +00:00
? toString ( static_cast < unsigned int > ( value ) )
2012-06-06 08:06:40 +01:00
: Detail :: makeString ( value );
}
inline std :: string toString ( signed char value ) {
return toString ( static_cast < char > ( value ) );
}
2012-12-14 07:50:08 +00:00
inline std :: string toString ( unsigned char value ) {
return toString ( static_cast < char > ( value ) );
}
2012-05-11 08:17:16 +01:00
#ifdef CATCH_CONFIG_CPP11_NULLPTR
2012-05-25 08:52:05 +01:00
inline std :: string toString ( std :: nullptr_t ) {
2012-05-11 08:17:16 +01:00
return "nullptr" ;
}
#endif
2012-08-01 08:17:07 +01:00
#ifdef __OBJC__
inline std :: string toString ( NSString const * const & nsstring ) {
return std :: string ( "@ \" " ) + [ nsstring UTF8String ] + " \" " ;
}
inline std :: string toString ( NSString * CATCH_ARC_STRONG const & nsstring ) {
return std :: string ( "@ \" " ) + [ nsstring UTF8String ] + " \" " ;
}
inline std :: string toString ( NSObject * const & nsObject ) {
return toString ( [ nsObject description ] );
}
#endif
2012-05-09 19:04:00 +01:00
} // end namespace Catch
2012-10-28 12:07:17 +00:00
// #included from: catch_assertionresult.h
#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED
2011-05-24 08:23:02 +01:00
#include <string>
// #included from: catch_result_type.h
2012-08-09 07:47:30 +01:00
#define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED
2011-05-24 08:23:02 +01:00
2012-05-16 15:09:17 +01:00
namespace Catch {
2011-05-24 08:23:02 +01:00
2012-11-13 21:46:01 +00:00
// ResultWas::OfType enum
2012-11-10 18:46:39 +00:00
struct ResultWas { enum OfType {
Unknown = - 1 ,
Ok = 0 ,
Info = 1 ,
Warning = 2 ,
2011-05-24 08:23:02 +01:00
2012-11-10 18:46:39 +00:00
FailureBit = 0x10 ,
2011-05-24 08:23:02 +01:00
2012-11-10 18:46:39 +00:00
ExpressionFailed = FailureBit | 1 ,
ExplicitFailure = FailureBit | 2 ,
2011-05-24 08:23:02 +01:00
2012-11-10 18:46:39 +00:00
Exception = 0x100 | FailureBit ,
2011-05-24 08:23:02 +01:00
2012-11-10 18:46:39 +00:00
ThrewException = Exception | 1 ,
DidntThrowException = Exception | 2
2011-05-24 08:23:02 +01:00
2012-11-10 18:46:39 +00:00
}; };
2011-05-24 08:23:02 +01:00
2012-11-10 18:46:39 +00:00
inline bool isOk ( ResultWas :: OfType resultType ) {
return ( resultType & ResultWas :: FailureBit ) == 0 ;
}
2012-10-09 11:48:55 +01:00
2012-11-13 21:46:01 +00:00
// ResultAction::Value enum
2012-11-10 18:46:39 +00: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 08:23:02 +01:00
2012-11-13 21:46:01 +00:00
// ResultDisposition::Flags enum
struct ResultDisposition { enum Flags {
2012-11-10 18:46:39 +00:00
Normal = 0x00 ,
2012-11-13 21:46:01 +00: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 18:46:39 +00:00
inline ResultDisposition :: Flags operator | ( ResultDisposition :: Flags lhs , ResultDisposition :: Flags rhs ) {
return static_cast < ResultDisposition :: Flags > ( static_cast < int > ( lhs ) | static_cast < int > ( rhs ) );
}
2012-11-17 10:49:24 +00:00
inline bool shouldContinueOnFailure ( int flags ) { return ( flags & ResultDisposition :: ContinueOnFailure ) != 0 ; }
inline bool shouldNegate ( int flags ) { return ( flags & ResultDisposition :: NegateResult ) != 0 ; }
inline bool shouldSuppressFailure ( int flags ) { return ( flags & ResultDisposition :: SuppressFail ) != 0 ; }
2012-11-10 18:46:39 +00:00
} // end namespace Catch
2011-05-24 08:23:02 +01:00
2012-05-16 15:09:17 +01:00
namespace Catch {
2011-05-24 08:23:02 +01:00
2012-10-28 12:07:17 +00:00
struct AssertionInfo
2012-10-09 11:48:55 +01:00
{
2012-10-28 12:07:17 +00:00
AssertionInfo () {}
2012-11-13 09:44:52 +00:00
AssertionInfo ( const std :: string & _macroName ,
const SourceLineInfo & _lineInfo ,
const std :: string & _capturedExpression ,
ResultDisposition :: Flags _resultDisposition );
2012-10-09 11:48:55 +01:00
std :: string macroName ;
SourceLineInfo lineInfo ;
std :: string capturedExpression ;
2012-11-13 09:44:52 +00:00
ResultDisposition :: Flags resultDisposition ;
2012-10-28 12:07:17 +00:00
};
struct AssertionResultData
{
AssertionResultData () : resultType ( ResultWas :: Unknown ) {}
2012-10-09 11:48:55 +01:00
std :: string reconstructedExpression ;
std :: string message ;
ResultWas :: OfType resultType ;
};
2012-10-28 12:07:17 +00:00
class AssertionResult {
2012-05-16 15:09:17 +01:00
public :
2012-10-28 12:07:17 +00:00
AssertionResult ();
AssertionResult ( const AssertionInfo & info , const AssertionResultData & data );
~ AssertionResult ();
2011-05-24 08:23:02 +01:00
2012-11-13 09:44:52 +00:00
bool isOk () const ;
bool succeeded () const ;
2012-08-09 07:47:30 +01:00
ResultWas :: OfType getResultType () const ;
bool hasExpression () const ;
bool hasMessage () const ;
std :: string getExpression () const ;
bool hasExpandedExpression () const ;
std :: string getExpandedExpression () const ;
std :: string getMessage () const ;
2012-10-28 12:07:17 +00:00
SourceLineInfo getSourceInfo () const ;
2012-08-09 07:47:30 +01:00
std :: string getTestMacroName () const ;
2011-05-24 08:23:02 +01:00
protected :
2012-10-28 12:07:17 +00:00
AssertionInfo m_info ;
AssertionResultData m_resultData ;
2011-05-24 08:23:02 +01:00
};
} // end namespace Catch
// #included from: catch_evaluate.hpp
2012-08-09 07:47:30 +01:00
#define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED
2011-05-24 08:23:02 +01:00
2012-05-16 15:09:17 +01:00
namespace Catch {
namespace Internal {
enum Operator {
2011-05-24 08:23:02 +01:00
IsEqualTo ,
IsNotEqualTo ,
IsLessThan ,
IsGreaterThan ,
IsLessThanOrEqualTo ,
IsGreaterThanOrEqualTo
};
2012-05-21 18:52:09 +01:00
template < Operator Op > struct OperatorTraits { static const char * getName (){ return "*error*" ; } };
template <> struct OperatorTraits < IsEqualTo > { static const char * getName (){ return "==" ; } };
template <> struct OperatorTraits < IsNotEqualTo > { static const char * getName (){ return "!=" ; } };
template <> struct OperatorTraits < IsLessThan > { static const char * getName (){ return "<" ; } };
template <> struct OperatorTraits < IsGreaterThan > { static const char * getName (){ return ">" ; } };
template <> struct OperatorTraits < IsLessThanOrEqualTo > { static const char * getName (){ return "<=" ; } };
template <> struct OperatorTraits < IsGreaterThanOrEqualTo > { static const char * getName (){ return ">=" ; } };
2011-05-24 08:23:02 +01:00
// So the compare overloads can be operator agnostic we convey the operator as a template
// enum, which is used to specialise an Evaluator for doing the comparison.
template < typename T1 , typename T2 , Operator Op >
class Evaluator {};
template < typename T1 , typename T2 >
2012-05-16 15:09:17 +01:00
struct Evaluator < T1 , T2 , IsEqualTo > {
static bool evaluate ( const T1 & lhs , const T2 & rhs ) {
2012-05-09 19:04:00 +01:00
return const_cast < T1 &> ( lhs ) == const_cast < T2 &> ( rhs );
2011-05-24 08:23:02 +01:00
}
};
template < typename T1 , typename T2 >
2012-05-16 15:09:17 +01:00
struct Evaluator < T1 , T2 , IsNotEqualTo > {
static bool evaluate ( const T1 & lhs , const T2 & rhs ) {
2011-05-24 08:23:02 +01:00
return const_cast < T1 &> ( lhs ) != const_cast < T2 &> ( rhs );
}
};
template < typename T1 , typename T2 >
2012-05-16 15:09:17 +01:00
struct Evaluator < T1 , T2 , IsLessThan > {
static bool evaluate ( const T1 & lhs , const T2 & rhs ) {
2011-05-24 08:23:02 +01:00
return const_cast < T1 &> ( lhs ) < const_cast < T2 &> ( rhs );
}
};
template < typename T1 , typename T2 >
2012-05-16 15:09:17 +01:00
struct Evaluator < T1 , T2 , IsGreaterThan > {
static bool evaluate ( const T1 & lhs , const T2 & rhs ) {
2011-05-24 08:23:02 +01:00
return const_cast < T1 &> ( lhs ) > const_cast < T2 &> ( rhs );
}
};
template < typename T1 , typename T2 >
2012-05-16 15:09:17 +01:00
struct Evaluator < T1 , T2 , IsGreaterThanOrEqualTo > {
static bool evaluate ( const T1 & lhs , const T2 & rhs ) {
2011-05-24 08:23:02 +01:00
return const_cast < T1 &> ( lhs ) >= const_cast < T2 &> ( rhs );
}
};
template < typename T1 , typename T2 >
2012-05-16 15:09:17 +01:00
struct Evaluator < T1 , T2 , IsLessThanOrEqualTo > {
static bool evaluate ( const T1 & lhs , const T2 & rhs ) {
2011-05-24 08:23:02 +01:00
return const_cast < T1 &> ( lhs ) <= const_cast < T2 &> ( rhs );
}
};
template < Operator Op , typename T1 , typename T2 >
2012-05-16 15:09:17 +01:00
bool applyEvaluator ( const T1 & lhs , const T2 & rhs ) {
2011-05-24 08:23:02 +01:00
return Evaluator < T1 , T2 , Op >:: evaluate ( lhs , rhs );
}
2012-11-06 19:13:25 +00:00
// This level of indirection allows us to specialise for integer types
// to avoid signed/ unsigned warnings
2011-05-24 08:23:02 +01:00
// "base" overload
template < Operator Op , typename T1 , typename T2 >
2012-05-16 15:09:17 +01:00
bool compare ( const T1 & lhs , const T2 & rhs ) {
2011-05-24 08:23:02 +01:00
return Evaluator < T1 , T2 , Op >:: evaluate ( lhs , rhs );
}
// unsigned X to int
2012-05-16 15:09:17 +01:00
template < Operator Op > bool compare ( unsigned int lhs , int rhs ) {
2011-05-24 08:23:02 +01:00
return applyEvaluator < Op > ( lhs , static_cast < unsigned int > ( rhs ) );
}
2012-05-16 15:09:17 +01:00
template < Operator Op > bool compare ( unsigned long lhs , int rhs ) {
2011-05-24 08:23:02 +01:00
return applyEvaluator < Op > ( lhs , static_cast < unsigned int > ( rhs ) );
}
2012-05-16 15:09:17 +01:00
template < Operator Op > bool compare ( unsigned char lhs , int rhs ) {
2011-05-24 08:23:02 +01:00
return applyEvaluator < Op > ( lhs , static_cast < unsigned int > ( rhs ) );
}
// unsigned X to long
2012-05-16 15:09:17 +01:00
template < Operator Op > bool compare ( unsigned int lhs , long rhs ) {
2011-05-24 08:23:02 +01:00
return applyEvaluator < Op > ( lhs , static_cast < unsigned long > ( rhs ) );
}
2012-05-16 15:09:17 +01:00
template < Operator Op > bool compare ( unsigned long lhs , long rhs ) {
2011-05-24 08:23:02 +01:00
return applyEvaluator < Op > ( lhs , static_cast < unsigned long > ( rhs ) );
}
2012-05-16 15:09:17 +01:00
template < Operator Op > bool compare ( unsigned char lhs , long rhs ) {
2011-05-24 08:23:02 +01:00
return applyEvaluator < Op > ( lhs , static_cast < unsigned long > ( rhs ) );
}
// int to unsigned X
2012-05-16 15:09:17 +01:00
template < Operator Op > bool compare ( int lhs , unsigned int rhs ) {
2011-05-24 08:23:02 +01:00
return applyEvaluator < Op > ( static_cast < unsigned int > ( lhs ), rhs );
}
2012-05-16 15:09:17 +01:00
template < Operator Op > bool compare ( int lhs , unsigned long rhs ) {
2011-05-24 08:23:02 +01:00
return applyEvaluator < Op > ( static_cast < unsigned int > ( lhs ), rhs );
}
2012-05-16 15:09:17 +01:00
template < Operator Op > bool compare ( int lhs , unsigned char rhs ) {
2011-05-24 08:23:02 +01:00
return applyEvaluator < Op > ( static_cast < unsigned int > ( lhs ), rhs );
}
// long to unsigned X
2012-05-16 15:09:17 +01:00
template < Operator Op > bool compare ( long lhs , unsigned int rhs ) {
2012-04-27 14:42:40 -03:00
return applyEvaluator < Op > ( static_cast < unsigned long > ( lhs ), rhs );
2011-05-24 08:23:02 +01:00
}
2012-05-16 15:09:17 +01:00
template < Operator Op > bool compare ( long lhs , unsigned long rhs ) {
2012-04-27 14:42:40 -03:00
return applyEvaluator < Op > ( static_cast < unsigned long > ( lhs ), rhs );
2011-05-24 08:23:02 +01:00
}
2012-05-16 15:09:17 +01:00
template < Operator Op > bool compare ( long lhs , unsigned char rhs ) {
2012-04-27 14:42:40 -03:00
return applyEvaluator < Op > ( static_cast < unsigned long > ( lhs ), rhs );
2011-05-24 08:23:02 +01:00
}
2012-05-25 08:52:05 +01:00
// pointer to long (when comparing against NULL)
2012-11-06 19:13:25 +00:00
template < Operator Op , typename T > bool compare ( long lhs , T * rhs ) {
2011-05-24 08:23:02 +01:00
return Evaluator < T * , T * , Op >:: evaluate ( reinterpret_cast < T *> ( lhs ), rhs );
2012-05-07 19:46:19 +01:00
}
2012-11-06 19:13:25 +00:00
template < Operator Op , typename T > bool compare ( T * lhs , long rhs ) {
2012-05-07 19:46:19 +01:00
return Evaluator < T * , T * , Op >:: evaluate ( lhs , reinterpret_cast < T *> ( rhs ) );
2011-05-24 08:23:02 +01:00
}
2012-05-25 08:52:05 +01:00
// pointer to int (when comparing against NULL)
2012-11-06 19:13:25 +00:00
template < Operator Op , typename T > bool compare ( int lhs , T * rhs ) {
2012-05-25 08:52:05 +01:00
return Evaluator < T * , T * , Op >:: evaluate ( reinterpret_cast < T *> ( lhs ), rhs );
}
2012-11-06 19:13:25 +00:00
template < Operator Op , typename T > bool compare ( T * lhs , int rhs ) {
2012-05-25 08:52:05 +01:00
return Evaluator < T * , T * , Op >:: evaluate ( lhs , reinterpret_cast < T *> ( rhs ) );
}
2011-05-24 08:23:02 +01:00
} // end of namespace Internal
} // end of namespace Catch
2012-05-16 15:09:17 +01:00
namespace Catch {
2011-12-28 10:37:31 +00:00
2012-10-28 12:07:17 +00: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 08:23:02 +01:00
public :
2012-10-28 12:07:17 +00:00
ExpressionResultBuilder ( ResultWas :: OfType resultType = ResultWas :: Unknown );
ExpressionResultBuilder ( const ExpressionResultBuilder & other );
ExpressionResultBuilder & operator = ( const ExpressionResultBuilder & other );
2012-05-09 19:04:00 +01:00
2012-10-28 12:07:17 +00: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 21:22:36 +00:00
2012-11-10 18:46:39 +00:00
ExpressionResultBuilder & endExpression ( ResultDisposition :: Flags resultDisposition );
2012-10-09 11:48:55 +01:00
2012-10-28 12:07:17 +00:00
template < typename T >
ExpressionResultBuilder & operator << ( const T & value ) {
m_stream << value ;
return * this ;
2012-10-09 11:48:55 +01:00
}
2012-10-28 12:07:17 +00:00
std :: string reconstructExpression ( const AssertionInfo & info ) const ;
AssertionResult buildResult ( const AssertionInfo & info ) const ;
2011-05-24 08:23:02 +01:00
private :
2012-10-28 12:07:17 +00: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 08:23:02 +01:00
};
2012-05-09 19:04:00 +01:00
} // end namespace Catch
2012-05-16 15:09:17 +01:00
namespace Catch {
2012-05-11 08:17:16 +01:00
2012-10-28 20:57:21 +00:00
struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison ;
2012-10-28 12:07:17 +00: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 08:17:16 +01:00
template < typename T >
2012-10-28 12:07:17 +00:00
class ExpressionLhs {
void operator = ( const ExpressionLhs & );
2012-05-11 08:17:16 +01:00
public :
2012-11-16 10:47:33 +01:00
ExpressionLhs ( T lhs ) : m_lhs ( lhs ) {}
2012-05-11 08:17:16 +01:00
template < typename RhsT >
2012-10-28 12:07:17 +00:00
ExpressionResultBuilder & operator == ( const RhsT & rhs ) {
2012-10-09 20:58:33 +01:00
return captureExpression < Internal :: IsEqualTo > ( rhs );
2012-05-11 08:17:16 +01:00
}
template < typename RhsT >
2012-10-28 12:07:17 +00:00
ExpressionResultBuilder & operator != ( const RhsT & rhs ) {
2012-10-09 20:58:33 +01:00
return captureExpression < Internal :: IsNotEqualTo > ( rhs );
2012-05-11 08:17:16 +01:00
}
template < typename RhsT >
2012-10-28 12:07:17 +00:00
ExpressionResultBuilder & operator < ( const RhsT & rhs ) {
2012-10-09 20:58:33 +01:00
return captureExpression < Internal :: IsLessThan > ( rhs );
2012-05-11 08:17:16 +01:00
}
template < typename RhsT >
2012-10-28 12:07:17 +00:00
ExpressionResultBuilder & operator > ( const RhsT & rhs ) {
2012-10-09 20:58:33 +01:00
return captureExpression < Internal :: IsGreaterThan > ( rhs );
2012-05-11 08:17:16 +01:00
}
template < typename RhsT >
2012-10-28 12:07:17 +00:00
ExpressionResultBuilder & operator <= ( const RhsT & rhs ) {
2012-10-09 20:58:33 +01:00
return captureExpression < Internal :: IsLessThanOrEqualTo > ( rhs );
2012-05-11 08:17:16 +01:00
}
template < typename RhsT >
2012-10-28 12:07:17 +00:00
ExpressionResultBuilder & operator >= ( const RhsT & rhs ) {
2012-10-09 20:58:33 +01:00
return captureExpression < Internal :: IsGreaterThanOrEqualTo > ( rhs );
2012-05-11 08:17:16 +01:00
}
2012-10-28 12:07:17 +00:00
ExpressionResultBuilder & operator == ( bool rhs ) {
2012-10-09 20:58:33 +01:00
return captureExpression < Internal :: IsEqualTo > ( rhs );
2012-05-11 08:17:16 +01:00
}
2012-10-28 12:07:17 +00:00
ExpressionResultBuilder & operator != ( bool rhs ) {
2012-10-09 20:58:33 +01:00
return captureExpression < Internal :: IsNotEqualTo > ( rhs );
2012-05-11 08:17:16 +01:00
}
2012-11-10 18:46:39 +00:00
ExpressionResultBuilder & endExpression ( ResultDisposition :: Flags resultDisposition ) {
2012-10-28 20:57:21 +00:00
bool value = m_lhs ? true : false ;
return m_result
. setLhs ( Catch :: toString ( value ) )
. setResultType ( value )
2012-11-10 18:46:39 +00:00
. endExpression ( resultDisposition );
2012-05-11 08:17:16 +01:00
}
2012-10-28 12:07:17 +00: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 08:17:16 +01:00
2012-10-09 20:58:33 +01:00
private :
template < Internal :: Operator Op , typename RhsT >
2012-10-28 12:07:17 +00:00
ExpressionResultBuilder & captureExpression ( const RhsT & rhs ) {
2012-10-09 20:58:33 +01:00
return m_result
2012-10-28 12:07:17 +00:00
. setResultType ( Internal :: compare < Op > ( m_lhs , rhs ) )
2012-10-28 20:57:21 +00:00
. setLhs ( Catch :: toString ( m_lhs ) )
2012-10-09 20:58:33 +01:00
. setRhs ( Catch :: toString ( rhs ) )
. setOp ( Internal :: OperatorTraits < Op >:: getName () );
}
2012-05-11 08:17:16 +01:00
private :
2012-10-28 12:07:17 +00:00
ExpressionResultBuilder m_result ;
2012-05-11 08:17:16 +01:00
T m_lhs ;
};
} // end namespace Catch
2012-05-16 15:09:17 +01:00
namespace Catch {
2012-10-28 12:07:17 +00:00
// Captures the LHS of the expression and wraps it in an Expression Lhs object
class ExpressionDecomposer {
2012-05-16 15:09:17 +01:00
public :
template < typename T >
2012-10-28 12:07:17 +00:00
ExpressionLhs < const T &> operator ->* ( const T & operand ) {
return ExpressionLhs < const T &> ( operand );
2012-05-16 15:09:17 +01:00
}
2012-10-28 12:07:17 +00:00
ExpressionLhs < bool > operator ->* ( bool value ) {
return ExpressionLhs < bool > ( value );
2012-05-16 15:09:17 +01:00
}
};
} // end namespace Catch
2012-05-09 19:04:00 +01:00
// #included from: catch_interfaces_capture.h
2012-08-09 07:47:30 +01:00
#define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED
2012-05-09 19:04:00 +01:00
#include <string>
2012-08-31 08:10:36 +01:00
// #included from: catch_totals.hpp
#define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED
2012-09-29 20:54:03 +01:00
#include <cstddef>
2012-08-31 08:10:36 +01:00
namespace Catch {
struct Counts {
2012-11-21 18:06:13 +00:00
Counts () : passed ( 0 ), failed ( 0 ), info ( 0 ) {}
2012-08-31 08:10:36 +01:00
Counts operator - ( const Counts & other ) const {
Counts diff ;
diff . passed = passed - other . passed ;
diff . failed = failed - other . failed ;
2012-11-21 18:06:13 +00:00
diff . info = info - other . info ;
2012-08-31 08:10:36 +01:00
return diff ;
}
Counts & operator += ( const Counts & other ) {
passed += other . passed ;
failed += other . failed ;
2012-11-21 18:06:13 +00:00
info += other . info ;
2012-08-31 08:10:36 +01:00
return * this ;
}
std :: size_t total () const {
return passed + failed ;
}
std :: size_t passed ;
std :: size_t failed ;
2012-11-21 18:06:13 +00:00
std :: size_t info ;
2012-08-31 08:10:36 +01:00
};
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 ;
};
}
2012-05-09 19:04:00 +01:00
2012-05-16 15:09:17 +01:00
namespace Catch {
2012-12-01 23:57:18 +00:00
class TestCase ;
2012-05-09 19:04:00 +01:00
class ScopedInfo ;
2012-10-28 12:07:17 +00:00
class ExpressionResultBuilder ;
class AssertionResult ;
struct AssertionInfo ;
2012-12-01 23:57:18 +00:00
struct SectionInfo ;
2012-05-09 19:04:00 +01:00
2012-05-16 15:09:17 +01:00
struct IResultCapture {
2012-05-09 19:04:00 +01:00
2012-08-13 07:46:10 +01:00
virtual ~ IResultCapture ();
2012-05-09 19:04:00 +01:00
2012-12-01 23:57:18 +00:00
virtual void testEnded ( AssertionResult const & result ) = 0 ;
virtual bool sectionStarted ( SectionInfo const & sectionInfo ,
2012-05-16 15:09:17 +01:00
Counts & assertions ) = 0 ;
2012-12-01 23:57:18 +00:00
virtual void sectionEnded ( SectionInfo const & name , Counts const & assertions ) = 0 ;
2012-05-16 15:09:17 +01:00
virtual void pushScopedInfo ( ScopedInfo * scopedInfo ) = 0 ;
virtual void popScopedInfo ( ScopedInfo * scopedInfo ) = 0 ;
virtual bool shouldDebugBreak () const = 0 ;
2012-05-09 19:04:00 +01:00
2012-12-01 23:57:18 +00:00
virtual ResultAction :: Value acceptExpression ( ExpressionResultBuilder const & assertionResult , AssertionInfo const & assertionInfo ) = 0 ;
2012-05-09 19:04:00 +01:00
2012-05-16 15:09:17 +01:00
virtual std :: string getCurrentTestName () const = 0 ;
2012-10-28 12:07:17 +00:00
virtual const AssertionResult * getLastResult () const = 0 ;
2012-05-09 19:04:00 +01:00
};
}
// #included from: catch_debugger.hpp
2012-08-09 07:47:30 +01:00
#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED
2012-05-09 19:04:00 +01: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 15:09:17 +01:00
namespace Catch {
2012-05-09 19:04:00 +01: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 15:09:17 +01:00
inline bool isDebuggerActive (){
2012-05-09 19:04:00 +01: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 15:09:17 +01:00
if( Catch::isDebuggerActive() ) { \
2012-05-09 19:04:00 +01:00
__asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\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 15:09:17 +01:00
inline bool isDebuggerActive () {
2012-05-09 19:04:00 +01:00
return IsDebuggerPresent () != 0 ;
}
2012-05-11 08:17:16 +01: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 15:09:17 +01:00
inline bool isDebuggerActive () {
2012-05-11 08:17:16 +01:00
return IsDebuggerPresent () != 0 ;
}
2012-05-09 19:04:00 +01:00
#else
inline void BreakIntoDebugger (){}
inline bool isDebuggerActive () { return false ; }
#endif
#ifdef CATCH_PLATFORM_WINDOWS
extern "C" __declspec ( dllimport ) void __stdcall OutputDebugStringA ( const char * );
2012-05-16 15:09:17 +01:00
inline void writeToDebugConsole ( const std :: string & text ) {
2012-05-09 19:04:00 +01:00
:: OutputDebugStringA ( text . c_str () );
}
#else
2012-05-16 15:09:17 +01:00
inline void writeToDebugConsole ( const std :: string & text ) {
2012-05-09 19:04:00 +01:00
// !TBD: Need a version for Mac/ XCode and other IDEs
std :: cout << text ;
}
#endif // CATCH_PLATFORM_WINDOWS
2012-08-09 07:47:30 +01:00
// #included from: catch_interfaces_registry_hub.h
#define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED
2012-08-31 08:10:36 +01:00
// #included from: catch_interfaces_reporter.h
2012-09-17 01:42:29 -04:00
#define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED
2012-08-31 08:10:36 +01:00
// #included from: catch_config.hpp
2012-09-17 01:42:29 -04:00
#define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED
2012-08-31 08:10:36 +01:00
// #included from: catch_test_spec.h
2012-09-17 01:42:29 -04:00
#define TWOBLUECUBES_CATCH_TEST_SPEC_H_INCLUDED
2012-08-31 08:10:36 +01:00
// #included from: catch_test_case_info.h
2012-09-17 01:42:29 -04:00
#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED
2012-08-31 08:10:36 +01:00
#include <string>
2012-09-15 17:53:27 +01:00
#include <set>
2012-08-31 08:10:36 +01:00
namespace Catch {
struct ITestCase ;
2012-12-01 23:57:18 +00: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 );
2012-08-31 08:10:36 +01:00
TestCaseInfo ( const TestCaseInfo & other );
2012-12-01 23:57:18 +00:00
std :: string name ;
std :: string className ;
std :: string description ;
std :: set < std :: string > tags ;
SourceLineInfo lineInfo ;
2012-12-06 08:44:51 +00:00
bool isHidden ;
2012-12-01 23:57:18 +00:00
};
class TestCase : protected TestCaseInfo {
public :
TestCase ( ITestCase * testCase , const TestCaseInfo & info );
TestCase ( const TestCase & other );
TestCase withName ( const std :: string & _newName ) const ;
2012-08-31 08:10:36 +01:00
void invoke () const ;
2012-11-04 21:39:38 +00:00
2012-12-01 23:57:18 +00:00
const TestCaseInfo & getTestCaseInfo () const ;
2012-08-31 08:10:36 +01:00
bool isHidden () const ;
2012-09-15 17:53:27 +01:00
bool hasTag ( const std :: string & tag ) const ;
2012-09-24 08:30:13 +01:00
bool matchesTags ( const std :: string & tagPattern ) const ;
2012-09-26 18:38:26 +01:00
const std :: set < std :: string >& getTags () const ;
2012-08-31 08:10:36 +01:00
2012-12-01 23:57:18 +00:00
void swap ( TestCase & other );
bool operator == ( const TestCase & other ) const ;
bool operator < ( const TestCase & other ) const ;
TestCase & operator = ( const TestCase & other );
2012-08-31 08:10:36 +01:00
private :
2012-12-01 23:57:18 +00:00
Ptr < ITestCase > test ;
2012-08-31 08:10:36 +01:00
};
2012-12-01 23:57:18 +00:00
TestCase makeTestCase ( ITestCase * testCase ,
const std :: string & className ,
const std :: string & name ,
const std :: string & description ,
const SourceLineInfo & lineInfo );
2012-08-31 08:10:36 +01:00
}
2012-09-26 18:38:26 +01:00
// #included from: catch_tags.hpp
#define TWOBLUECUBES_CATCH_TAGS_HPP_INCLUDED
#include <string>
#include <set>
#include <map>
#include <vector>
#ifdef __clang__
#pragma clang diagnostic ignored "-Wpadded"
#endif
namespace Catch {
class TagParser {
public :
virtual ~ TagParser ();
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 ();
}
protected :
virtual void acceptTag ( const std :: string & tag ) = 0 ;
virtual void acceptChar ( char c ) = 0 ;
virtual void endParse () {}
private :
};
class TagExtracter : public TagParser {
public :
TagExtracter ( std :: set < std :: string >& tags )
: m_tags ( tags )
{}
virtual ~ TagExtracter ();
void parse ( std :: string & description ) {
TagParser :: parse ( description );
description = m_remainder ;
}
private :
virtual void acceptTag ( const std :: string & tag ) {
m_tags . insert ( tag );
}
virtual void acceptChar ( char c ) {
m_remainder += c ;
}
2012-11-04 21:39:38 +00:00
TagExtracter & operator = ( const TagExtracter & );
2012-09-26 18:38:26 +01:00
std :: set < std :: string >& m_tags ;
std :: string m_remainder ;
};
class Tag {
public :
Tag ()
2012-11-06 19:34:35 +00:00
: m_isNegated ( false )
2012-09-26 18:38:26 +01:00
{}
Tag ( const std :: string & name , bool isNegated )
: m_name ( name ),
2012-11-06 19:34:35 +00:00
m_isNegated ( isNegated )
2012-09-26 18:38:26 +01:00
{}
std :: string getName () const {
return m_name ;
}
bool isNegated () const {
return m_isNegated ;
}
bool operator ! () const {
return m_name . empty ();
}
private :
std :: string m_name ;
bool m_isNegated ;
};
class TagSet {
typedef std :: map < std :: string , Tag > TagMap ;
public :
void add ( const Tag & tag ) {
m_tags . insert ( std :: make_pair ( tag . getName (), tag ) );
}
bool empty () const {
return m_tags . empty ();
}
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 ;
}
private :
TagMap m_tags ;
};
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 ;
}
private :
friend class TagExpressionParser ;
std :: vector < TagSet > m_tagSets ;
};
class TagExpressionParser : public TagParser {
public :
TagExpressionParser ( TagExpression & exp )
: m_isNegated ( false ),
m_exp ( exp )
{}
~ TagExpressionParser ();
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 );
}
2012-11-04 21:39:38 +00:00
TagExpressionParser & operator = ( const TagExpressionParser & );
2012-09-26 18:38:26 +01:00
bool m_isNegated ;
TagSet m_currentTagSet ;
TagExpression & m_exp ;
};
} // end namespace Catch
2012-08-31 08:10:36 +01:00
#include <string>
#include <vector>
namespace Catch {
struct IfFilterMatches { enum DoWhat {
2012-09-07 17:52:35 +01:00
AutoDetectBehaviour ,
2012-08-31 08:10:36 +01:00
IncludeTests ,
ExcludeTests
}; };
class TestCaseFilter {
enum WildcardPosition {
NoWildcard = 0 ,
WildcardAtStart = 1 ,
WildcardAtEnd = 2 ,
WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
};
public :
2012-09-07 17:52:35 +01:00
TestCaseFilter ( const std :: string & testSpec , IfFilterMatches :: DoWhat matchBehaviour = IfFilterMatches :: AutoDetectBehaviour )
2012-08-31 08:10:36 +01:00
: m_stringToMatch ( testSpec ),
m_filterType ( matchBehaviour ),
m_wildcardPosition ( NoWildcard )
{
2012-09-07 17:52:35 +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 ;
}
}
2012-08-31 08:10:36 +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 );
}
}
IfFilterMatches :: DoWhat getFilterType () const {
return m_filterType ;
}
2012-12-01 23:57:18 +00:00
bool shouldInclude ( const TestCase & testCase ) const {
2012-08-31 08:10:36 +01:00
return isMatch ( testCase ) == ( m_filterType == IfFilterMatches :: IncludeTests );
}
private :
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunreachable-code"
#endif
2012-12-01 23:57:18 +00:00
bool isMatch ( const TestCase & testCase ) const {
const std :: string & name = testCase . getTestCaseInfo (). name ;
2012-08-31 08:10:36 +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" );
}
#ifdef __clang__
#pragma clang diagnostic pop
#endif
std :: string m_stringToMatch ;
IfFilterMatches :: DoWhat m_filterType ;
WildcardPosition m_wildcardPosition ;
};
class TestCaseFilters {
public :
TestCaseFilters ( const std :: string & name ) : m_name ( name ) {}
std :: string getName () const {
return m_name ;
}
void addFilter ( const TestCaseFilter & filter ) {
if ( filter . getFilterType () == IfFilterMatches :: ExcludeTests )
m_exclusionFilters . push_back ( filter );
else
m_inclusionFilters . push_back ( filter );
}
2012-09-26 18:38:26 +01:00
void addTags ( const std :: string & tagPattern ) {
TagExpression exp ;
TagExpressionParser ( exp ). parse ( tagPattern );
m_tagExpressions . push_back ( exp );
}
2012-12-01 23:57:18 +00:00
bool shouldInclude ( const TestCase & testCase ) const {
2012-09-26 18:38:26 +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-31 08:10:36 +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 ;
}
2012-09-26 18:38:26 +01:00
else if ( m_exclusionFilters . empty () && m_tagExpressions . empty () ) {
2012-09-15 17:53:27 +01:00
return ! testCase . isHidden ();
}
2012-08-31 08:10:36 +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 :
2012-09-26 18:38:26 +01:00
std :: vector < TagExpression > m_tagExpressions ;
2012-08-31 08:10:36 +01:00
std :: vector < TestCaseFilter > m_inclusionFilters ;
std :: vector < TestCaseFilter > m_exclusionFilters ;
std :: string m_name ;
};
}
// #included from: catch_interfaces_config.h
#define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED
namespace Catch {
struct IConfig {
virtual ~ IConfig ();
virtual bool allowThrows () const = 0 ;
};
}
2012-09-26 18:38:26 +01:00
// #included from: catch_stream.hpp
#define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED
2012-09-29 20:54:03 +01:00
// #included from: catch_streambuf.h
#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED
#include <streambuf>
namespace Catch {
class StreamBufBase : public std :: streambuf {
public :
virtual ~ StreamBufBase ();
};
}
2012-09-26 18:38:26 +01:00
#include <stdexcept>
#include <cstdio>
namespace Catch {
template < typename WriterF , size_t bufferSize = 256 >
class StreamBufImpl : public StreamBufBase {
char data [ bufferSize ];
WriterF m_writer ;
public :
StreamBufImpl () {
setp ( data , data + sizeof ( data ) );
}
~ StreamBufImpl () {
sync ();
}
private :
int overflow ( int c ) {
sync ();
if ( c != EOF ) {
if ( pbase () == epptr () )
m_writer ( std :: string ( 1 , static_cast < char > ( c ) ) );
else
sputc ( static_cast < char > ( c ) );
}
return 0 ;
}
int sync () {
if ( pbase () != pptr () ) {
m_writer ( std :: string ( pbase (), static_cast < std :: string :: size_type > ( pptr () - pbase () ) ) );
setp ( pbase (), epptr () );
}
return 0 ;
}
};
///////////////////////////////////////////////////////////////////////////
struct OutputDebugWriter {
void operator ()( const std :: string & str ) {
writeToDebugConsole ( str );
}
};
class Stream {
public :
Stream ()
: streamBuf ( NULL ), isOwned ( false )
{}
Stream ( std :: streambuf * _streamBuf , bool _isOwned )
: streamBuf ( _streamBuf ), isOwned ( _isOwned )
{}
void release () {
if ( isOwned ) {
delete streamBuf ;
streamBuf = NULL ;
isOwned = false ;
}
}
std :: streambuf * streamBuf ;
private :
bool isOwned ;
};
}
2012-08-31 08:10:36 +01:00
#include <memory>
#include <vector>
#include <string>
#include <iostream>
namespace Catch {
struct Include { enum WhichResults {
FailedOnly ,
SuccessfulResults
}; };
struct List { enum What {
None = 0 ,
Reports = 1 ,
Tests = 2 ,
All = 3 ,
TestNames = 6 ,
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 ;
};
class Config : public IConfig {
private :
Config ( const Config & other );
Config & operator = ( const Config & other );
virtual void dummy ();
public :
Config ()
2012-09-26 18:38:26 +01:00
: m_os ( std :: cout . rdbuf () )
2012-08-31 08:10:36 +01:00
{}
Config ( const ConfigData & data )
: m_data ( data ),
m_os ( std :: cout . rdbuf () )
{}
virtual ~ Config () {
m_os . rdbuf ( std :: cout . rdbuf () );
2012-09-26 18:38:26 +01:00
m_stream . release ();
2012-08-31 08:10:36 +01:00
}
void setFilename ( const std :: string & filename ) {
m_data . outputFilename = filename ;
}
List :: What getListSpec ( void ) const {
return m_data . listSpec ;
}
const std :: string & getFilename () const {
return m_data . outputFilename ;
}
List :: What listWhat () const {
return static_cast < List :: What > ( m_data . listSpec & List :: WhatMask );
}
List :: What listAs () const {
return static_cast < List :: What > ( m_data . listSpec & List :: AsMask );
}
std :: string getName () const {
return m_data . name ;
}
bool shouldDebugBreak () const {
return m_data . shouldDebugBreak ;
}
virtual std :: ostream & stream () const {
return m_os ;
}
void setStreamBuf ( std :: streambuf * buf ) {
m_os . rdbuf ( buf ? buf : std :: cout . rdbuf () );
}
void useStream ( const std :: string & streamName ) {
2012-09-26 18:38:26 +01:00
Stream stream = createStream ( streamName );
setStreamBuf ( stream . streamBuf );
m_stream . release ();
m_stream = stream ;
2012-08-31 08:10:36 +01:00
}
2012-09-07 17:52:35 +01:00
void addTestSpec ( const std :: string & testSpec ) {
TestCaseFilters filters ( testSpec );
filters . addFilter ( TestCaseFilter ( testSpec ) );
m_data . filters . push_back ( filters );
}
2012-08-31 08:10:36 +01:00
virtual bool includeSuccessfulResults () const {
return m_data . includeWhichResults == Include :: SuccessfulResults ;
}
int getCutoff () const {
return m_data . cutoff ;
}
virtual bool allowThrows () const {
return m_data . allowThrows ;
}
const ConfigData & data () const {
return m_data ;
}
ConfigData & data () {
return m_data ;
}
private :
ConfigData m_data ;
// !TBD Move these out of here
2012-09-26 18:38:26 +01:00
Stream m_stream ;
2012-08-31 08:10:36 +01:00
mutable std :: ostream m_os ;
};
} // end namespace Catch
2012-12-06 08:44:51 +00: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-08-31 08:10:36 +01:00
#include <string>
#include <ostream>
#include <map>
namespace Catch
{
2012-12-01 23:57:18 +00:00
struct ReporterConfig {
ReporterConfig ( std :: ostream & _stream , ConfigData const & _fullConfig )
: m_stream ( & _stream ), m_fullConfig ( _fullConfig ) {}
2012-12-06 08:44:51 +00:00
std :: ostream & stream () const { return * m_stream ; }
2012-12-01 23:57:18 +00: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-08-31 08:10:36 +01:00
{}
2012-12-01 23:57:18 +00:00
bool shouldRedirectStdOut ;
};
struct TestRunInfo {
TestRunInfo ( std :: string const & _name ) : name ( _name ) {}
std :: string name ;
};
struct GroupInfo {
GroupInfo ( std :: string const & _name ) : name ( _name ) {}
std :: string name ;
};
struct SectionInfo {
SectionInfo ( std :: string const & _name ,
std :: string const & _description ,
SourceLineInfo const & _lineInfo )
: name ( _name ),
description ( _description ),
lineInfo ( _lineInfo )
2012-09-24 08:30:13 +01:00
{}
2012-08-31 08:10:36 +01:00
std :: string name ;
2012-12-01 23:57:18 +00:00
std :: string description ;
SourceLineInfo lineInfo ;
2012-08-31 08:10:36 +01:00
};
2012-12-06 08:44:51 +00:00
struct ThreadedSectionInfo : SectionInfo , SharedImpl <> {
ThreadedSectionInfo ( SectionInfo const & _sectionInfo , Ptr < ThreadedSectionInfo > const & _parent = Ptr < ThreadedSectionInfo > () )
: SectionInfo ( _sectionInfo ),
2012-12-10 08:54:57 +00:00
parent ( _parent ),
printed ( false )
2012-12-06 08:44:51 +00:00
{}
virtual ~ ThreadedSectionInfo ();
std :: vector < Ptr < ThreadedSectionInfo > > children ;
Ptr < ThreadedSectionInfo > parent ;
2012-12-10 08:54:57 +00:00
bool printed ;
2012-12-06 08:44:51 +00:00
};
2012-12-01 23:57:18 +00:00
struct AssertionStats : SharedImpl <> {
AssertionStats ( AssertionResult const & _assertionResult ,
Totals const & _totals )
: assertionResult ( _assertionResult ),
totals ( _totals )
{}
virtual ~ AssertionStats ();
2012-08-31 08:10:36 +01:00
2012-12-01 23:57:18 +00:00
AssertionResult assertionResult ;
Totals totals ;
};
struct SectionStats : SharedImpl <> {
SectionStats ( SectionInfo const & _sectionInfo ,
Counts const & _assertions ,
bool _missingAssertions )
: sectionInfo ( _sectionInfo ),
assertions ( _assertions ),
missingAssertions ( _missingAssertions )
{}
virtual ~ SectionStats ();
SectionInfo sectionInfo ;
Counts assertions ;
bool missingAssertions ;
};
struct TestCaseStats : SharedImpl <> {
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 ;
};
struct TestGroupStats : SharedImpl <> {
TestGroupStats ( GroupInfo const & _groupInfo ,
Totals const & _totals ,
bool _aborting )
: groupInfo ( _groupInfo ),
totals ( _totals ),
aborting ( _aborting )
{}
virtual ~ TestGroupStats ();
GroupInfo groupInfo ;
Totals totals ;
bool aborting ;
};
struct TestRunStats : SharedImpl <> {
TestRunStats ( TestRunInfo const & _runInfo ,
Totals const & _totals ,
bool _aborting )
: runInfo ( _runInfo ),
totals ( _totals ),
aborting ( _aborting )
{}
virtual ~ TestRunStats ();
TestRunInfo runInfo ;
Totals totals ;
bool aborting ;
};
// !Work In progress
struct IStreamingReporter : IShared {
virtual ~ IStreamingReporter ();
2012-12-06 08:44:51 +00:00
// Implementing class must also provide the following static methid:
// static std::string getDescription();
2012-12-01 23:57:18 +00: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 ;
virtual void assertionEnded ( Ptr < AssertionStats const > const & assertionStats ) = 0 ;
virtual void sectionEnded ( Ptr < SectionStats const > const & sectionStats ) = 0 ;
virtual void testCaseEnded ( Ptr < TestCaseStats const > const & testCaseStats ) = 0 ;
virtual void testGroupEnded ( Ptr < TestGroupStats const > const & testGroupStats ) = 0 ;
virtual void testRunEnded ( Ptr < TestRunStats const > const & testRunStats ) = 0 ;
};
// !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
2012-12-06 08:44:51 +00:00
struct AccumulatingReporter : SharedImpl < IStreamingReporter > {
AccumulatingReporter ( ReporterConfig const & _config )
2012-12-10 08:54:57 +00:00
: m_config ( _config ),
stream ( _config . stream () )
2012-12-06 08:44:51 +00:00
{}
virtual ~ AccumulatingReporter ();
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 );
unusedSectionInfo = sectionInfo ;
if ( ! currentSectionInfo ) {
currentSectionInfo = sectionInfo ;
}
else {
currentSectionInfo -> children . push_back ( sectionInfo );
sectionInfo -> parent = currentSectionInfo ;
currentSectionInfo = sectionInfo ;
}
}
virtual void sectionEnded ( Ptr < SectionStats const > const & /* _sectionStats */ ) {
currentSectionInfo = currentSectionInfo -> parent ;
unusedSectionInfo = currentSectionInfo ;
}
virtual void testCaseEnded ( Ptr < TestCaseStats const > const & /* _testCaseStats */ ) {
unusedTestCaseInfo . reset ();
}
virtual void testGroupEnded ( Ptr < TestGroupStats const > const & /* _testGroupStats */ ) {
unusedGroupInfo . reset ();
}
virtual void testRunEnded ( Ptr < TestRunStats const > const & /* _testRunStats */ ) {
}
2012-12-10 08:54:57 +00:00
ReporterConfig m_config ;
2012-12-06 08:44:51 +00:00
Option < TestRunInfo > testRunInfo ;
Option < GroupInfo > unusedGroupInfo ;
Option < TestCaseInfo > unusedTestCaseInfo ;
Ptr < ThreadedSectionInfo > unusedSectionInfo ;
Ptr < ThreadedSectionInfo > currentSectionInfo ;
bool currentSectionOpen ;
std :: ostream & stream ;
};
2012-12-01 23:57:18 +00:00
// Deprecated
2012-08-31 08:10:36 +01:00
struct IReporter : IShared {
virtual ~ IReporter ();
2012-10-28 12:07:17 +00:00
2012-08-31 08:10:36 +01:00
virtual bool shouldRedirectStdout () const = 0 ;
2012-10-28 12:07:17 +00:00
2012-08-31 08:10:36 +01:00
virtual void StartTesting () = 0 ;
2012-12-01 23:57:18 +00: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 ;
2012-08-31 08:10:36 +01:00
virtual void Aborted () = 0 ;
2012-10-28 12:07:17 +00:00
virtual void Result ( const AssertionResult & result ) = 0 ;
2012-08-31 08:10:36 +01:00
};
2012-12-01 23:57:18 +00:00
class LegacyReporterAdapter : public SharedImpl < IStreamingReporter >
{
public :
LegacyReporterAdapter ( Ptr < IReporter > const & legacyReporter , ReporterConfig const & config )
: m_legacyReporter ( legacyReporter ),
m_config ( config )
{}
virtual ~ LegacyReporterAdapter ();
virtual ReporterPreferences getPreferences () const {
ReporterPreferences prefs ;
prefs . shouldRedirectStdOut = m_legacyReporter -> shouldRedirectStdout ();
return prefs ;
}
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
}
virtual void assertionEnded ( Ptr < AssertionStats const > const & assertionStats ) {
m_legacyReporter -> Result ( assertionStats -> assertionResult );
}
virtual void sectionEnded ( Ptr < SectionStats const > const & sectionStats ) {
if ( sectionStats -> missingAssertions )
m_legacyReporter -> NoAssertionsInSection ( sectionStats -> sectionInfo . name );
m_legacyReporter -> EndSection ( sectionStats -> sectionInfo . name , sectionStats -> assertions );
}
virtual void testCaseEnded ( Ptr < TestCaseStats const > const & testCaseStats ) {
if ( testCaseStats -> missingAssertions )
m_legacyReporter -> NoAssertionsInTestCase ( testCaseStats -> testInfo . name );
m_legacyReporter -> EndTestCase
( testCaseStats -> testInfo ,
testCaseStats -> totals ,
testCaseStats -> stdOut ,
testCaseStats -> stdErr );
}
virtual void testGroupEnded ( Ptr < TestGroupStats const > const & testGroupStats ) {
if ( testGroupStats -> aborting )
m_legacyReporter -> Aborted ();
m_legacyReporter -> EndGroup ( testGroupStats -> groupInfo . name , testGroupStats -> totals );
}
virtual void testRunEnded ( Ptr < TestRunStats const > const & testRunStats ) {
m_legacyReporter -> EndTesting ( testRunStats -> totals );
}
private :
Ptr < IReporter > m_legacyReporter ;
ReporterConfig m_config ;
};
2012-08-31 08:10:36 +01:00
struct IReporterFactory {
virtual ~ IReporterFactory ();
2012-12-01 23:57:18 +00:00
virtual IStreamingReporter * create ( ReporterConfig const & config ) const = 0 ;
2012-08-31 08:10:36 +01:00
virtual std :: string getDescription () const = 0 ;
};
struct IReporterRegistry {
typedef std :: map < std :: string , IReporterFactory *> FactoryMap ;
virtual ~ IReporterRegistry ();
2012-12-01 23:57:18 +00:00
virtual IStreamingReporter * create ( std :: string const & name , ReporterConfig const & config ) const = 0 ;
2012-08-31 08:10:36 +01:00
virtual const FactoryMap & getFactories () const = 0 ;
};
2012-12-01 23:57:18 +00:00
inline std :: string trim ( std :: string const & str ) {
2012-08-31 08:10:36 +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-08-09 07:47:30 +01:00
#include <vector>
namespace Catch {
2012-12-01 23:57:18 +00:00
class TestCase ;
2012-08-09 07:47:30 +01:00
struct ITestCaseRegistry ;
struct IExceptionTranslatorRegistry ;
struct IExceptionTranslator ;
struct IRegistryHub {
2012-08-13 07:46:10 +01:00
virtual ~ IRegistryHub ();
2012-08-09 07:47:30 +01:00
virtual const IReporterRegistry & getReporterRegistry () const = 0 ;
virtual const ITestCaseRegistry & getTestCaseRegistry () const = 0 ;
virtual IExceptionTranslatorRegistry & getExceptionTranslatorRegistry () = 0 ;
};
struct IMutableRegistryHub {
2012-08-13 07:46:10 +01:00
virtual ~ IMutableRegistryHub ();
2012-08-09 07:47:30 +01:00
virtual void registerReporter ( const std :: string & name , IReporterFactory * factory ) = 0 ;
2012-12-01 23:57:18 +00:00
virtual void registerTest ( const TestCase & testInfo ) = 0 ;
2012-08-09 07:47:30 +01:00
virtual void registerTranslator ( const IExceptionTranslator * translator ) = 0 ;
};
IRegistryHub & getRegistryHub ();
IMutableRegistryHub & getMutableRegistryHub ();
void cleanUp ();
2012-10-28 12:07:17 +00:00
std :: string translateActiveException ();
2012-08-09 07:47:30 +01:00
}
2012-10-28 12:07:17 +00: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" );
}
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 ) );
}
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 ) );
}
struct TestFailureException {};
class ScopedInfo {
public :
ScopedInfo () : m_resultBuilder ( ResultWas :: Info ) {
getResultCapture (). pushScopedInfo ( this );
}
~ ScopedInfo () {
getResultCapture (). popScopedInfo ( this );
}
template < typename T >
ScopedInfo & operator << ( const T & value ) {
m_resultBuilder << value ;
return * this ;
}
AssertionResult buildResult ( const AssertionInfo & assertionInfo ) const {
return m_resultBuilder . buildResult ( assertionInfo );
}
private :
ExpressionResultBuilder m_resultBuilder ;
};
// This is just here to avoid compiler warnings with macro constants and boolean literals
inline bool isTrue ( bool value ){ return value ; }
} // end namespace Catch
2012-10-29 20:49:22 +00:00
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_ASSERTIONINFO_NAME INTERNAL_CATCH_UNIQUE_NAME( __assertionInfo )
2012-10-28 12:07:17 +00:00
///////////////////////////////////////////////////////////////////////////////
2012-11-10 18:46:39 +00:00
#define INTERNAL_CATCH_ACCEPT_EXPR( evaluatedExpr, resultDisposition, originalExpr ) \
2012-10-29 20:49:22 +00:00
if( Catch::ResultAction::Value internal_catch_action = Catch::getResultCapture().acceptExpression( evaluatedExpr, INTERNAL_CATCH_ASSERTIONINFO_NAME ) ) { \
2012-10-28 12:07:17 +00:00
if( internal_catch_action & Catch::ResultAction::Debug ) BreakIntoDebugger(); \
if( internal_catch_action & Catch::ResultAction::Abort ) throw Catch::TestFailureException(); \
2012-11-10 18:46:39 +00:00
if( !Catch::shouldContinueOnFailure( resultDisposition ) ) throw Catch::TestFailureException(); \
2012-10-28 12:07:17 +00:00
if( Catch::isTrue( false ) ){ bool this_is_here_to_invoke_warnings = ( originalExpr ); Catch::isTrue( this_is_here_to_invoke_warnings ); } \
}
///////////////////////////////////////////////////////////////////////////////
2012-11-10 18:46:39 +00:00
#define INTERNAL_CATCH_ACCEPT_INFO( expr, macroName, resultDisposition ) \
2012-11-13 09:44:52 +00:00
Catch::AssertionInfo INTERNAL_CATCH_ASSERTIONINFO_NAME( macroName, CATCH_INTERNAL_LINEINFO, expr, resultDisposition );
2012-10-28 12:07:17 +00:00
///////////////////////////////////////////////////////////////////////////////
2012-11-10 18:46:39 +00:00
#define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \
2012-10-29 20:49:22 +00:00
do { \
2012-11-10 18:46:39 +00:00
INTERNAL_CATCH_ACCEPT_INFO( #expr, macroName, resultDisposition ); \
2012-10-29 20:49:22 +00:00
try { \
2012-11-10 18:46:39 +00:00
INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionDecomposer()->*expr ).endExpression( resultDisposition ), resultDisposition, expr ); \
2012-10-29 20:49:22 +00:00
} catch( Catch::TestFailureException& ) { \
throw; \
} catch( ... ) { \
2012-11-10 18:46:39 +00:00
INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException(), \
resultDisposition | Catch::ResultDisposition::ContinueOnFailure, expr ); \
2012-10-29 20:49:22 +00:00
throw; \
} \
} while( Catch::isTrue( false ) )
2012-10-28 12:07:17 +00:00
///////////////////////////////////////////////////////////////////////////////
2012-11-10 18:46:39 +00:00
#define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \
INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \
2012-11-13 09:44:52 +00:00
if( Catch::getResultCapture().getLastResult()->succeeded() )
2012-10-28 12:07:17 +00:00
///////////////////////////////////////////////////////////////////////////////
2012-11-10 18:46:39 +00:00
#define INTERNAL_CATCH_ELSE( expr, resultDisposition, macroName ) \
INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \
2012-11-13 09:44:52 +00:00
if( !Catch::getResultCapture().getLastResult()->succeeded() )
2012-10-28 12:07:17 +00:00
///////////////////////////////////////////////////////////////////////////////
2012-11-10 18:46:39 +00:00
#define INTERNAL_CATCH_NO_THROW( expr, resultDisposition, macroName ) \
2012-10-29 20:49:22 +00:00
do { \
2012-11-10 18:46:39 +00:00
INTERNAL_CATCH_ACCEPT_INFO( #expr, macroName, resultDisposition ); \
2012-10-29 20:49:22 +00:00
try { \
expr; \
2012-11-10 18:46:39 +00:00
INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::Ok ), resultDisposition, false ); \
2012-10-29 20:49:22 +00:00
} \
catch( ... ) { \
2012-11-10 18:46:39 +00:00
INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException(), resultDisposition, false ); \
2012-10-29 20:49:22 +00:00
} \
} while( Catch::isTrue( false ) )
2012-10-28 12:07:17 +00:00
///////////////////////////////////////////////////////////////////////////////
2012-11-10 18:46:39 +00:00
#define INTERNAL_CATCH_THROWS_IMPL( expr, exceptionType, resultDisposition ) \
2012-10-28 12:07:17 +00:00
try { \
if( Catch::getCurrentContext().getConfig()->allowThrows() ) { \
expr; \
2012-11-10 18:46:39 +00:00
INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::DidntThrowException ), resultDisposition, false ); \
2012-10-28 12:07:17 +00:00
} \
} \
catch( Catch::TestFailureException& ) { \
throw; \
} \
catch( exceptionType ) { \
2012-11-10 18:46:39 +00:00
INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::Ok ), resultDisposition, false ); \
2012-10-28 12:07:17 +00:00
}
2012-10-29 20:49:22 +00:00
///////////////////////////////////////////////////////////////////////////////
2012-11-10 18:46:39 +00:00
#define INTERNAL_CATCH_THROWS( expr, exceptionType, resultDisposition, macroName ) \
2012-10-29 20:49:22 +00:00
do { \
2012-11-10 18:46:39 +00:00
INTERNAL_CATCH_ACCEPT_INFO( #expr, macroName, resultDisposition ); \
INTERNAL_CATCH_THROWS_IMPL( expr, exceptionType, resultDisposition ) \
2012-10-29 20:49:22 +00:00
} while( Catch::isTrue( false ) )
2012-10-28 12:07:17 +00:00
///////////////////////////////////////////////////////////////////////////////
2012-11-10 18:46:39 +00:00
#define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, resultDisposition, macroName ) \
2012-10-29 20:49:22 +00:00
do { \
2012-11-10 18:46:39 +00:00
INTERNAL_CATCH_ACCEPT_INFO( #expr, macroName, resultDisposition ); \
INTERNAL_CATCH_THROWS_IMPL( expr, exceptionType, resultDisposition ) \
2012-10-29 20:49:22 +00:00
catch( ... ) { \
2012-11-10 18:46:39 +00:00
INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException() ), \
resultDisposition | Catch::ResultDisposition::ContinueOnFailure, false ); \
2012-10-29 20:49:22 +00:00
} \
} while( Catch::isTrue( false ) )
2012-10-28 12:07:17 +00:00
///////////////////////////////////////////////////////////////////////////////
2012-11-10 18:46:39 +00:00
#define INTERNAL_CATCH_MSG( reason, resultType, resultDisposition, macroName ) \
2012-11-06 07:52:28 +00:00
do { \
2012-11-10 18:46:39 +00:00
INTERNAL_CATCH_ACCEPT_INFO( "", macroName, resultDisposition ); \
INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( resultType ) << reason, resultDisposition, true ) \
2012-11-06 07:52:28 +00:00
} while( Catch::isTrue( false ) )
2012-10-28 12:07:17 +00:00
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_SCOPED_INFO( log, macroName ) \
2012-11-10 18:46:39 +00:00
INTERNAL_CATCH_ACCEPT_INFO( "", macroName, Catch::ResultDisposition::Normal ); \
2012-10-28 12:07:17 +00:00
Catch::ScopedInfo INTERNAL_CATCH_UNIQUE_NAME( info ); \
INTERNAL_CATCH_UNIQUE_NAME( info ) << log
///////////////////////////////////////////////////////////////////////////////
2012-11-10 18:46:39 +00:00
#define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \
2012-10-29 20:49:22 +00:00
do { \
2012-11-10 18:46:39 +00:00
INTERNAL_CATCH_ACCEPT_INFO( #arg " " #matcher, macroName, resultDisposition ); \
2012-10-29 20:49:22 +00:00
try { \
2012-11-10 18:46:39 +00:00
INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::expressionResultBuilderFromMatcher( ::Catch::Matchers::matcher, arg, #matcher ) ), resultDisposition, false ); \
2012-10-29 20:49:22 +00:00
} catch( Catch::TestFailureException& ) { \
throw; \
} catch( ... ) { \
2012-11-10 18:46:39 +00:00
INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException() ), \
resultDisposition | Catch::ResultDisposition::ContinueOnFailure, false ); \
2012-10-29 20:49:22 +00:00
throw; \
} \
} while( Catch::isTrue( false ) )
2012-10-28 12:07:17 +00:00
// #included from: internal/catch_section.hpp
#define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED
#include <string>
namespace Catch {
class Section {
public :
Section ( const std :: string & name ,
const std :: string & description ,
const SourceLineInfo & lineInfo )
2012-12-01 23:57:18 +00:00
: m_info ( name , description , lineInfo ),
m_sectionIncluded ( getCurrentContext (). getResultCapture (). sectionStarted ( m_info , m_assertions ) )
2012-10-28 12:07:17 +00:00
{}
~ Section () {
if ( m_sectionIncluded )
2012-12-01 23:57:18 +00:00
getCurrentContext (). getResultCapture (). sectionEnded ( m_info , m_assertions );
2012-10-28 12:07:17 +00:00
}
// This indicates whether the section should be executed or not
operator bool () {
return m_sectionIncluded ;
}
private :
2012-12-01 23:57:18 +00:00
SectionInfo m_info ;
2012-10-28 12:07:17 +00:00
std :: string m_name ;
Counts m_assertions ;
bool m_sectionIncluded ;
};
} // end namespace Catch
#define INTERNAL_CATCH_SECTION( name, desc ) \
if( Catch::Section INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::Section( name, desc, CATCH_INTERNAL_LINEINFO ) )
// #included from: internal/catch_generators.hpp
#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED
#include <iterator>
#include <vector>
#include <string>
#include <stdlib.h>
namespace Catch {
template < typename T >
struct IGenerator {
virtual ~ IGenerator () {}
virtual T getValue ( std :: size_t index ) const = 0 ;
virtual std :: size_t size () const = 0 ;
};
template < typename T >
class BetweenGenerator : public IGenerator < T > {
public :
BetweenGenerator ( T from , T to ) : m_from ( from ), m_to ( to ){}
virtual T getValue ( std :: size_t index ) const {
return m_from + static_cast < T > ( index );
}
virtual std :: size_t size () const {
return static_cast < std :: size_t > ( 1 + m_to - m_from );
}
private :
T m_from ;
T m_to ;
};
template < typename T >
class ValuesGenerator : public IGenerator < T > {
public :
ValuesGenerator (){}
void add ( T value ) {
m_values . push_back ( value );
}
virtual T getValue ( std :: size_t index ) const {
return m_values [ index ];
}
virtual std :: size_t size () const {
return m_values . size ();
}
private :
std :: vector < T > m_values ;
};
template < typename T >
class CompositeGenerator {
public :
CompositeGenerator () : m_totalSize ( 0 ) {}
// *** Move semantics, similar to auto_ptr ***
CompositeGenerator ( CompositeGenerator & other )
: m_fileInfo ( other . m_fileInfo ),
m_totalSize ( 0 )
{
move ( other );
}
CompositeGenerator & setFileInfo ( const char * fileInfo ) {
m_fileInfo = fileInfo ;
return * this ;
}
~ CompositeGenerator () {
deleteAll ( m_composed );
}
operator T () const {
size_t overallIndex = getCurrentContext (). getGeneratorIndex ( m_fileInfo , m_totalSize );
typename std :: vector < const IGenerator < T >*>:: const_iterator it = m_composed . begin ();
typename std :: vector < const IGenerator < T >*>:: const_iterator itEnd = m_composed . end ();
for ( size_t index = 0 ; it != itEnd ; ++ it )
{
const IGenerator < T >* generator = * it ;
if ( overallIndex >= index && overallIndex < index + generator -> size () )
{
return generator -> getValue ( overallIndex - index );
}
index += generator -> size ();
}
CATCH_INTERNAL_ERROR ( "Indexed past end of generated range" );
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
}
void add ( const IGenerator < T >* generator ) {
m_totalSize += generator -> size ();
m_composed . push_back ( generator );
}
CompositeGenerator & then ( CompositeGenerator & other ) {
move ( other );
return * this ;
}
CompositeGenerator & then ( T value ) {
ValuesGenerator < T >* valuesGen = new ValuesGenerator < T > ();
valuesGen -> add ( value );
add ( valuesGen );
return * this ;
}
private :
void move ( CompositeGenerator & other ) {
std :: copy ( other . m_composed . begin (), other . m_composed . end (), std :: back_inserter ( m_composed ) );
m_totalSize += other . m_totalSize ;
other . m_composed . clear ();
}
std :: vector < const IGenerator < T >*> m_composed ;
std :: string m_fileInfo ;
size_t m_totalSize ;
};
namespace Generators
{
template < typename T >
CompositeGenerator < T > between ( T from , T to ) {
CompositeGenerator < T > generators ;
generators . add ( new BetweenGenerator < T > ( from , to ) );
return generators ;
}
template < typename T >
CompositeGenerator < T > values ( T val1 , T val2 ) {
CompositeGenerator < T > generators ;
ValuesGenerator < T >* valuesGen = new ValuesGenerator < T > ();
valuesGen -> add ( val1 );
valuesGen -> add ( val2 );
generators . add ( valuesGen );
return generators ;
}
template < typename T >
CompositeGenerator < T > values ( T val1 , T val2 , T val3 ){
CompositeGenerator < T > generators ;
ValuesGenerator < T >* valuesGen = new ValuesGenerator < T > ();
valuesGen -> add ( val1 );
valuesGen -> add ( val2 );
valuesGen -> add ( val3 );
generators . add ( valuesGen );
return generators ;
}
template < typename T >
CompositeGenerator < T > values ( T val1 , T val2 , T val3 , T val4 ) {
CompositeGenerator < T > generators ;
ValuesGenerator < T >* valuesGen = new ValuesGenerator < T > ();
valuesGen -> add ( val1 );
valuesGen -> add ( val2 );
valuesGen -> add ( val3 );
valuesGen -> add ( val4 );
generators . add ( valuesGen );
return generators ;
}
} // end namespace Generators
using namespace Generators ;
} // end namespace Catch
#define INTERNAL_CATCH_LINESTR2( line ) #line
#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line )
#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" )
// #included from: internal/catch_interfaces_exception.h
#define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED
#include <string>
2011-05-24 08:23:02 +01:00
2012-05-16 15:09:17 +01:00
namespace Catch {
2011-05-24 08:23:02 +01:00
typedef std :: string ( * exceptionTranslateFunction )();
2012-05-16 15:09:17 +01:00
struct IExceptionTranslator {
2012-08-13 07:46:10 +01:00
virtual ~ IExceptionTranslator ();
2011-05-24 08:23:02 +01:00
virtual std :: string translate () const = 0 ;
};
2012-05-16 15:09:17 +01:00
struct IExceptionTranslatorRegistry {
2012-08-13 07:46:10 +01:00
virtual ~ IExceptionTranslatorRegistry ();
2011-05-24 08:23:02 +01:00
2012-05-16 15:09:17 +01:00
virtual std :: string translateActiveException () const = 0 ;
2011-05-24 08:23:02 +01:00
};
2012-05-16 15:09:17 +01:00
class ExceptionTranslatorRegistrar {
2011-05-24 08:23:02 +01:00
template < typename T >
2012-05-16 15:09:17 +01:00
class ExceptionTranslator : public IExceptionTranslator {
2011-05-24 08:23:02 +01:00
public :
2012-05-16 15:09:17 +01:00
ExceptionTranslator ( std :: string ( * translateFunction )( T & ) )
2011-05-24 08:23:02 +01:00
: m_translateFunction ( translateFunction )
{}
2012-05-16 15:09:17 +01:00
virtual std :: string translate () const {
try {
2011-05-24 08:23:02 +01:00
throw ;
}
2012-05-16 15:09:17 +01:00
catch ( T & ex ) {
2011-05-24 08:23:02 +01:00
return m_translateFunction ( ex );
}
}
protected :
std :: string ( * m_translateFunction )( T & );
};
public :
template < typename T >
2012-05-16 15:09:17 +01:00
ExceptionTranslatorRegistrar ( std :: string ( * translateFunction )( T & ) ) {
2012-08-09 07:47:30 +01:00
getMutableRegistryHub (). registerTranslator
2011-05-24 08:23:02 +01:00
( new ExceptionTranslator < T > ( translateFunction ) );
}
};
}
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) \
static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ); \
namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ) ); }\
static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature )
// #included from: internal/catch_approx.hpp
2012-08-09 07:47:30 +01:00
#define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
2011-05-24 08:23:02 +01:00
#include <cmath>
#include <limits>
2012-05-16 15:09:17 +01:00
namespace Catch {
namespace Detail {
2011-05-24 08:23:02 +01:00
2012-05-16 15:09:17 +01:00
class Approx {
public :
explicit Approx ( double value )
: m_epsilon ( std :: numeric_limits < float >:: epsilon () * 100 ),
m_scale ( 1.0 ),
m_value ( value )
{}
2011-06-07 14:13:57 +01:00
2012-05-16 15:09:17 +01:00
Approx ( const Approx & other )
: m_epsilon ( other . m_epsilon ),
m_scale ( other . m_scale ),
m_value ( other . m_value )
{}
2011-06-07 14:13:57 +01:00
2012-05-16 15:09:17 +01:00
static Approx custom () {
return Approx ( 0 );
}
2011-06-07 14:13:57 +01:00
2012-05-16 15:09:17 +01:00
Approx operator ()( double value ) {
Approx approx ( value );
approx . epsilon ( m_epsilon );
approx . scale ( m_scale );
return approx ;
}
2011-05-24 08:23:02 +01:00
2012-05-16 15:09:17 +01:00
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 ) ) );
}
2011-05-24 08:23:02 +01:00
2012-05-16 15:09:17 +01:00
friend bool operator == ( const Approx & lhs , double rhs ) {
return operator == ( rhs , lhs );
}
2011-05-24 08:23:02 +01:00
2012-05-16 15:09:17 +01:00
friend bool operator != ( double lhs , const Approx & rhs ) {
return ! operator == ( lhs , rhs );
}
2011-05-24 08:23:02 +01:00
2012-05-16 15:09:17 +01:00
friend bool operator != ( const Approx & lhs , double rhs ) {
return ! operator == ( rhs , lhs );
}
2011-05-24 08:23:02 +01:00
2012-05-16 15:09:17 +01:00
Approx & epsilon ( double newEpsilon ) {
m_epsilon = newEpsilon ;
return * this ;
}
2011-05-24 08:23:02 +01:00
2012-05-16 15:09:17 +01:00
Approx & scale ( double newScale ) {
m_scale = newScale ;
return * this ;
}
2011-05-24 08:23:02 +01:00
2012-05-16 15:09:17 +01:00
std :: string toString () const {
std :: ostringstream oss ;
2012-10-09 11:48:55 +01:00
oss << "Approx( " << m_value << " )" ;
2012-05-16 15:09:17 +01:00
return oss . str ();
}
2011-05-24 08:23:02 +01:00
2012-05-16 15:09:17 +01:00
private :
double m_epsilon ;
double m_scale ;
double m_value ;
};
}
template <>
inline std :: string toString < Detail :: Approx > ( const Detail :: Approx & value ) {
return value . toString ();
}
2011-05-24 08:23:02 +01:00
} // end namespace Catch
2012-05-21 18:52:09 +01:00
// #included from: internal/catch_matchers.hpp
2012-08-09 07:47:30 +01:00
#define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED
2012-05-21 18:52:09 +01:00
namespace Catch {
namespace Matchers {
namespace Impl {
2012-10-12 07:58:17 +01:00
template < typename ExpressionT >
struct Matcher : SharedImpl < IShared >
{
2012-12-06 08:44:51 +00:00
typedef ExpressionT ExpressionType ;
2012-10-12 07:58:17 +01:00
virtual ~ Matcher () {}
virtual Ptr < Matcher > clone () const = 0 ;
2012-12-06 08:44:51 +00:00
virtual bool match ( ExpressionT const & expr ) const = 0 ;
2012-10-12 07:58:17 +01: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 {
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
{
for ( std :: size_t i = 0 ; i < m_matchers . size (); ++ i )
if ( ! m_matchers [ i ] -> match ( expr ) )
return false ;
return true ;
}
virtual std :: string toString () const {
std :: ostringstream oss ;
oss << "( " ;
for ( std :: size_t i = 0 ; i < m_matchers . size (); ++ i ) {
if ( i != 0 )
oss << " and " ;
oss << m_matchers [ i ] -> toString ();
}
oss << " )" ;
return oss . str ();
}
private :
std :: vector < Ptr < Matcher < ExpressionT > > > m_matchers ;
};
template < typename ExpressionT >
class AnyOf : public MatcherImpl < AnyOf < ExpressionT > , ExpressionT > {
public :
AnyOf () {}
AnyOf ( 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
{
for ( std :: size_t i = 0 ; i < m_matchers . size (); ++ i )
if ( m_matchers [ i ] -> match ( expr ) )
return true ;
return false ;
}
virtual std :: string toString () const {
std :: ostringstream oss ;
oss << "( " ;
for ( std :: size_t i = 0 ; i < m_matchers . size (); ++ i ) {
if ( i != 0 )
oss << " or " ;
oss << m_matchers [ i ] -> toString ();
}
oss << " )" ;
return oss . str ();
}
private :
std :: vector < Ptr < Matcher < ExpressionT > > > m_matchers ;
};
}
2012-05-21 18:52:09 +01:00
namespace StdString {
2012-10-12 07:58:17 +01:00
struct Equals : MatcherImpl < Equals , std :: string > {
2012-05-24 08:29:41 +01:00
Equals ( const std :: string & str ) : m_str ( str ){}
2012-10-12 07:58:17 +01:00
Equals ( const Equals & other ) : m_str ( other . m_str ){}
2012-05-24 08:29:41 +01:00
2012-10-12 07:58:17 +01:00
virtual ~ Equals ();
virtual bool match ( const std :: string & expr ) const {
return m_str == expr ;
}
virtual std :: string toString () const {
return "equals: \" " + m_str + " \" " ;
2012-05-24 08:29:41 +01:00
}
std :: string m_str ;
};
2012-10-12 07:58:17 +01:00
struct Contains : MatcherImpl < Contains , std :: string > {
2012-05-21 18:52:09 +01:00
Contains ( const std :: string & substr ) : m_substr ( substr ){}
2012-10-12 07:58:17 +01:00
Contains ( const Contains & other ) : m_substr ( other . m_substr ){}
2012-05-21 18:52:09 +01:00
2012-10-12 07:58:17 +01:00
virtual ~ Contains ();
virtual bool match ( const std :: string & expr ) const {
return expr . find ( m_substr ) != std :: string :: npos ;
}
virtual std :: string toString () const {
return "contains: \" " + m_substr + " \" " ;
2012-05-21 18:52:09 +01:00
}
std :: string m_substr ;
};
2012-10-12 07:58:17 +01:00
struct StartsWith : MatcherImpl < StartsWith , std :: string > {
2012-05-21 18:52:09 +01:00
StartsWith ( const std :: string & substr ) : m_substr ( substr ){}
2012-10-12 07:58:17 +01:00
StartsWith ( const StartsWith & other ) : m_substr ( other . m_substr ){}
2012-05-21 18:52:09 +01:00
2012-10-12 07:58:17 +01:00
virtual ~ StartsWith ();
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-05-21 18:52:09 +01:00
}
std :: string m_substr ;
};
2012-10-12 07:58:17 +01:00
struct EndsWith : MatcherImpl < EndsWith , std :: string > {
2012-05-21 18:52:09 +01:00
EndsWith ( const std :: string & substr ) : m_substr ( substr ){}
2012-10-12 07:58:17 +01:00
EndsWith ( const EndsWith & other ) : m_substr ( other . m_substr ){}
2012-05-21 18:52:09 +01:00
2012-10-12 07:58:17 +01:00
virtual ~ EndsWith ();
virtual bool match ( const std :: string & expr ) const {
return expr . find ( m_substr ) == expr . size () - m_substr . size ();
}
virtual std :: string toString () const {
return "ends with: \" " + m_substr + " \" " ;
2012-05-21 18:52:09 +01:00
}
std :: string m_substr ;
};
} // namespace StdString
} // namespace Impl
2012-10-12 07:58:17 +01: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-05-24 08:29:41 +01:00
inline Impl :: StdString :: Equals Equals ( const std :: string & str ){ return Impl :: StdString :: Equals ( str ); }
2012-05-21 18:52:09 +01:00
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 ); }
} // namespace Matchers
using namespace Matchers ;
} // namespace Catch
2012-06-02 23:12:42 +01:00
// These files are included here so the single_include script doesn't put them
// in the conditionally compiled sections
// #included from: internal/catch_interfaces_runner.h
2012-09-17 01:42:29 -04:00
#define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED
2012-06-02 23:12:42 +01:00
#include <string>
namespace Catch {
2012-12-01 23:57:18 +00:00
class TestCase ;
2012-06-02 23:12:42 +01:00
struct IRunner {
2012-08-13 07:46:10 +01:00
virtual ~ IRunner ();
2012-06-02 23:12:42 +01:00
};
}
2012-05-21 18:52:09 +01:00
#ifdef __OBJC__
// #included from: internal/catch_objc.hpp
2012-08-09 07:47:30 +01:00
#define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED
2012-05-21 18:52:09 +01:00
#import <objc/runtime.h>
#include <string>
// NB. Any general catch headers included here must be included
// in catch.hpp first to make sure they are included by the single
// header for non obj-usage
2011-08-15 09:06:31 +01:00
2011-08-12 18:53:28 +01:00
///////////////////////////////////////////////////////////////////////////////
// This protocol is really only here for (self) documenting purposes, since
// all its methods are optional.
@ protocol OcFixture
@ optional
- ( void ) setUp ;
- ( void ) tearDown ;
@ end
2012-05-16 15:09:17 +01:00
namespace Catch {
2011-08-12 18:53:28 +01:00
2012-08-16 18:48:50 +01:00
class OcMethod : public SharedImpl < ITestCase > {
2012-05-16 15:09:17 +01:00
public :
OcMethod ( Class cls , SEL sel ) : m_cls ( cls ), m_sel ( sel ) {}
virtual void invoke () const {
2012-03-17 18:20:06 +00:00
id obj = [[ m_cls alloc ] init ];
2011-08-12 18:53:28 +01:00
2012-03-17 18:20:06 +00:00
performOptionalSelector ( obj , @ selector ( setUp ) );
performOptionalSelector ( obj , m_sel );
performOptionalSelector ( obj , @ selector ( tearDown ) );
2011-08-12 18:53:28 +01:00
2012-03-17 18:20:06 +00:00
arcSafeRelease ( obj );
2011-08-12 18:53:28 +01:00
}
private :
2012-08-16 18:48:50 +01:00
virtual ~ OcMethod () {}
2011-08-12 18:53:28 +01:00
Class m_cls ;
SEL m_sel ;
};
2012-05-16 15:09:17 +01:00
namespace Detail {
2011-08-12 18:53:28 +01:00
2012-05-16 15:09:17 +01:00
inline bool startsWith ( const std :: string & str , const std :: string & sub ) {
2011-08-12 18:53:28 +01:00
return str . length () > sub . length () && str . substr ( 0 , sub . length () ) == sub ;
}
2012-05-16 15:09:17 +01:00
inline std :: string getAnnotation ( Class cls ,
const std :: string & annotationName ,
const std :: string & testCaseName ) {
2011-08-12 18:53:28 +01:00
NSString * selStr = [[ NSString alloc ] initWithFormat : @ "Catch_%s_%s" , annotationName . c_str (), testCaseName . c_str ()];
SEL sel = NSSelectorFromString ( selStr );
2012-03-17 18:20:06 +00:00
arcSafeRelease ( selStr );
id value = performOptionalSelector ( cls , sel );
if ( value )
return [( NSString * ) value UTF8String ];
2011-08-12 18:53:28 +01:00
return "" ;
}
}
2012-05-16 15:09:17 +01:00
inline size_t registerTestMethods () {
2011-08-12 18:53:28 +01:00
size_t noTestMethods = 0 ;
int noClasses = objc_getClassList ( NULL , 0 );
2012-04-28 12:29:52 +01:00
Class * classes = ( CATCH_UNSAFE_UNRETAINED Class * ) malloc ( sizeof ( Class ) * noClasses );
2012-03-17 18:20:06 +00:00
objc_getClassList ( classes , noClasses );
2011-08-12 18:53:28 +01:00
2012-05-16 15:09:17 +01:00
for ( int c = 0 ; c < noClasses ; c ++ ) {
2011-08-12 18:53:28 +01:00
Class cls = classes [ c ];
{
u_int count ;
Method * methods = class_copyMethodList ( cls , & count );
2012-05-22 08:56:59 +01:00
for ( u_int m = 0 ; m < count ; m ++ ) {
2011-08-12 18:53:28 +01:00
SEL selector = method_getName ( methods [ m ]);
std :: string methodName = sel_getName ( selector );
2012-05-16 15:09:17 +01:00
if ( Detail :: startsWith ( methodName , "Catch_TestCase_" ) ) {
2011-08-12 18:53:28 +01:00
std :: string testCaseName = methodName . substr ( 15 );
2012-03-17 18:20:06 +00:00
std :: string name = Detail :: getAnnotation ( cls , "Name" , testCaseName );
std :: string desc = Detail :: getAnnotation ( cls , "Description" , testCaseName );
2011-08-12 18:53:28 +01:00
2012-12-06 08:44:51 +00:00
getMutableRegistryHub (). registerTest ( makeTestCase ( new OcMethod ( cls , selector ), "" , name . c_str (), desc . c_str (), SourceLineInfo () ) );
2011-08-12 18:53:28 +01:00
noTestMethods ++ ;
}
}
free ( methods );
}
}
return noTestMethods ;
}
2012-03-04 21:22:36 +00:00
2012-05-16 15:09:17 +01:00
namespace Matchers {
namespace Impl {
namespace NSStringMatchers {
2012-12-06 08:44:51 +00:00
template < typename MatcherT >
struct StringHolder : MatcherImpl < MatcherT , NSString *> {
2012-03-04 21:22:36 +00:00
StringHolder ( NSString * substr ) : m_substr ( [ substr copy ] ){}
2012-12-06 08:44:51 +00:00
StringHolder ( StringHolder const & other ) : m_substr ( [ other . m_substr copy ] ){}
2012-05-16 15:09:17 +01:00
StringHolder () {
2012-03-17 18:20:06 +00:00
arcSafeRelease ( m_substr );
2012-03-04 21:22:36 +00:00
}
NSString * m_substr ;
};
2012-12-06 08:44:51 +00:00
struct Equals : StringHolder < Equals > {
2012-03-14 20:06:14 +00:00
Equals ( NSString * substr ) : StringHolder ( substr ){}
2012-12-06 08:44:51 +00:00
virtual bool match ( ExpressionType const & str ) const {
2012-03-14 20:06:14 +00:00
return [ str isEqualToString : m_substr ];
}
2012-12-06 08:44:51 +00:00
virtual std :: string toString () const {
return "equals string: \" " + Catch :: toString ( m_substr ) + " \" " ;
2012-03-14 20:06:14 +00:00
}
};
2012-12-06 08:44:51 +00:00
struct Contains : StringHolder < Contains > {
2012-03-04 21:22:36 +00:00
Contains ( NSString * substr ) : StringHolder ( substr ){}
2012-12-06 08:44:51 +00:00
virtual bool match ( ExpressionType const & str ) const {
2012-03-04 21:22:36 +00:00
return [ str rangeOfString : m_substr ]. location != NSNotFound ;
}
2012-12-06 08:44:51 +00:00
virtual std :: string toString () const {
return "contains string: \" " + Catch :: toString ( m_substr ) + " \" " ;
2012-03-04 21:22:36 +00:00
}
};
2012-12-06 08:44:51 +00:00
struct StartsWith : StringHolder < StartsWith > {
2012-03-04 21:22:36 +00:00
StartsWith ( NSString * substr ) : StringHolder ( substr ){}
2012-12-06 08:44:51 +00:00
virtual bool match ( ExpressionType const & str ) const {
2012-03-04 21:22:36 +00:00
return [ str rangeOfString : m_substr ]. location == 0 ;
}
2012-12-06 08:44:51 +00:00
virtual std :: string toString () const {
return "starts with: \" " + Catch :: toString ( m_substr ) + " \" " ;
2012-03-04 21:22:36 +00:00
}
};
2012-12-06 08:44:51 +00:00
struct EndsWith : StringHolder < EndsWith > {
2012-03-04 21:22:36 +00:00
EndsWith ( NSString * substr ) : StringHolder ( substr ){}
2012-12-06 08:44:51 +00:00
virtual bool match ( ExpressionType const & str ) const {
2012-03-04 21:22:36 +00:00
return [ str rangeOfString : m_substr ]. location == [ str length ] - [ m_substr length ];
}
2012-12-06 08:44:51 +00:00
virtual std :: string toString () const {
return "ends with: \" " + Catch :: toString ( m_substr ) + " \" " ;
2012-03-04 21:22:36 +00:00
}
};
} // namespace NSStringMatchers
} // namespace Impl
2012-03-14 20:06:14 +00:00
inline Impl :: NSStringMatchers :: Equals
Equals ( NSString * substr ){ return Impl :: NSStringMatchers :: Equals ( substr ); }
2012-03-04 21:22:36 +00:00
inline Impl :: NSStringMatchers :: Contains
Contains ( NSString * substr ){ return Impl :: NSStringMatchers :: Contains ( substr ); }
2012-03-14 20:06:14 +00:00
2012-03-04 21:22:36 +00:00
inline Impl :: NSStringMatchers :: StartsWith
StartsWith ( NSString * substr ){ return Impl :: NSStringMatchers :: StartsWith ( substr ); }
2012-03-14 20:06:14 +00:00
2012-03-04 21:22:36 +00:00
inline Impl :: NSStringMatchers :: EndsWith
EndsWith ( NSString * substr ){ return Impl :: NSStringMatchers :: EndsWith ( substr ); }
} // namespace Matchers
using namespace Matchers ;
} // namespace Catch
2011-08-12 18:53:28 +01:00
///////////////////////////////////////////////////////////////////////////////
#define OC_TEST_CASE( name, desc )\
2012-03-17 18:20:06 +00:00
+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \
2011-08-12 18:53:28 +01:00
{\
2012-03-17 18:20:06 +00:00
return @ name; \
2011-08-12 18:53:28 +01:00
}\
2012-03-17 18:20:06 +00:00
+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \
2011-08-12 18:53:28 +01:00
{ \
2012-03-17 18:20:06 +00:00
return @ desc; \
2011-08-12 18:53:28 +01:00
} \
-(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test )
#endif
#if defined( CATCH_CONFIG_MAIN ) || defined( CATCH_CONFIG_RUNNER )
2012-08-13 07:46:10 +01:00
// #included from: internal/catch_impl.hpp
2012-09-17 01:42:29 -04:00
#define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED
2012-08-13 07:46:10 +01:00
// Collect all the implementation files together here
// These are the equivalent of what would usually be cpp files
2012-08-16 18:48:50 +01:00
#ifdef __clang__
2012-08-13 07:46:10 +01:00
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wweak-vtables"
2012-08-16 18:48:50 +01:00
#endif
2012-08-13 07:46:10 +01:00
2011-08-12 18:53:28 +01:00
// #included from: catch_runner.hpp
2012-08-09 07:47:30 +01:00
#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED
2011-08-12 18:53:28 +01:00
2012-08-13 07:46:10 +01:00
// #included from: internal/catch_commandline.hpp
#define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED
namespace Catch {
class Command {
public :
Command (){}
2012-08-27 21:42:55 +01:00
explicit Command ( const std :: string & name ) : m_name ( name ) {
}
2012-08-13 07:46:10 +01: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 ;
}
operator SafeBool :: type () const {
2012-08-24 18:54:56 +01:00
return SafeBool :: makeSafe ( ! m_name . empty () || ! m_args . empty () );
2012-08-13 07:46:10 +01: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 (); }
CATCH_ATTRIBUTE_NORETURN
void raiseError ( const std :: string & message ) const {
std :: ostringstream oss ;
2012-08-27 21:42:55 +01:00
if ( m_name . empty () )
oss << "Error while parsing " << m_name << ". " << message << "." ;
else
oss << "Error while parsing arguments. " << message << "." ;
2012-08-13 07:46:10 +01:00
if ( m_args . size () > 0 )
2012-08-27 21:42:55 +01:00
oss << " Arguments were:" ;
2012-08-13 07:46:10 +01:00
for ( std :: size_t i = 0 ; i < m_args . size (); ++ i )
oss << " " << m_args [ i ];
throw std :: domain_error ( oss . str () );
}
private :
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 17:52:35 +01:00
std :: string exeName () const {
2012-11-19 19:59:10 +00: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 17:52:35 +01:00
}
2012-08-13 07:46:10 +01: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 21:42:55 +01: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-13 07:46:10 +01:00
return Command ();
}
2012-08-24 18:54:56 +01:00
Command getDefaultArgs () const {
return getArgs ( "" , 1 );
}
2012-08-13 07:46:10 +01:00
private :
2012-08-24 18:54:56 +01: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-13 07:46:10 +01:00
command += m_argv [ i ];
return command ;
}
std :: size_t m_argc ;
char const * const * m_argv ;
};
2012-08-27 21:42:55 +01:00
class OptionParser : public SharedImpl < IShared > {
public :
OptionParser ( int minArgs = 0 , int maxArgs = 0 )
: m_minArgs ( minArgs ), m_maxArgs ( maxArgs )
{}
2012-08-13 07:46:10 +01:00
2012-08-27 21:42:55 +01:00
virtual ~ OptionParser () {}
2012-08-13 07:46:10 +01:00
2012-08-27 21:42:55 +01: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 ;
}
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-13 07:46:10 +01:00
else
2012-08-27 21:42:55 +01:00
oss << "Expected between " << m_minArgs << " and " << m_maxArgs << " argument" ;
args . raiseError ( oss . str () );
2012-08-13 07:46:10 +01:00
}
2012-08-27 21:42:55 +01:00
}
void parseIntoConfig ( const CommandParser & parser , ConfigData & config ) {
if ( Command cmd = find ( parser ) ) {
validateArgs ( cmd );
parseIntoConfig ( cmd , config );
}
}
virtual void parseIntoConfig ( const Command & cmd , ConfigData & config ) = 0 ;
virtual std :: string argsSynopsis () const = 0 ;
virtual std :: string optionSummary () const = 0 ;
2012-09-07 17:52:35 +01:00
virtual std :: string optionDescription () const { return "" ; };
2012-08-27 21:42:55 +01: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 ;
}
protected :
bool tooFewArgs ( const Command & args ) const {
return args . argsCount () < static_cast < std :: size_t > ( m_minArgs );
}
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 18:38:26 +01:00
return "[<option for help on> ...]" ;
2012-08-27 21:42:55 +01:00
}
virtual std :: string optionSummary () const {
2012-09-26 18:38:26 +01:00
return "Shows this usage summary, or help on a specific option, or options, if supplied" ;
2012-09-07 17:52:35 +01:00
}
virtual std :: string optionDescription () const {
return "" ;
2012-08-27 21:42:55 +01: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 17:52:35 +01: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 11:44:30 +01: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 08:30:13 +01:00
"inclusion spec included them. Subsequent inclusion specs will take precedence, however. "
2012-09-09 11:44:30 +01: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 21:42:55 +01: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 17:52:35 +01:00
for ( std :: size_t i = 0 ; i < cmd . argsCount (); ++ i )
filters . addFilter ( TestCaseFilter ( cmd [ i ] ) );
2012-08-27 21:42:55 +01:00
config . filters . push_back ( filters );
}
};
2012-09-24 08:30:13 +01: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 19:34:35 +00: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 08:30:13 +01:00
}
virtual void parseIntoConfig ( const Command & cmd , ConfigData & config ) {
2012-09-26 18:38:26 +01: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 08:30:13 +01:00
}
};
2012-08-27 21:42:55 +01: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 17:52:35 +01:00
return "Lists available tests or reporters" ;
}
virtual std :: string optionDescription () const {
2012-09-09 11:44:30 +01: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 21:42:55 +01: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 17:52:35 +01:00
return "Specifies type of reporter" ;
}
virtual std :: string optionDescription () const {
2012-09-09 11:44:30 +01:00
return
"A reporter is an object that formats and structures the output of running "
"tests, and potentially summarises the results. By default a basic reporter "
"is used that writes IDE friendly results. CATCH comes bundled with some "
"alternative reporters, but more can be added in client code. \n "
" \n "
"The bundled reporters are: \n "
" -r basic \n "
" -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 21:42:55 +01: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 17:52:35 +01:00
return "Sends output to a file or stream" ;
2012-08-27 21:42:55 +01:00
}
2012-09-09 11:44:30 +01: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 08:30:13 +01:00
"sent to stdout (note that uses of stdout and stderr from within test cases are "
2012-09-09 11:44:30 +01:00
"redirected and included in the report - so even stderr will effectively end up "
2012-09-24 08:30:13 +01:00
"on stdout). If the name begins with % it is interpreted as a stream. "
2012-09-09 11:44:30 +01: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 21:42:55 +01:00
virtual void parseIntoConfig ( const Command & cmd , ConfigData & config ) {
if ( cmd [ 0 ][ 0 ] == '%' )
config . stream = cmd [ 0 ]. substr ( 1 );
2012-08-13 07:46:10 +01:00
else
2012-08-27 21:42:55 +01:00
config . outputFilename = cmd [ 0 ];
2012-08-13 07:46:10 +01:00
}
2012-08-27 21:42:55 +01:00
};
2012-08-13 07:46:10 +01:00
2012-09-09 11:44:30 +01:00
class SuccessOptionParser : public OptionParser {
2012-08-27 21:42:55 +01:00
public :
2012-09-09 11:44:30 +01:00
SuccessOptionParser () {
2012-08-27 21:42:55 +01:00
m_optionNames . push_back ( "-s" );
m_optionNames . push_back ( "--success" );
2012-08-23 20:08:50 +01:00
}
2012-08-27 21:42:55 +01:00
virtual std :: string argsSynopsis () const {
return "" ;
2012-08-23 20:08:50 +01:00
}
2012-08-27 21:42:55 +01:00
virtual std :: string optionSummary () const {
2012-09-07 17:52:35 +01:00
return "Shows results for successful tests" ;
2012-08-13 07:46:10 +01:00
}
2012-09-09 11:44:30 +01: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 08:30:13 +01:00
"added worked first time!). To see successful, as well as failing, test results "
2012-09-09 11:44:30 +01:00
"just pass this option." ;
}
2012-08-27 21:48:15 +01:00
virtual void parseIntoConfig ( const Command & , ConfigData & config ) {
2012-08-27 21:42:55 +01:00
config . includeWhichResults = Include :: SuccessfulResults ;
}
};
2012-08-13 07:46:10 +01:00
2012-08-27 21:42:55 +01:00
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 17:52:35 +01:00
return "Breaks into the debugger on failure" ;
2012-08-27 21:42:55 +01:00
}
2012-09-09 11:44:30 +01: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 21:42:55 +01:00
2012-08-27 21:48:15 +01:00
virtual void parseIntoConfig ( const Command & , ConfigData & config ) {
2012-08-27 21:42:55 +01: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 17:52:35 +01:00
return "Names a test run" ;
2012-08-27 21:42:55 +01:00
}
2012-09-09 11:44:30 +01: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 21:42:55 +01: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 17:52:35 +01:00
return "Aborts after a certain number of failures" ;
2012-08-27 21:42:55 +01:00
}
2012-09-09 11:44:30 +01: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 21:42:55 +01: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 17:52:35 +01:00
return "Elides assertions expected to throw" ;
2012-08-27 21:42:55 +01:00
}
2012-09-09 11:44:30 +01: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 21:42:55 +01:00
2012-08-27 21:48:15 +01:00
virtual void parseIntoConfig ( const Command & , ConfigData & config ) {
2012-08-27 21:42:55 +01:00
config . allowThrows = false ;
}
};
2012-08-31 08:10:36 +01: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 17:52:35 +01:00
return "Enable warnings" ;
2012-08-31 08:10:36 +01:00
}
2012-09-09 11:44:30 +01: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 08:10:36 +01: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-13 07:46:10 +01:00
}
2012-08-27 21:42:55 +01: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 08:10:36 +01:00
add < Options :: TestCaseOptionParser > (); // Keep this one first
2012-09-26 18:38:26 +01:00
add < Options :: TagOptionParser > ();
2012-08-27 21:42:55 +01:00
add < Options :: ListOptionParser > ();
add < Options :: ReporterOptionParser > ();
add < Options :: OutputOptionParser > ();
2012-09-09 11:44:30 +01:00
add < Options :: SuccessOptionParser > ();
2012-08-27 21:42:55 +01:00
add < Options :: DebugBreakOptionParser > ();
add < Options :: NameOptionParser > ();
add < Options :: AbortOptionParser > ();
add < Options :: NoThrowOptionParser > ();
2012-08-31 08:10:36 +01:00
add < Options :: WarningsOptionParser > ();
add < Options :: HelpOptionParser > (); // Keep this one last
2012-08-27 21:42:55 +01:00
}
void parseIntoConfig ( const CommandParser & parser , ConfigData & config ) {
2012-11-19 19:59:10 +00:00
config . name = parser . exeName ();
if ( endsWith ( config . name , ".exe" ) )
config . name = config . name . substr ( 0 , config . name . size () - 4 );
2012-08-27 21:42:55 +01:00
for ( const_iterator it = m_parsers . begin (); it != m_parsers . end (); ++ it )
( * it ) -> parseIntoConfig ( parser , config );
}
const_iterator begin () const {
return m_parsers . begin ();
}
const_iterator end () const {
return m_parsers . end ();
}
private :
template < typename T >
void add () {
m_parsers . push_back ( new T () );
}
Parsers m_parsers ;
};
2012-08-13 07:46:10 +01:00
} // end namespace Catch
// #included from: internal/catch_list.hpp
#define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED
#include <limits>
namespace Catch {
2012-12-01 23:57:18 +00:00
inline bool matchesFilters ( const std :: vector < TestCaseFilters >& filters , const TestCase & testCase ) {
2012-08-23 20:08:50 +01: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 ) {
2012-08-13 07:46:10 +01:00
2012-08-16 18:48:50 +01:00
if ( config . listSpec & List :: Reports ) {
2012-08-13 07:46:10 +01:00
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 " ;
}
std :: cout << std :: endl ;
}
2012-08-16 18:48:50 +01:00
if ( config . listSpec & List :: Tests ) {
2012-08-23 20:08:50 +01:00
if ( config . filters . empty () )
2012-08-24 08:23:50 +01:00
std :: cout << "All available test cases: \n " ;
2012-08-23 20:08:50 +01:00
else
2012-08-24 08:23:50 +01:00
std :: cout << "Matching test cases: \n " ;
2012-12-01 23:57:18 +00:00
std :: vector < TestCase >:: const_iterator it = getRegistryHub (). getTestCaseRegistry (). getAllTests (). begin ();
std :: vector < TestCase >:: const_iterator itEnd = getRegistryHub (). getTestCaseRegistry (). getAllTests (). end ();
2012-08-24 08:23:50 +01:00
std :: size_t matchedTests = 0 ;
2012-08-13 07:46:10 +01:00
for (; it != itEnd ; ++ it ) {
2012-08-23 20:08:50 +01:00
if ( matchesFilters ( config . filters , * it ) ) {
2012-08-24 08:23:50 +01:00
matchedTests ++ ;
2012-08-23 20:08:50 +01:00
// !TBD: consider listAs()
2012-12-01 23:57:18 +00:00
std :: cout << " \t " << it -> getTestCaseInfo (). name << " \n " ;
2012-08-23 20:08:50 +01:00
if ( ( config . listSpec & List :: TestNames ) != List :: TestNames )
2012-12-01 23:57:18 +00:00
std :: cout << " \t\t '" << it -> getTestCaseInfo (). description << "' \n " ;
2012-08-23 20:08:50 +01:00
}
2012-08-13 07:46:10 +01:00
}
2012-08-24 08:23:50 +01:00
if ( config . filters . empty () )
std :: cout << pluralise ( matchedTests , "test case" ) << std :: endl ;
else
std :: cout << pluralise ( matchedTests , "matching test case" ) << std :: endl ;
2012-08-13 07:46:10 +01:00
}
2012-08-16 18:48:50 +01:00
if ( ( config . listSpec & List :: All ) == 0 ) {
2012-08-23 20:08:50 +01:00
std :: ostringstream oss ;
oss << "Unknown list type" ;
throw std :: domain_error ( oss . str () );
2012-08-13 07:46:10 +01:00
}
}
} // end namespace Catch
// #included from: internal/catch_runner_impl.hpp
2012-09-17 01:42:29 -04:00
#define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED
2012-08-13 07:46:10 +01:00
// #included from: catch_running_test.hpp
2012-09-17 01:42:29 -04:00
#define TWOBLUECUBES_CATCH_RUNNING_TEST_HPP_INCLUDED
2012-08-13 07:46:10 +01:00
// #included from: catch_section_info.hpp
2012-09-17 01:42:29 -04:00
#define TWOBLUECUBES_CATCH_SECTION_INFO_HPP_INCLUDED
2012-08-13 07:46:10 +01:00
#include <map>
#include <string>
namespace Catch {
2012-12-01 23:57:18 +00:00
class RunningSection {
2012-08-13 07:46:10 +01:00
public :
2012-12-01 23:57:18 +00:00
typedef std :: vector < RunningSection *> SubSections ;
enum State {
2012-08-13 07:46:10 +01:00
Root ,
Unknown ,
Branch ,
TestedBranch ,
TestedLeaf
};
2012-12-01 23:57:18 +00:00
RunningSection ( RunningSection * parent , const std :: string & name )
: m_state ( Unknown ),
m_parent ( parent ),
m_name ( name )
2012-08-13 07:46:10 +01:00
{}
2012-12-01 23:57:18 +00:00
RunningSection ( const std :: string & name )
: m_state ( Root ),
m_parent ( NULL ),
m_name ( name )
2012-08-13 07:46:10 +01:00
{}
2012-12-01 23:57:18 +00:00
~ RunningSection () {
deleteAll ( m_subSections );
}
std :: string getName () const {
return m_name ;
2012-08-13 07:46:10 +01:00
}
bool shouldRun () const {
2012-12-01 23:57:18 +00:00
return m_state < TestedBranch ;
2012-08-13 07:46:10 +01:00
}
2012-08-31 08:10:36 +01:00
bool isBranch () const {
2012-12-01 23:57:18 +00:00
return m_state == Branch ;
2012-08-31 08:10:36 +01:00
}
2012-12-01 23:57:18 +00:00
const RunningSection * getParent () const {
2012-08-13 07:46:10 +01:00
return m_parent ;
}
bool hasUntestedSections () const {
2012-12-01 23:57:18 +00:00
if ( m_state == Unknown )
2012-08-13 07:46:10 +01:00
return true ;
2012-12-01 23:57:18 +00:00
for ( SubSections :: const_iterator it = m_subSections . begin ();
it != m_subSections . end ();
++ it )
if ( ( * it ) -> hasUntestedSections () )
2012-08-13 07:46:10 +01:00
return true ;
return false ;
}
2012-12-01 23:57:18 +00:00
// Mutable methods:
RunningSection * getParent () {
return m_parent ;
}
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 ;
}
bool ran () {
if ( m_state >= Branch )
return false ;
m_state = TestedLeaf ;
return true ;
}
void ranToCompletion () {
if ( m_state == Branch && ! hasUntestedSections () )
m_state = TestedBranch ;
}
2012-08-13 07:46:10 +01:00
private :
2012-12-01 23:57:18 +00:00
State m_state ;
RunningSection * m_parent ;
std :: string m_name ;
SubSections m_subSections ;
2012-08-13 07:46:10 +01:00
};
}
namespace Catch {
class RunningTest {
enum RunStatus {
NothingRun ,
EncounteredASection ,
RanAtLeastOneSection ,
RanToCompletionWithSections ,
RanToCompletionWithNoSections
};
public :
2012-12-01 23:57:18 +00:00
explicit RunningTest ( const TestCase & info )
2012-08-13 07:46:10 +01:00
: m_info ( info ),
m_runStatus ( RanAtLeastOneSection ),
2012-12-01 23:57:18 +00:00
m_rootSection ( info . getTestCaseInfo (). name ),
2012-08-13 07:46:10 +01:00
m_currentSection ( & m_rootSection ),
m_changed ( false )
{}
bool wasSectionSeen () const {
return m_runStatus == RanAtLeastOneSection ||
m_runStatus == RanToCompletionWithSections ;
}
2012-08-31 08:10:36 +01: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-13 07:46:10 +01:00
void reset () {
m_runStatus = NothingRun ;
m_changed = false ;
m_lastSectionToRun = NULL ;
}
void ranToCompletion () {
2012-12-01 23:57:18 +00:00
if ( m_runStatus != RanAtLeastOneSection && m_runStatus != EncounteredASection )
2012-08-13 07:46:10 +01:00
m_runStatus = RanToCompletionWithNoSections ;
2012-12-01 23:57:18 +00:00
m_runStatus = RanToCompletionWithSections ;
if ( m_lastSectionToRun ) {
m_lastSectionToRun -> ranToCompletion ();
m_changed = true ;
2012-08-13 07:46:10 +01:00
}
}
bool addSection ( const std :: string & name ) {
if ( m_runStatus == NothingRun )
m_runStatus = EncounteredASection ;
2012-12-01 23:57:18 +00:00
RunningSection * thisSection = m_currentSection -> findOrAddSubSection ( name , m_changed );
2012-08-13 07:46:10 +01:00
if ( ! wasSectionSeen () && thisSection -> shouldRun () ) {
m_currentSection = thisSection ;
m_lastSectionToRun = NULL ;
return true ;
}
return false ;
}
void endSection ( const std :: string & ) {
if ( m_currentSection -> ran () ) {
m_runStatus = RanAtLeastOneSection ;
m_changed = true ;
}
else if ( m_runStatus == EncounteredASection ) {
m_runStatus = RanAtLeastOneSection ;
m_lastSectionToRun = m_currentSection ;
}
m_currentSection = m_currentSection -> getParent ();
}
2012-12-01 23:57:18 +00:00
const TestCase & getTestCase () const {
return m_info ;
2012-08-13 07:46:10 +01:00
}
bool hasUntestedSections () const {
return m_runStatus == RanAtLeastOneSection ||
( m_rootSection . hasUntestedSections () && m_changed );
}
private :
2012-12-01 23:57:18 +00:00
const TestCase & m_info ;
2012-08-13 07:46:10 +01:00
RunStatus m_runStatus ;
2012-12-01 23:57:18 +00:00
RunningSection m_rootSection ;
RunningSection * m_currentSection ;
RunningSection * m_lastSectionToRun ;
2012-08-13 07:46:10 +01:00
bool m_changed ;
};
}
#include <set>
#include <string>
namespace Catch {
class StreamRedirect {
public :
StreamRedirect ( std :: ostream & stream , std :: string & targetString )
: m_stream ( stream ),
m_prevBuf ( stream . rdbuf () ),
m_targetString ( targetString )
{
stream . rdbuf ( m_oss . rdbuf () );
}
~ StreamRedirect () {
m_targetString += m_oss . str ();
m_stream . rdbuf ( m_prevBuf );
}
private :
std :: ostream & m_stream ;
std :: streambuf * m_prevBuf ;
std :: ostringstream m_oss ;
std :: string & m_targetString ;
};
///////////////////////////////////////////////////////////////////////////
class Runner : public IResultCapture , public IRunner {
Runner ( const Runner & );
void operator = ( const Runner & );
public :
2012-12-01 23:57:18 +00:00
explicit Runner ( const Config & config , const Ptr < IStreamingReporter >& reporter )
: m_runInfo ( config . data (). name ),
m_context ( getCurrentMutableContext () ),
2012-08-13 07:46:10 +01: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-01 23:57:18 +00:00
m_reporter -> testRunStarting ( m_runInfo );
2012-08-13 07:46:10 +01:00
}
virtual ~ Runner () {
2012-12-01 23:57:18 +00:00
m_reporter -> testRunEnded ( new TestRunStats ( m_runInfo , m_totals , aborting () ) );
2012-08-13 07:46:10 +01:00
m_context . setRunner ( m_prevRunner );
m_context . setConfig ( NULL );
m_context . setResultCapture ( m_prevResultCapture );
m_context . setConfig ( m_prevConfig );
}
2012-12-01 23:57:18 +00:00
void testGroupStarting ( std :: string const & testSpec ) {
m_reporter -> testGroupStarting ( GroupInfo ( testSpec ) );
}
void testGroupEnded ( std :: string const & testSpec , Totals const & totals ) {
m_reporter -> testGroupEnded ( new TestGroupStats ( GroupInfo ( testSpec ), totals , aborting () ) );
}
2012-08-23 20:08:50 +01:00
Totals runMatching ( const std :: string & testSpec ) {
2012-08-13 07:46:10 +01:00
2012-12-01 23:57:18 +00:00
std :: vector < TestCase > matchingTests = getRegistryHub (). getTestCaseRegistry (). getMatchingTestCases ( testSpec );
2012-08-16 18:48:50 +01:00
Totals totals ;
2012-12-01 23:57:18 +00:00
testGroupStarting ( testSpec );
2012-08-23 20:08:50 +01:00
2012-12-01 23:57:18 +00:00
std :: vector < TestCase >:: const_iterator it = matchingTests . begin ();
std :: vector < TestCase >:: const_iterator itEnd = matchingTests . end ();
2012-08-23 20:08:50 +01:00
for (; it != itEnd ; ++ it )
totals += runTest ( * it );
2012-12-01 23:57:18 +00:00
testGroupEnded ( testSpec , totals );
2012-08-16 18:48:50 +01:00
return totals ;
}
2012-12-01 23:57:18 +00:00
Totals runTest ( const TestCase & testCase ) {
2012-08-13 07:46:10 +01:00
Totals prevTotals = m_totals ;
std :: string redirectedCout ;
std :: string redirectedCerr ;
2012-12-01 23:57:18 +00:00
TestCaseInfo testInfo = testCase . getTestCaseInfo ();
2012-08-13 07:46:10 +01:00
2012-12-01 23:57:18 +00:00
m_reporter -> testCaseStarting ( testInfo );
m_runningTest = new RunningTest ( testCase );
2012-08-13 07:46:10 +01:00
do {
do {
runCurrentTest ( redirectedCout , redirectedCerr );
}
while ( m_runningTest -> hasUntestedSections () && ! aborting () );
}
while ( getCurrentContext (). advanceGeneratorsForCurrentTest () && ! aborting () );
2012-11-21 18:06:13 +00:00
Totals deltaTotals = m_totals . delta ( prevTotals );
2012-12-01 23:57:18 +00:00
bool missingAssertions = false ;
2012-11-21 18:06:13 +00:00
if ( deltaTotals . assertions . total () == 0 &&
( m_config . data (). warnings & ConfigData :: WarnAbout :: NoAssertions ) ) {
m_totals . assertions . failed ++ ;
deltaTotals = m_totals . delta ( prevTotals );
2012-12-01 23:57:18 +00:00
missingAssertions = true ;
2012-11-21 18:06:13 +00:00
}
2012-12-01 23:57:18 +00:00
2012-11-21 18:06:13 +00:00
m_totals . testCases += deltaTotals . testCases ;
2012-12-01 23:57:18 +00:00
m_reporter -> testCaseEnded ( new TestCaseStats ( testInfo ,
deltaTotals ,
redirectedCout ,
redirectedCerr ,
missingAssertions ,
aborting () ) );
2012-11-21 18:06:13 +00:00
2012-08-13 07:46:10 +01:00
delete m_runningTest ;
m_runningTest = NULL ;
2012-08-16 18:48:50 +01:00
return deltaTotals ;
2012-08-13 07:46:10 +01:00
}
const Config & config () const {
return m_config ;
}
private : // IResultCapture
2012-10-29 20:49:22 +00:00
virtual ResultAction :: Value acceptExpression ( const ExpressionResultBuilder & assertionResult , const AssertionInfo & assertionInfo ) {
2012-11-04 21:39:38 +00:00
m_lastAssertionInfo = assertionInfo ;
return actOnCurrentResult ( assertionResult . buildResult ( assertionInfo ) );
2012-08-13 07:46:10 +01:00
}
2012-10-28 12:07:17 +00:00
virtual void testEnded ( const AssertionResult & result ) {
2012-08-13 07:46:10 +01:00
if ( result . getResultType () == ResultWas :: Ok ) {
m_totals . assertions . passed ++ ;
}
2012-11-13 09:44:52 +00:00
else if ( ! result . isOk () ) {
2012-08-13 07:46:10 +01:00
m_totals . assertions . failed ++ ;
2012-09-24 08:30:13 +01:00
{
std :: vector < ScopedInfo *>:: const_iterator it = m_scopedInfos . begin ();
std :: vector < ScopedInfo *>:: const_iterator itEnd = m_scopedInfos . end ();
for (; it != itEnd ; ++ it )
2012-12-01 23:57:18 +00:00
m_reporter -> assertionEnded ( new AssertionStats ( ( * it ) -> buildResult ( m_lastAssertionInfo ), m_totals ) );
2012-09-24 08:30:13 +01:00
}
{
2012-10-28 12:07:17 +00:00
std :: vector < AssertionResult >:: const_iterator it = m_assertionResults . begin ();
std :: vector < AssertionResult >:: const_iterator itEnd = m_assertionResults . end ();
2012-09-24 08:30:13 +01:00
for (; it != itEnd ; ++ it )
2012-12-01 23:57:18 +00:00
m_reporter -> assertionEnded ( new AssertionStats ( * it , m_totals ) );
2012-09-24 08:30:13 +01:00
}
2012-10-28 12:07:17 +00:00
m_assertionResults . clear ();
2012-08-13 07:46:10 +01:00
}
if ( result . getResultType () == ResultWas :: Info )
2012-11-21 18:06:13 +00:00
{
2012-10-28 12:07:17 +00:00
m_assertionResults . push_back ( result );
2012-11-21 18:06:13 +00:00
m_totals . assertions . info ++ ;
}
2012-08-13 07:46:10 +01:00
else
2012-12-01 23:57:18 +00:00
m_reporter -> assertionEnded ( new AssertionStats ( result , m_totals ) );
2012-11-19 19:59:10 +00:00
// Reset AssertionInfo
m_lastAssertionInfo = AssertionInfo ( "" , m_lastAssertionInfo . lineInfo , "{Unknown expression after this line}" , m_lastAssertionInfo . resultDisposition );
2012-08-13 07:46:10 +01:00
}
virtual bool sectionStarted (
2012-12-01 23:57:18 +00:00
SectionInfo const & sectionInfo ,
2012-08-13 07:46:10 +01:00
Counts & assertions
)
{
std :: ostringstream oss ;
2012-12-01 23:57:18 +00:00
oss << sectionInfo . name << "@" << sectionInfo . lineInfo ;
2012-08-13 07:46:10 +01:00
if ( ! m_runningTest -> addSection ( oss . str () ) )
return false ;
2012-12-01 23:57:18 +00:00
m_lastAssertionInfo . lineInfo = sectionInfo . lineInfo ;
m_reporter -> sectionStarting ( sectionInfo );
2012-11-04 21:39:38 +00:00
2012-08-13 07:46:10 +01:00
assertions = m_totals . assertions ;
return true ;
}
2012-12-01 23:57:18 +00:00
virtual void sectionEnded ( SectionInfo const & info , Counts const & prevAssertions ) {
2012-08-31 08:10:36 +01:00
Counts assertions = m_totals . assertions - prevAssertions ;
2012-12-01 23:57:18 +00:00
bool missingAssertions = false ;
2012-11-21 18:06:13 +00:00
if ( assertions . total () == 0 &&
2012-08-31 08:10:36 +01:00
( m_config . data (). warnings & ConfigData :: WarnAbout :: NoAssertions ) &&
! m_runningTest -> isBranchSection () ) {
m_totals . assertions . failed ++ ;
assertions . failed ++ ;
2012-12-01 23:57:18 +00:00
missingAssertions = true ;
2012-08-31 08:10:36 +01:00
}
2012-12-01 23:57:18 +00:00
m_runningTest -> endSection ( info . name );
m_reporter -> sectionEnded ( new SectionStats ( info , assertions , missingAssertions ) );
2012-08-13 07:46:10 +01:00
}
virtual void pushScopedInfo ( ScopedInfo * scopedInfo ) {
m_scopedInfos . push_back ( scopedInfo );
}
virtual void popScopedInfo ( ScopedInfo * scopedInfo ) {
if ( m_scopedInfos . back () == scopedInfo )
m_scopedInfos . pop_back ();
}
virtual bool shouldDebugBreak () const {
return m_config . shouldDebugBreak ();
}
virtual std :: string getCurrentTestName () const {
return m_runningTest
2012-12-01 23:57:18 +00:00
? m_runningTest -> getTestCase (). getTestCaseInfo (). name
2012-08-13 07:46:10 +01:00
: "" ;
}
2012-10-28 12:07:17 +00:00
virtual const AssertionResult * getLastResult () const {
2012-08-13 07:46:10 +01:00
return & m_lastResult ;
}
2012-08-23 20:08:50 +01:00
public :
// !TBD We need to do this another way!
2012-08-13 07:46:10 +01:00
bool aborting () const {
return m_totals . assertions . failed == static_cast < std :: size_t > ( m_config . getCutoff () );
}
2012-08-23 20:08:50 +01:00
private :
2012-11-04 21:39:38 +00:00
ResultAction :: Value actOnCurrentResult ( const AssertionResult & result ) {
m_lastResult = result ;
2012-10-09 11:48:55 +01:00
testEnded ( m_lastResult );
2012-08-13 07:46:10 +01:00
ResultAction :: Value action = ResultAction :: None ;
2012-11-13 09:44:52 +00:00
if ( ! m_lastResult . isOk () ) {
2012-08-13 07:46:10 +01:00
action = ResultAction :: Failed ;
if ( shouldDebugBreak () )
action = ( ResultAction :: Value )( action | ResultAction :: Debug );
if ( aborting () )
action = ( ResultAction :: Value )( action | ResultAction :: Abort );
}
return action ;
}
void runCurrentTest ( std :: string & redirectedCout , std :: string & redirectedCerr ) {
try {
2012-12-01 23:57:18 +00:00
m_lastAssertionInfo = AssertionInfo ( "TEST_CASE" , m_runningTest -> getTestCase (). getTestCaseInfo (). lineInfo , "" , ResultDisposition :: Normal );
2012-08-13 07:46:10 +01:00
m_runningTest -> reset ();
2012-12-01 23:57:18 +00:00
if ( m_reporter -> getPreferences (). shouldRedirectStdOut ) {
2012-08-13 07:46:10 +01:00
StreamRedirect coutRedir ( std :: cout , redirectedCout );
StreamRedirect cerrRedir ( std :: cerr , redirectedCerr );
2012-12-01 23:57:18 +00:00
m_runningTest -> getTestCase (). invoke ();
2012-08-13 07:46:10 +01:00
}
else {
2012-12-01 23:57:18 +00:00
m_runningTest -> getTestCase (). invoke ();
2012-08-13 07:46:10 +01:00
}
m_runningTest -> ranToCompletion ();
}
catch ( TestFailureException & ) {
// This just means the test was aborted due to failure
}
catch (...) {
2012-11-04 21:39:38 +00:00
ExpressionResultBuilder exResult ( ResultWas :: ThrewException );
exResult << translateActiveException ();
actOnCurrentResult ( exResult . buildResult ( m_lastAssertionInfo ) );
2012-08-13 07:46:10 +01:00
}
2012-10-28 12:07:17 +00:00
m_assertionResults . clear ();
2012-08-13 07:46:10 +01:00
}
private :
2012-12-01 23:57:18 +00:00
TestRunInfo m_runInfo ;
2012-08-13 07:46:10 +01:00
IMutableContext & m_context ;
RunningTest * m_runningTest ;
2012-10-28 12:07:17 +00:00
AssertionResult m_lastResult ;
2012-08-13 07:46:10 +01:00
const Config & m_config ;
Totals m_totals ;
2012-12-01 23:57:18 +00:00
Ptr < IStreamingReporter > m_reporter ;
2012-08-13 07:46:10 +01:00
std :: vector < ScopedInfo *> m_scopedInfos ;
2012-10-28 12:07:17 +00:00
std :: vector < AssertionResult > m_assertionResults ;
2012-08-13 07:46:10 +01:00
IRunner * m_prevRunner ;
IResultCapture * m_prevResultCapture ;
const IConfig * m_prevConfig ;
2012-11-04 21:39:38 +00:00
AssertionInfo m_lastAssertionInfo ;
2012-08-13 07:46:10 +01:00
};
} // end namespace Catch
2012-11-15 22:15:41 +00:00
// #included from: internal/catch_version.h
#define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED
namespace Catch {
// Versioning information
struct Version {
2012-12-01 23:57:18 +00:00
Version ( unsigned int _majorVersion ,
unsigned int _minorVersion ,
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 22:15:41 +00:00
};
extern Version libraryVersion ;
}
2011-05-24 08:23:02 +01:00
#include <fstream>
#include <stdlib.h>
#include <limits>
2012-05-16 15:09:17 +01:00
namespace Catch {
2012-08-23 20:08:50 +01:00
class Runner2 { // This will become Runner when Runner becomes Context
2012-05-31 19:40:26 +01:00
2012-08-23 20:08:50 +01:00
public :
Runner2 ( Config & configWrapper )
: m_configWrapper ( configWrapper ),
m_config ( configWrapper . data () )
2012-05-25 08:52:05 +01:00
{
2012-09-26 18:38:26 +01:00
openStream ();
2012-08-23 20:08:50 +01:00
makeReporter ();
}
2012-05-25 08:52:05 +01:00
2012-08-23 20:08:50 +01:00
Totals runTests () {
std :: vector < TestCaseFilters > filterGroups = m_config . filters ;
if ( filterGroups . empty () ) {
TestCaseFilters filterGroup ( "" );
filterGroups . push_back ( filterGroup );
2011-05-24 08:23:02 +01:00
}
2012-08-23 20:08:50 +01:00
Runner context ( m_configWrapper , m_reporter ); // This Runner will be renamed Context
Totals totals ;
std :: vector < TestCaseFilters >:: const_iterator it = filterGroups . begin ();
std :: vector < TestCaseFilters >:: const_iterator itEnd = filterGroups . end ();
2012-12-01 23:57:18 +00:00
2012-09-07 17:52:35 +01:00
for (; it != itEnd && ! context . aborting (); ++ it ) {
2012-12-01 23:57:18 +00:00
context . testGroupStarting ( it -> getName () );
2012-08-31 18:46:13 +01:00
totals += runTestsForGroup ( context , * it );
2012-12-01 23:57:18 +00:00
context . testGroupEnded ( it -> getName (), totals );
2012-08-23 20:08:50 +01:00
}
return totals ;
}
Totals runTestsForGroup ( Runner & context , const TestCaseFilters & filterGroup ) {
Totals totals ;
2012-12-01 23:57:18 +00:00
std :: vector < TestCase >:: const_iterator it = getRegistryHub (). getTestCaseRegistry (). getAllTests (). begin ();
std :: vector < TestCase >:: const_iterator itEnd = getRegistryHub (). getTestCaseRegistry (). getAllTests (). end ();
2012-08-23 20:08:50 +01:00
int testsRunForGroup = 0 ;
for (; it != itEnd ; ++ it ) {
if ( filterGroup . shouldInclude ( * it ) ) {
testsRunForGroup ++ ;
if ( m_testsAlreadyRun . find ( * it ) == m_testsAlreadyRun . end () ) {
if ( context . aborting () )
break ;
totals += context . runTest ( * it );
m_testsAlreadyRun . insert ( * it );
}
2012-05-25 08:52:05 +01:00
}
}
2012-08-23 20:08:50 +01:00
if ( testsRunForGroup == 0 )
std :: cerr << " \n [No test cases matched with: " << filterGroup . getName () << "]" << std :: endl ;
return totals ;
2011-05-24 08:23:02 +01:00
}
2012-08-23 20:08:50 +01:00
private :
2012-09-26 18:38:26 +01:00
void openStream () {
if ( ! m_config . stream . empty () )
m_configWrapper . useStream ( m_config . stream );
2012-08-23 20:08:50 +01: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 08:54:57 +00:00
? "console"
2012-08-23 20:08:50 +01:00
: m_config . reporter ;
2012-12-01 23:57:18 +00:00
ReporterConfig reporterConfig ( m_configWrapper . stream (), m_config );
2012-08-23 20:08:50 +01: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-01 23:57:18 +00:00
Ptr < IStreamingReporter > m_reporter ;
std :: set < TestCase > m_testsAlreadyRun ;
2012-08-23 20:08:50 +01:00
};
inline int Main ( Config & configWrapper ) {
int result = 0 ;
try
{
Runner2 runner ( configWrapper );
const ConfigData & config = configWrapper . data ();
// Handle list request
if ( config . listSpec != List :: None ) {
List ( config );
2012-09-24 08:30:13 +01:00
Catch :: cleanUp ();
2012-08-23 20:08:50 +01:00
return 0 ;
}
result = static_cast < int > ( runner . runTests (). assertions . failed );
}
catch ( std :: exception & ex ) {
std :: cerr << ex . what () << std :: endl ;
result = ( std :: numeric_limits < int >:: max )();
}
2012-08-09 07:47:30 +01:00
Catch :: cleanUp ();
2012-05-21 18:52:09 +01:00
return result ;
2011-05-24 08:23:02 +01:00
}
2012-05-31 19:40:26 +01:00
inline void showUsage ( std :: ostream & os ) {
2012-08-27 21:42:55 +01:00
AllOptions options ;
2012-09-07 17:52:35 +01:00
2012-08-27 21:42:55 +01: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-05-31 19:40:26 +01:00
}
2012-09-07 17:52:35 +01:00
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 << " \n " ;
}
2012-09-09 11:44:30 +01:00
2012-09-07 17:52:35 +01:00
inline std :: string addLineBreaks ( const std :: string & str , std :: size_t columns , std :: size_t indent = 0 ) {
std :: ostringstream oss ;
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 ( oss , paragraph , columns , indent );
pos = newline + 1 ;
newline = str . find_first_of ( '\n' , pos );
}
2012-09-09 11:44:30 +01:00
if ( pos != str . size () )
recursivelyWrapLine ( oss , str . substr ( pos , str . size () - pos ), columns , indent );
2012-09-07 17:52:35 +01:00
return oss . str ();
}
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 "
<< addLineBreaks ( opt . optionDescription (), 80 , 2 ) << " \n " << std :: endl ;
}
}
if ( ! displayedSpecificOption ) {
2012-12-01 23:57:18 +00:00
std :: cout << " \n CATCH v" << libraryVersion . majorVersion << "."
<< libraryVersion . minorVersion << " build "
<< libraryVersion . buildNumber ;
if ( libraryVersion . branchName != "master" )
std :: cout << " (" << libraryVersion . branchName << " branch)" ;
2012-11-15 22:15:41 +00:00
2012-11-19 19:59:10 +00:00
std :: cout << " \n\n " << parser . exeName () << " is a CATCH host application. Options are as follows: \n\n " ;
2012-09-07 17:52:35 +01:00
showUsage ( std :: cout );
}
2011-05-24 08:23:02 +01:00
}
2012-05-16 15:09:17 +01:00
inline int Main ( int argc , char * const argv [], Config & config ) {
2012-05-31 19:40:26 +01:00
2012-07-05 18:37:58 +01:00
try {
CommandParser parser ( argc , argv );
2011-05-24 08:23:02 +01:00
2012-08-27 21:42:55 +01:00
if ( Command cmd = Options :: HelpOptionParser (). find ( parser ) ) {
2012-07-05 18:37:58 +01:00
if ( cmd . argsCount () != 0 )
cmd . raiseError ( "Does not accept arguments" );
2012-09-07 17:52:35 +01:00
showHelp ( parser );
2012-08-09 07:47:30 +01:00
Catch :: cleanUp ();
2012-07-05 18:37:58 +01:00
return 0 ;
}
2012-08-27 21:42:55 +01:00
AllOptions options ;
options . parseIntoConfig ( parser , config . data () );
2012-07-05 18:37:58 +01:00
}
catch ( std :: exception & ex ) {
2012-07-23 08:24:52 +01:00
std :: cerr << ex . what () << " \n\n Usage: ... \n\n " ;
2012-05-31 19:40:26 +01:00
showUsage ( std :: cerr );
2012-08-09 07:47:30 +01:00
Catch :: cleanUp ();
2011-05-24 08:23:02 +01:00
return ( std :: numeric_limits < int >:: max )();
}
return Main ( config );
}
2012-05-16 15:09:17 +01:00
inline int Main ( int argc , char * const argv [] ) {
2011-05-24 08:23:02 +01:00
Config config ;
2012-05-21 18:52:09 +01:00
// !TBD: This doesn't always work, for some reason
2011-05-24 08:23:02 +01:00
// if( isDebuggerActive() )
// config.useStream( "debug" );
2012-05-21 18:52:09 +01:00
return Main ( argc , argv , config );
2011-05-24 08:23:02 +01:00
}
} // end namespace Catch
2012-08-09 07:47:30 +01:00
// #included from: catch_registry_hub.hpp
2012-09-17 01:42:29 -04:00
#define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED
2012-08-09 07:47:30 +01:00
// #included from: catch_test_case_registry_impl.hpp
2012-09-17 01:42:29 -04:00
#define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
2012-08-09 07:47:30 +01:00
#include <vector>
#include <set>
#include <sstream>
#include <iostream>
namespace Catch {
class TestRegistry : public ITestCaseRegistry {
public :
TestRegistry () : m_unnamedCount ( 0 ) {}
2012-08-13 07:46:10 +01:00
virtual ~ TestRegistry ();
2012-08-09 07:47:30 +01:00
2012-12-01 23:57:18 +00:00
virtual void registerTest ( const TestCase & testCase ) {
std :: string name = testCase . getTestCaseInfo (). name ;
if ( name == "" ) {
2012-08-09 07:47:30 +01:00
std :: ostringstream oss ;
2012-12-01 23:57:18 +00:00
oss << name << "unnamed/" << ++ m_unnamedCount ;
return registerTest ( testCase . withName ( oss . str () ) );
2012-08-09 07:47:30 +01:00
}
2012-12-01 23:57:18 +00: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-09 07:47:30 +01:00
}
else {
2012-12-01 23:57:18 +00: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-09 07:47:30 +01:00
exit ( 1 );
}
}
2012-12-01 23:57:18 +00:00
virtual const std :: vector < TestCase >& getAllTests () const {
2012-08-09 07:47:30 +01:00
return m_functionsInOrder ;
}
2012-12-01 23:57:18 +00:00
virtual const std :: vector < TestCase >& getAllNonHiddenTests () const {
2012-08-16 18:48:50 +01:00
return m_nonHiddenFunctions ;
}
2012-08-23 20:08:50 +01:00
// !TBD deprecated
2012-12-01 23:57:18 +00:00
virtual std :: vector < TestCase > getMatchingTestCases ( const std :: string & rawTestSpec ) const {
std :: vector < TestCase > matchingTests ;
2012-08-16 18:48:50 +01:00
getMatchingTestCases ( rawTestSpec , matchingTests );
return matchingTests ;
}
2012-08-23 20:08:50 +01:00
// !TBD deprecated
2012-12-01 23:57:18 +00:00
virtual void getMatchingTestCases ( const std :: string & rawTestSpec , std :: vector < TestCase >& matchingTestsOut ) const {
2012-08-23 20:08:50 +01:00
TestCaseFilter filter ( rawTestSpec );
2012-08-16 18:48:50 +01:00
2012-12-01 23:57:18 +00:00
std :: vector < TestCase >:: const_iterator it = m_functionsInOrder . begin ();
std :: vector < TestCase >:: const_iterator itEnd = m_functionsInOrder . end ();
2012-08-09 07:47:30 +01:00
for (; it != itEnd ; ++ it ) {
2012-08-23 20:08:50 +01:00
if ( filter . shouldInclude ( * it ) ) {
2012-08-16 18:48:50 +01:00
matchingTestsOut . push_back ( * it );
2012-08-09 07:47:30 +01:00
}
}
}
2012-12-01 23:57:18 +00: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 20:08:50 +01:00
// !TBD: replace with algorithm
for (; it != itEnd ; ++ it )
if ( filters . shouldInclude ( * it ) )
matchingTestsOut . push_back ( * it );
}
2012-08-09 07:47:30 +01:00
private :
2012-12-01 23:57:18 +00:00
std :: set < TestCase > m_functions ;
std :: vector < TestCase > m_functionsInOrder ;
std :: vector < TestCase > m_nonHiddenFunctions ;
2012-08-09 07:47:30 +01:00
size_t m_unnamedCount ;
};
///////////////////////////////////////////////////////////////////////////
2012-08-16 18:48:50 +01:00
class FreeFunctionTestCase : public SharedImpl < ITestCase > {
2012-08-09 07:47:30 +01:00
public :
FreeFunctionTestCase ( TestFunction fun ) : m_fun ( fun ) {}
virtual void invoke () const {
m_fun ();
}
private :
2012-08-16 18:48:50 +01:00
virtual ~ FreeFunctionTestCase ();
2012-08-09 07:47:30 +01:00
TestFunction m_fun ;
};
2012-11-04 21:39:38 +00: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-09 07:47:30 +01:00
///////////////////////////////////////////////////////////////////////////
AutoReg :: AutoReg ( TestFunction function ,
const char * name ,
const char * description ,
const SourceLineInfo & lineInfo ) {
2012-11-04 21:39:38 +00:00
registerTestCase ( new FreeFunctionTestCase ( function ), "global" , name , description , lineInfo );
2012-08-09 07:47:30 +01:00
}
AutoReg ::~ AutoReg () {}
void AutoReg :: registerTestCase ( ITestCase * testCase ,
2012-11-04 21:39:38 +00:00
const char * classOrQualifiedMethodName ,
2012-08-09 07:47:30 +01:00
const char * name ,
const char * description ,
const SourceLineInfo & lineInfo ) {
2012-11-04 21:39:38 +00:00
2012-12-01 23:57:18 +00:00
getMutableRegistryHub (). registerTest ( makeTestCase ( testCase , extractClassName ( classOrQualifiedMethodName ), name , description , lineInfo ) );
2012-08-09 07:47:30 +01:00
}
} // end namespace Catch
// #included from: catch_reporter_registry.hpp
#define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED
#include <map>
namespace Catch {
class ReporterRegistry : public IReporterRegistry {
public :
2012-08-13 07:46:10 +01:00
virtual ~ ReporterRegistry () {
2012-08-09 07:47:30 +01:00
deleteAllValues ( m_factories );
}
2012-12-01 23:57:18 +00:00
virtual IStreamingReporter * create ( const std :: string & name , const ReporterConfig & config ) const {
2012-08-09 07:47:30 +01:00
FactoryMap :: const_iterator it = m_factories . find ( name );
if ( it == m_factories . end () )
return NULL ;
return it -> second -> create ( config );
}
void registerReporter ( const std :: string & name , IReporterFactory * factory ) {
m_factories . insert ( std :: make_pair ( name , factory ) );
}
const FactoryMap & getFactories () const {
return m_factories ;
}
private :
FactoryMap m_factories ;
};
}
// #included from: catch_exception_translator_registry.hpp
2012-09-17 01:42:29 -04:00
#define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED
2012-08-09 07:47:30 +01:00
#ifdef __OBJC__
#import "Foundation/Foundation.h"
#endif
namespace Catch {
class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry {
public :
~ ExceptionTranslatorRegistry () {
deleteAll ( m_translators );
}
virtual void registerTranslator ( const IExceptionTranslator * translator ) {
m_translators . push_back ( translator );
}
virtual std :: string translateActiveException () const {
try {
#ifdef __OBJC__
// In Objective-C try objective-c exceptions first
@ try {
throw ;
}
@ catch ( NSException * exception ) {
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 () );
}
}
std :: string tryTranslators ( std :: vector < const IExceptionTranslator *>:: const_iterator it ) const {
if ( it == m_translators . end () )
return "Unknown exception" ;
try {
return ( * it ) -> translate ();
}
catch (...) {
return tryTranslators ( it + 1 );
}
}
private :
std :: vector < const IExceptionTranslator *> m_translators ;
};
}
namespace Catch {
namespace {
class RegistryHub : public IRegistryHub , public IMutableRegistryHub {
RegistryHub ( const RegistryHub & );
void operator = ( const RegistryHub & );
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 ;
}
public : // IMutableRegistryHub
virtual void registerReporter ( const std :: string & name , IReporterFactory * factory ) {
m_reporterRegistry . registerReporter ( name , factory );
}
2012-12-01 23:57:18 +00:00
virtual void registerTest ( const TestCase & testInfo ) {
2012-08-09 07:47:30 +01: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 ;
};
// Single, global, instance
inline RegistryHub *& getTheRegistryHub () {
static RegistryHub * theRegistryHub = NULL ;
if ( ! theRegistryHub )
theRegistryHub = new RegistryHub ();
return theRegistryHub ;
}
}
IRegistryHub & getRegistryHub () {
return * getTheRegistryHub ();
}
IMutableRegistryHub & getMutableRegistryHub () {
return * getTheRegistryHub ();
}
void cleanUp () {
delete getTheRegistryHub ();
getTheRegistryHub () = NULL ;
cleanUpContext ();
}
2012-10-28 12:07:17 +00:00
std :: string translateActiveException () {
return getRegistryHub (). getExceptionTranslatorRegistry (). translateActiveException ();
}
2012-08-09 07:47:30 +01:00
} // end namespace Catch
2012-09-17 01:42:29 -04:00
2012-08-09 07:47:30 +01:00
// #included from: catch_notimplemented_exception.hpp
#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED
#include <ostream>
namespace Catch {
NotImplementedException :: NotImplementedException ( const SourceLineInfo & lineInfo )
: m_lineInfo ( lineInfo ) {
std :: ostringstream oss ;
oss << lineInfo << "function " ;
oss << "not implemented" ;
m_what = oss . str ();
}
const char * NotImplementedException :: what () const throw () {
return m_what . c_str ();
}
} // end namespace Catch
// #included from: catch_context_impl.hpp
2012-09-17 01:42:29 -04:00
#define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED
2012-08-09 07:47:30 +01:00
namespace Catch {
class Context : public IMutableContext {
Context () : m_config ( NULL ) {}
Context ( const Context & );
void operator = ( const Context & );
public : // IContext
virtual IResultCapture & getResultCapture () {
return * m_resultCapture ;
}
virtual IRunner & getRunner () {
return * m_runner ;
}
virtual size_t getGeneratorIndex ( const std :: string & fileInfo , size_t totalSize ) {
return getGeneratorsForCurrentTest ()
. getGeneratorInfo ( fileInfo , totalSize )
. getCurrentIndex ();
}
virtual bool advanceGeneratorsForCurrentTest () {
IGeneratorsForTest * generators = findGeneratorsForCurrentTest ();
return generators && generators -> moveNext ();
}
virtual const IConfig * getConfig () const {
return m_config ;
}
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 ;
}
friend IMutableContext & getCurrentMutableContext ();
private :
IGeneratorsForTest * findGeneratorsForCurrentTest () {
std :: string testName = getResultCapture (). getCurrentTestName ();
std :: map < std :: string , IGeneratorsForTest *>:: const_iterator it =
m_generatorsByTestName . find ( testName );
return it != m_generatorsByTestName . end ()
? it -> second
: NULL ;
}
IGeneratorsForTest & getGeneratorsForCurrentTest () {
IGeneratorsForTest * generators = findGeneratorsForCurrentTest ();
if ( ! generators ) {
std :: string testName = getResultCapture (). getCurrentTestName ();
generators = createGeneratorsForTest ();
m_generatorsByTestName . insert ( std :: make_pair ( testName , generators ) );
}
return * generators ;
}
private :
IRunner * m_runner ;
IResultCapture * m_resultCapture ;
const IConfig * m_config ;
std :: map < std :: string , IGeneratorsForTest *> m_generatorsByTestName ;
};
namespace {
Context * currentContext = NULL ;
}
IMutableContext & getCurrentMutableContext () {
if ( ! currentContext )
currentContext = new Context ();
return * currentContext ;
}
IContext & getCurrentContext () {
return getCurrentMutableContext ();
}
2012-09-26 18:38:26 +01: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 07:47:30 +01:00
throw std :: domain_error ( "Unknown stream: " + streamName );
}
void cleanUpContext () {
delete currentContext ;
currentContext = NULL ;
}
}
2012-09-17 01:42:29 -04:00
2012-08-09 07:47:30 +01:00
// #included from: catch_console_colour_impl.hpp
#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED
2012-08-23 20:08:50 +01:00
// #included from: catch_console_colour.hpp
#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED
namespace Catch {
struct ConsoleColourImpl ;
class TextColour : NonCopyable {
public :
enum Colours {
None ,
FileName ,
ResultError ,
ResultSuccess ,
Error ,
Success ,
OriginalExpression ,
ReconstructedExpression
};
TextColour ( Colours colour = None );
void set ( Colours colour );
~ TextColour ();
private :
ConsoleColourImpl * m_impl ;
};
} // end namespace Catch
2012-10-31 18:04:22 +00:00
#if defined( CATCH_CONFIG_USE_ANSI_COLOUR_CODES )
#include <unistd.h>
2012-10-29 20:49:22 +00:00
namespace Catch {
2012-10-31 18:04:22 +00:00
// use POSIX/ ANSI console terminal codes
2012-10-29 20:49:22 +00:00
// Implementation contributed by Adam Strzelecki (http://github.com/nanoant)
// https://github.com/philsquared/Catch/pull/131
TextColour :: TextColour ( Colours colour ) {
if ( colour )
set ( colour );
}
TextColour ::~ TextColour () {
set ( TextColour :: None );
}
2012-10-31 18:04:22 +00:00
namespace { const char colourEscape = '\033' ; }
2012-10-29 20:49:22 +00:00
void TextColour :: set ( Colours colour ) {
if ( isatty ( fileno ( stdout ) ) ) {
switch ( colour ) {
case TextColour :: FileName :
2012-11-04 21:39:38 +00:00
std :: cout << colourEscape << "[0m" ; // white/ normal
2012-10-29 20:49:22 +00:00
break ;
case TextColour :: ResultError :
2012-10-31 18:04:22 +00:00
std :: cout << colourEscape << "[1;31m" ; // bold red
2012-10-29 20:49:22 +00:00
break ;
case TextColour :: ResultSuccess :
2012-10-31 18:04:22 +00:00
std :: cout << colourEscape << "[1;32m" ; // bold green
2012-10-29 20:49:22 +00:00
break ;
case TextColour :: Error :
2012-10-31 18:04:22 +00:00
std :: cout << colourEscape << "[0;31m" ; // red
2012-10-29 20:49:22 +00:00
break ;
case TextColour :: Success :
2012-10-31 18:04:22 +00:00
std :: cout << colourEscape << "[0;32m" ; // green
2012-10-29 20:49:22 +00:00
break ;
case TextColour :: OriginalExpression :
2012-10-31 18:04:22 +00:00
std :: cout << colourEscape << "[0;36m" ; // cyan
2012-10-29 20:49:22 +00:00
break ;
case TextColour :: ReconstructedExpression :
2012-10-31 18:04:22 +00:00
std :: cout << colourEscape << "[0;33m" ; // yellow
2012-10-29 20:49:22 +00:00
break ;
case TextColour :: None :
2012-11-04 21:39:38 +00:00
std :: cout << colourEscape << "[0m" ; // reset
2012-10-29 20:49:22 +00:00
}
}
}
2012-10-31 18:04:22 +00:00
} // namespace Catch
2012-10-29 20:49:22 +00:00
#elif defined ( CATCH_PLATFORM_WINDOWS )
2012-08-09 07:47:30 +01:00
#include <windows.h>
2012-10-31 18:04:22 +00:00
namespace Catch {
2012-08-09 07:47:30 +01:00
namespace {
WORD mapConsoleColour ( TextColour :: Colours colour ) {
switch ( colour ) {
case TextColour :: FileName :
return FOREGROUND_INTENSITY ; // greyed out
case TextColour :: ResultError :
return FOREGROUND_RED | FOREGROUND_INTENSITY ; // bright red
case TextColour :: ResultSuccess :
return FOREGROUND_GREEN | FOREGROUND_INTENSITY ; // bright green
case TextColour :: Error :
return FOREGROUND_RED ; // dark red
case TextColour :: Success :
return FOREGROUND_GREEN ; // dark green
case TextColour :: OriginalExpression :
return FOREGROUND_BLUE | FOREGROUND_GREEN ; // turquoise
case TextColour :: ReconstructedExpression :
return FOREGROUND_RED | FOREGROUND_GREEN ; // greeny-yellow
default : return 0 ;
}
}
}
struct ConsoleColourImpl {
ConsoleColourImpl ()
: hStdout ( GetStdHandle ( STD_OUTPUT_HANDLE ) ),
wOldColorAttrs ( 0 )
{
GetConsoleScreenBufferInfo ( hStdout , & csbiInfo );
wOldColorAttrs = csbiInfo . wAttributes ;
}
~ ConsoleColourImpl () {
SetConsoleTextAttribute ( hStdout , wOldColorAttrs );
}
void set ( TextColour :: Colours colour ) {
WORD consoleColour = mapConsoleColour ( colour );
if ( consoleColour > 0 )
SetConsoleTextAttribute ( hStdout , consoleColour );
}
HANDLE hStdout ;
CONSOLE_SCREEN_BUFFER_INFO csbiInfo ;
WORD wOldColorAttrs ;
};
TextColour :: TextColour ( Colours colour )
: m_impl ( new ConsoleColourImpl () )
{
if ( colour )
m_impl -> set ( colour );
}
TextColour ::~ TextColour () {
delete m_impl ;
}
void TextColour :: set ( Colours colour ) {
m_impl -> set ( colour );
}
2012-10-31 18:04:22 +00:00
} // end namespace Catch
2012-08-09 07:47:30 +01:00
#else
2012-10-31 18:04:22 +00:00
namespace Catch {
2012-08-09 07:47:30 +01:00
TextColour :: TextColour ( Colours ){}
TextColour ::~ TextColour (){}
void TextColour :: set ( Colours ){}
2012-10-29 20:49:22 +00:00
} // end namespace Catch
2012-10-31 18:04:22 +00:00
#endif
2012-08-09 07:47:30 +01:00
// #included from: catch_generators_impl.hpp
#define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED
#include <vector>
#include <string>
#include <map>
namespace Catch {
struct GeneratorInfo : IGeneratorInfo {
GeneratorInfo ( std :: size_t size )
: m_size ( size ),
m_currentIndex ( 0 )
{}
bool moveNext () {
if ( ++ m_currentIndex == m_size ) {
m_currentIndex = 0 ;
return false ;
}
return true ;
}
std :: size_t getCurrentIndex () const {
return m_currentIndex ;
}
std :: size_t m_size ;
std :: size_t m_currentIndex ;
};
///////////////////////////////////////////////////////////////////////////
class GeneratorsForTest : public IGeneratorsForTest {
public :
~ GeneratorsForTest () {
deleteAll ( m_generatorsInOrder );
}
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 ;
}
bool moveNext () {
std :: vector < IGeneratorInfo *>:: const_iterator it = m_generatorsInOrder . begin ();
std :: vector < IGeneratorInfo *>:: const_iterator itEnd = m_generatorsInOrder . end ();
for (; it != itEnd ; ++ it ) {
if ( ( * it ) -> moveNext () )
return true ;
}
return false ;
}
private :
std :: map < std :: string , IGeneratorInfo *> m_generatorsByName ;
std :: vector < IGeneratorInfo *> m_generatorsInOrder ;
};
IGeneratorsForTest * createGeneratorsForTest ()
{
return new GeneratorsForTest ();
}
} // end namespace Catch
2012-10-28 12:07:17 +00:00
// #included from: catch_assertionresult.hpp
#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED
2012-08-09 07:47:30 +01:00
namespace Catch {
2012-11-13 09:44:52 +00: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 12:07:17 +00:00
AssertionResult :: AssertionResult () {}
2012-08-09 07:47:30 +01:00
2012-10-28 12:07:17 +00:00
AssertionResult :: AssertionResult ( const AssertionInfo & info , const AssertionResultData & data )
: m_info ( info ),
m_resultData ( data )
{}
2012-08-09 07:47:30 +01:00
2012-10-28 12:07:17 +00:00
AssertionResult ::~ AssertionResult () {}
2012-08-09 07:47:30 +01:00
2012-11-13 09:44:52 +00:00
// Result was a success
bool AssertionResult :: succeeded () const {
return Catch :: isOk ( m_resultData . resultType );
}
// Result was a success, or failure is suppressed
bool AssertionResult :: isOk () const {
return Catch :: isOk ( m_resultData . resultType ) || shouldSuppressFailure ( m_info . resultDisposition );
2012-08-09 07:47:30 +01:00
}
2012-10-28 12:07:17 +00:00
ResultWas :: OfType AssertionResult :: getResultType () const {
return m_resultData . resultType ;
2012-08-09 07:47:30 +01:00
}
2012-10-28 12:07:17 +00:00
bool AssertionResult :: hasExpression () const {
return ! m_info . capturedExpression . empty ();
2012-08-09 07:47:30 +01:00
}
2012-10-28 12:07:17 +00:00
bool AssertionResult :: hasMessage () const {
return ! m_resultData . message . empty ();
2012-08-09 07:47:30 +01:00
}
2012-10-28 12:07:17 +00:00
std :: string AssertionResult :: getExpression () const {
return m_info . capturedExpression ;
2012-08-09 07:47:30 +01:00
}
2012-10-28 12:07:17 +00:00
bool AssertionResult :: hasExpandedExpression () const {
2012-10-09 11:48:55 +01:00
return hasExpression () && getExpandedExpression () != getExpression ();
2012-08-09 07:47:30 +01:00
}
2012-10-28 12:07:17 +00:00
std :: string AssertionResult :: getExpandedExpression () const {
return m_resultData . reconstructedExpression ;
2012-08-09 07:47:30 +01:00
}
2012-10-28 12:07:17 +00:00
std :: string AssertionResult :: getMessage () const {
return m_resultData . message ;
}
SourceLineInfo AssertionResult :: getSourceInfo () const {
return m_info . lineInfo ;
2012-08-09 07:47:30 +01:00
}
2012-10-28 12:07:17 +00:00
std :: string AssertionResult :: getTestMacroName () const {
return m_info . macroName ;
2012-08-09 07:47:30 +01:00
}
} // end namespace Catch
2012-10-28 12:07:17 +00:00
// #included from: catch_expressionresult_builder.hpp
#define TWOBLUECUBES_CATCH_EXPRESSIONRESULT_BUILDER_HPP_INCLUDED
#include <assert.h>
2012-08-09 07:47:30 +01:00
namespace Catch {
2012-10-28 12:07:17 +00:00
ExpressionResultBuilder :: ExpressionResultBuilder ( ResultWas :: OfType resultType ) {
m_data . resultType = resultType ;
2012-10-09 11:48:55 +01:00
}
2012-10-28 12:07:17 +00:00
ExpressionResultBuilder :: ExpressionResultBuilder ( const ExpressionResultBuilder & other )
: m_data ( other . m_data ),
m_exprComponents ( other . m_exprComponents )
2012-10-09 11:48:55 +01:00
{
2012-10-28 12:07:17 +00:00
m_stream << other . m_stream . str ();
2012-08-09 07:47:30 +01:00
}
2012-10-28 12:07:17 +00: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 ();
return * this ;
}
ExpressionResultBuilder & ExpressionResultBuilder :: setResultType ( ResultWas :: OfType result ) {
m_data . resultType = result ;
return * this ;
}
ExpressionResultBuilder & ExpressionResultBuilder :: setResultType ( bool result ) {
m_data . resultType = result ? ResultWas :: Ok : ResultWas :: ExpressionFailed ;
return * this ;
}
2012-11-10 18:46:39 +00:00
ExpressionResultBuilder & ExpressionResultBuilder :: endExpression ( ResultDisposition :: Flags resultDisposition ) {
2012-11-13 09:44:52 +00:00
m_exprComponents . shouldNegate = shouldNegate ( resultDisposition );
2012-10-28 12:07:17 +00:00
return * this ;
}
ExpressionResultBuilder & ExpressionResultBuilder :: setLhs ( const std :: string & lhs ) {
m_exprComponents . lhs = lhs ;
return * this ;
}
ExpressionResultBuilder & ExpressionResultBuilder :: setRhs ( const std :: string & rhs ) {
m_exprComponents . rhs = rhs ;
return * this ;
}
ExpressionResultBuilder & ExpressionResultBuilder :: setOp ( const std :: string & op ) {
m_exprComponents . op = op ;
return * this ;
}
AssertionResult ExpressionResultBuilder :: buildResult ( const AssertionInfo & info ) const
{
assert ( m_data . resultType != ResultWas :: Unknown );
2012-08-09 07:47:30 +01:00
2012-10-28 12:07:17 +00:00
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 == "" )
data . reconstructedExpression = "!" + data . reconstructedExpression ;
2012-10-09 11:48:55 +01:00
else
2012-10-28 12:07:17 +00:00
data . reconstructedExpression = "!(" + data . reconstructedExpression + ")" ;
}
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 != "!" ) {
if ( m_exprComponents . lhs . size () + m_exprComponents . rhs . size () < 30 )
return m_exprComponents . lhs + " " + m_exprComponents . op + " " + m_exprComponents . rhs ;
else if ( m_exprComponents . lhs . size () < 70 && m_exprComponents . rhs . size () < 70 )
return " \n\t " + m_exprComponents . lhs + " \n\t " + m_exprComponents . op + " \n\t " + m_exprComponents . rhs ;
else
return " \n " + m_exprComponents . lhs + " \n " + m_exprComponents . op + " \n " + m_exprComponents . rhs + " \n\n " ;
2012-10-09 11:48:55 +01:00
}
else
2012-10-28 12:07:17 +00: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 07:47:30 +01:00
}
} // end namespace Catch
2012-08-16 18:48:50 +01:00
// #included from: catch_test_case_info.hpp
2012-09-17 01:42:29 -04:00
#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED
2012-08-16 18:48:50 +01:00
namespace Catch {
2012-12-01 23:57:18 +00:00
TestCase makeTestCase ( ITestCase * _testCase ,
const std :: string & _className ,
const std :: string & _name ,
const std :: string & _descOrTags ,
const SourceLineInfo & _lineInfo )
2012-09-15 17:53:27 +01:00
{
2012-12-01 23:57:18 +00: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 );
2012-09-15 17:53:27 +01:00
}
2012-08-16 18:48:50 +01:00
2012-12-01 23:57:18 +00:00
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 08:44:51 +00:00
lineInfo ( _lineInfo ),
isHidden ( _isHidden )
2012-08-16 18:48:50 +01:00
{}
2012-08-23 19:48:57 +01:00
TestCaseInfo :: TestCaseInfo ( const TestCaseInfo & other )
2012-12-01 23:57:18 +00:00
: name ( other . name ),
className ( other . className ),
description ( other . description ),
tags ( other . tags ),
2012-12-06 08:44:51 +00:00
lineInfo ( other . lineInfo ),
isHidden ( other . isHidden )
2012-08-23 19:48:57 +01:00
{}
2012-12-01 23:57:18 +00:00
TestCase :: TestCase ( ITestCase * testCase , const TestCaseInfo & info ) : TestCaseInfo ( info ), test ( testCase ) {}
TestCase :: TestCase ( const TestCase & other )
: TestCaseInfo ( other ),
test ( other . test )
{}
TestCase TestCase :: withName ( const std :: string & _newName ) const {
TestCase other ( * this );
other . name = _newName ;
return other ;
2012-08-16 18:48:50 +01:00
}
2012-12-01 23:57:18 +00:00
void TestCase :: invoke () const {
test -> invoke ();
2012-08-16 18:48:50 +01:00
}
2012-12-01 23:57:18 +00:00
bool TestCase :: isHidden () const {
return TestCaseInfo :: isHidden ;
2012-09-15 17:53:27 +01:00
}
2012-12-01 23:57:18 +00:00
bool TestCase :: hasTag ( const std :: string & tag ) const {
return tags . find ( tag ) != tags . end ();
2012-09-15 17:53:27 +01:00
}
2012-12-01 23:57:18 +00:00
bool TestCase :: matchesTags ( const std :: string & tagPattern ) const {
2012-09-24 08:30:13 +01:00
TagExpression exp ;
TagExpressionParser ( exp ). parse ( tagPattern );
2012-12-01 23:57:18 +00:00
return exp . matches ( tags );
2012-09-24 08:30:13 +01:00
}
2012-12-01 23:57:18 +00:00
const std :: set < std :: string >& TestCase :: getTags () const {
return tags ;
2012-08-16 18:48:50 +01:00
}
2012-12-01 23:57:18 +00: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-16 18:48:50 +01:00
}
2012-12-01 23:57:18 +00:00
bool TestCase :: operator == ( const TestCase & other ) const {
return test . get () == other . test . get () &&
name == other . name &&
className == other . className ;
2012-08-16 18:48:50 +01:00
}
2012-12-01 23:57:18 +00:00
bool TestCase :: operator < ( const TestCase & other ) const {
return name < other . name ;
2012-08-16 18:48:50 +01:00
}
2012-12-01 23:57:18 +00:00
TestCase & TestCase :: operator = ( const TestCase & other ) {
TestCase temp ( other );
2012-08-23 19:48:57 +01:00
swap ( temp );
return * this ;
}
2012-09-24 08:30:13 +01:00
2012-12-01 23:57:18 +00:00
const TestCaseInfo & TestCase :: getTestCaseInfo () const
{
return * this ;
}
2012-09-24 08:30:13 +01:00
} // end namespace Catch
2012-08-16 18:48:50 +01:00
2012-11-15 22:15:41 +00:00
// #included from: catch_version.hpp
#define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED
namespace Catch {
// These numbers are maintained by a script
2012-12-14 07:50:08 +00:00
Version libraryVersion ( 0 , 9 , 12 , "integration" );
2012-11-15 22:15:41 +00:00
}
2012-08-23 20:08:50 +01:00
// #included from: ../reporters/catch_reporter_basic.hpp
#define TWOBLUECUBES_CATCH_REPORTER_BASIC_HPP_INCLUDED
// #included from: ../internal/catch_reporter_registrars.hpp
#define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
namespace Catch {
2012-12-01 23:57:18 +00:00
template < typename T >
class LegacyReporterRegistrar {
class ReporterFactory : public IReporterFactory {
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 20:08:50 +01:00
template < typename T >
class ReporterRegistrar {
class ReporterFactory : public IReporterFactory {
2012-12-01 23:57:18 +00:00
// *** Please Note ***:
// - If you end up here looking at a compiler error because it's trying to register
// your custom reporter class be aware that the native reporter interface has changed
// to IStreamingReporter. The "legacy" interface, IReporter, is still supported via
// an adapter. Just use REGISTER_LEGACY_REPORTER to take advantage of the adapter.
// However please consider updating to the new interface as the old one is now
// deprecated and will probably be removed quite soon!
// Please contact me via github if you have any questions at all about this.
// In fact, ideally, please contact me anyway to let me know you've hit this - as I have
// no idea who is actually using custom reporters at all (possibly no-one!).
// The new interface is designed to minimise exposure to interface changes in the future.
virtual IStreamingReporter * create ( const ReporterConfig & config ) const {
2012-08-23 20:08:50 +01:00
return new T ( config );
}
virtual std :: string getDescription () const {
return T :: getDescription ();
}
};
public :
ReporterRegistrar ( const std :: string & name ) {
getMutableRegistryHub (). registerReporter ( name , new ReporterFactory () );
}
};
}
2012-12-01 23:57:18 +00:00
#define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \
Catch::LegacyReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name );
2012-08-23 20:08:50 +01:00
#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \
Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name );
namespace Catch {
class BasicReporter : public SharedImpl < IReporter > {
struct SpanInfo {
SpanInfo ()
: emitted ( false )
{}
SpanInfo ( const std :: string & spanName )
: name ( spanName ),
emitted ( false )
{}
SpanInfo ( const SpanInfo & other )
: name ( other . name ),
emitted ( other . emitted )
{}
std :: string name ;
bool emitted ;
};
public :
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" ;
}
private :
void ReportCounts ( const std :: string & label , const Counts & counts , const std :: string & allPrefix = "All " ) {
if ( counts . passed )
2012-12-01 23:57:18 +00:00
m_config . stream () << counts . failed << " of " << counts . total () << " " << label << "s failed" ;
2012-08-23 20:08:50 +01:00
else
2012-12-01 23:57:18 +00:00
m_config . stream () << ( counts . failed > 1 ? allPrefix : "" ) << pluralise ( counts . failed , label ) << " failed" ;
2012-08-23 20:08:50 +01:00
}
void ReportCounts ( const Totals & totals , const std :: string & allPrefix = "All " ) {
if ( totals . assertions . total () == 0 ) {
2012-12-01 23:57:18 +00:00
m_config . stream () << "No tests ran" ;
2012-08-23 20:08:50 +01:00
}
else if ( totals . assertions . failed ) {
TextColour colour ( TextColour :: ResultError );
ReportCounts ( "test case" , totals . testCases , allPrefix );
if ( totals . testCases . failed > 0 ) {
2012-12-01 23:57:18 +00:00
m_config . stream () << " (" ;
2012-08-23 20:08:50 +01:00
ReportCounts ( "assertion" , totals . assertions , allPrefix );
2012-12-01 23:57:18 +00:00
m_config . stream () << ")" ;
2012-08-23 20:08:50 +01:00
}
}
else {
TextColour colour ( TextColour :: ResultSuccess );
2012-12-01 23:57:18 +00:00
m_config . stream () << allPrefix << "tests passed ("
2012-08-23 20:08:50 +01:00
<< pluralise ( totals . assertions . passed , "assertion" ) << " in "
<< pluralise ( totals . testCases . passed , "test case" ) << ")" ;
}
}
private : // IReporter
virtual bool shouldRedirectStdout () const {
return false ;
}
virtual void StartTesting () {
m_testingSpan = SpanInfo ();
}
virtual void Aborted () {
m_aborted = true ;
}
virtual void EndTesting ( const Totals & totals ) {
// Output the overall test results even if "Started Testing" was not emitted
if ( m_aborted ) {
2012-12-01 23:57:18 +00:00
m_config . stream () << " \n [Testing aborted. " ;
2012-08-23 20:08:50 +01:00
ReportCounts ( totals , "The first " );
}
else {
2012-12-01 23:57:18 +00:00
m_config . stream () << " \n [Testing completed. " ;
2012-08-23 20:08:50 +01:00
ReportCounts ( totals );
}
2012-12-01 23:57:18 +00:00
m_config . stream () << "] \n " << std :: endl ;
2012-08-23 20:08:50 +01:00
}
virtual void StartGroup ( const std :: string & groupName ) {
m_groupSpan = groupName ;
}
virtual void EndGroup ( const std :: string & groupName , const Totals & totals ) {
if ( m_groupSpan . emitted && ! groupName . empty () ) {
2012-12-01 23:57:18 +00:00
m_config . stream () << "[End of group: '" << groupName << "'. " ;
2012-08-23 20:08:50 +01:00
ReportCounts ( totals );
2012-12-01 23:57:18 +00:00
m_config . stream () << "] \n " << std :: endl ;
2012-08-23 20:08:50 +01:00
m_groupSpan = SpanInfo ();
}
}
virtual void StartTestCase ( const TestCaseInfo & testInfo ) {
2012-12-01 23:57:18 +00:00
m_testSpan = testInfo . name ;
2012-08-23 20:08:50 +01:00
}
virtual void StartSection ( const std :: string & sectionName , const std :: string & ) {
m_sectionSpans . push_back ( SpanInfo ( sectionName ) );
}
2012-08-31 08:10:36 +01:00
virtual void NoAssertionsInSection ( const std :: string & sectionName ) {
2012-09-07 17:52:35 +01:00
startSpansLazily ();
2012-08-31 08:10:36 +01:00
TextColour colour ( TextColour :: ResultError );
2012-12-01 23:57:18 +00:00
m_config . stream () << " \n No assertions in section, '" << sectionName << "' \n " << std :: endl ;
2012-08-31 08:10:36 +01:00
}
virtual void NoAssertionsInTestCase ( const std :: string & testName ) {
2012-09-07 17:52:35 +01:00
startSpansLazily ();
2012-08-31 08:10:36 +01:00
TextColour colour ( TextColour :: ResultError );
2012-12-01 23:57:18 +00:00
m_config . stream () << " \n No assertions in test case, '" << testName << "' \n " << std :: endl ;
2012-08-31 08:10:36 +01:00
}
2012-08-23 20:08:50 +01:00
virtual void EndSection ( const std :: string & sectionName , const Counts & assertions ) {
2012-08-31 08:10:36 +01:00
2012-08-23 20:08:50 +01:00
SpanInfo & sectionSpan = m_sectionSpans . back ();
if ( sectionSpan . emitted && ! sectionSpan . name . empty () ) {
2012-12-01 23:57:18 +00:00
m_config . stream () << "[End of section: '" << sectionName << "' " ;
2012-08-23 20:08:50 +01:00
if ( assertions . failed ) {
TextColour colour ( TextColour :: ResultError );
ReportCounts ( "assertion" , assertions );
}
else {
TextColour colour ( TextColour :: ResultSuccess );
2012-12-01 23:57:18 +00:00
m_config . stream () << ( assertions . passed > 1 ? "All " : "" )
2012-08-23 20:08:50 +01:00
<< pluralise ( assertions . passed , "assertion" ) << " passed" ;
}
2012-12-01 23:57:18 +00:00
m_config . stream () << "] \n " << std :: endl ;
2012-08-23 20:08:50 +01:00
}
m_sectionSpans . pop_back ();
}
2012-10-28 12:07:17 +00:00
virtual void Result ( const AssertionResult & assertionResult ) {
2012-12-01 23:57:18 +00:00
if ( ! m_config . includeSuccessfulResults () && assertionResult . getResultType () == ResultWas :: Ok )
2012-08-23 20:08:50 +01:00
return ;
2012-09-07 17:52:35 +01:00
startSpansLazily ();
2012-08-23 20:08:50 +01:00
2012-10-28 12:07:17 +00:00
if ( ! assertionResult . getSourceInfo (). empty () ) {
2012-08-23 20:08:50 +01:00
TextColour colour ( TextColour :: FileName );
2012-12-01 23:57:18 +00:00
m_config . stream () << assertionResult . getSourceInfo ();
2012-08-23 20:08:50 +01:00
}
2012-10-28 12:07:17 +00:00
if ( assertionResult . hasExpression () ) {
2012-08-23 20:08:50 +01:00
TextColour colour ( TextColour :: OriginalExpression );
2012-12-01 23:57:18 +00:00
m_config . stream () << assertionResult . getExpression ();
2012-11-13 09:44:52 +00:00
if ( assertionResult . succeeded () ) {
2012-08-23 20:08:50 +01:00
TextColour successColour ( TextColour :: Success );
2012-12-01 23:57:18 +00:00
m_config . stream () << " succeeded" ;
2012-08-23 20:08:50 +01:00
}
else {
TextColour errorColour ( TextColour :: Error );
2012-12-01 23:57:18 +00:00
m_config . stream () << " failed" ;
2012-11-13 09:44:52 +00:00
if ( assertionResult . isOk () ) {
TextColour okAnywayColour ( TextColour :: Success );
2012-12-01 23:57:18 +00:00
m_config . stream () << " - but was ok" ;
2012-11-13 09:44:52 +00:00
}
2012-08-23 20:08:50 +01:00
}
}
2012-10-28 12:07:17 +00:00
switch ( assertionResult . getResultType () ) {
2012-08-23 20:08:50 +01:00
case ResultWas :: ThrewException :
2012-10-31 18:04:22 +00:00
{
TextColour colour ( TextColour :: Error );
if ( assertionResult . hasExpression () )
2012-12-01 23:57:18 +00:00
m_config . stream () << " with unexpected" ;
2012-10-31 18:04:22 +00:00
else
2012-12-01 23:57:18 +00:00
m_config . stream () << "Unexpected" ;
m_config . stream () << " exception with message: '" << assertionResult . getMessage () << "'" ;
2012-10-31 18:04:22 +00:00
}
2012-08-23 20:08:50 +01:00
break ;
case ResultWas :: DidntThrowException :
2012-10-31 18:04:22 +00:00
{
TextColour colour ( TextColour :: Error );
if ( assertionResult . hasExpression () )
2012-12-01 23:57:18 +00:00
m_config . stream () << " because no exception was thrown where one was expected" ;
2012-10-31 18:04:22 +00:00
else
2012-12-01 23:57:18 +00:00
m_config . stream () << "No exception thrown where one was expected" ;
2012-10-31 18:04:22 +00:00
}
2012-08-23 20:08:50 +01:00
break ;
case ResultWas :: Info :
2012-10-31 18:04:22 +00:00
{
TextColour colour ( TextColour :: ReconstructedExpression );
streamVariableLengthText ( "info" , assertionResult . getMessage () );
}
2012-08-23 20:08:50 +01:00
break ;
case ResultWas :: Warning :
2012-10-31 18:04:22 +00:00
{
TextColour colour ( TextColour :: ReconstructedExpression );
streamVariableLengthText ( "warning" , assertionResult . getMessage () );
}
2012-08-23 20:08:50 +01:00
break ;
case ResultWas :: ExplicitFailure :
2012-10-31 18:04:22 +00:00
{
TextColour colour ( TextColour :: Error );
2012-12-01 23:57:18 +00:00
m_config . stream () << "failed with message: '" << assertionResult . getMessage () << "'" ;
2012-10-31 18:04:22 +00:00
}
2012-08-23 20:08:50 +01: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 12:07:17 +00:00
if ( ! assertionResult . hasExpression () ) {
2012-11-13 09:44:52 +00:00
if ( assertionResult . succeeded () ) {
2012-08-23 20:08:50 +01:00
TextColour colour ( TextColour :: Success );
2012-12-01 23:57:18 +00:00
m_config . stream () << " succeeded" ;
2012-08-23 20:08:50 +01:00
}
else {
TextColour colour ( TextColour :: Error );
2012-12-01 23:57:18 +00:00
m_config . stream () << " failed" ;
2012-11-13 09:44:52 +00:00
if ( assertionResult . isOk () ) {
TextColour okAnywayColour ( TextColour :: Success );
2012-12-01 23:57:18 +00:00
m_config . stream () << " - but was ok" ;
2012-11-13 09:44:52 +00:00
}
2012-08-23 20:08:50 +01:00
}
}
2012-11-21 18:06:13 +00:00
if ( assertionResult . hasMessage () ) {
2012-12-01 23:57:18 +00:00
m_config . stream () << " \n " ;
2012-11-21 18:06:13 +00:00
TextColour colour ( TextColour :: ReconstructedExpression );
streamVariableLengthText ( "with message" , assertionResult . getMessage () );
}
2012-08-23 20:08:50 +01:00
break ;
}
2012-10-28 12:07:17 +00:00
if ( assertionResult . hasExpandedExpression () ) {
2012-12-01 23:57:18 +00:00
m_config . stream () << " for: " ;
2012-10-29 20:49:22 +00:00
if ( assertionResult . getExpandedExpression (). size () > 40 ) {
2012-12-01 23:57:18 +00:00
m_config . stream () << " \n " ;
2012-10-29 20:49:22 +00:00
if ( assertionResult . getExpandedExpression (). size () < 70 )
2012-12-01 23:57:18 +00:00
m_config . stream () << " \t " ;
2012-10-29 20:49:22 +00:00
}
2012-08-23 20:08:50 +01:00
TextColour colour ( TextColour :: ReconstructedExpression );
2012-12-01 23:57:18 +00:00
m_config . stream () << assertionResult . getExpandedExpression ();
2012-08-23 20:08:50 +01:00
}
2012-12-01 23:57:18 +00:00
m_config . stream () << std :: endl ;
2012-08-23 20:08:50 +01:00
}
virtual void EndTestCase ( const TestCaseInfo & testInfo ,
const Totals & totals ,
const std :: string & stdOut ,
const std :: string & stdErr ) {
if ( ! stdOut . empty () ) {
2012-09-07 17:52:35 +01:00
startSpansLazily ();
2012-08-23 20:08:50 +01:00
streamVariableLengthText ( "stdout" , stdOut );
}
if ( ! stdErr . empty () ) {
2012-09-07 17:52:35 +01:00
startSpansLazily ();
2012-08-23 20:08:50 +01:00
streamVariableLengthText ( "stderr" , stdErr );
}
if ( m_testSpan . emitted ) {
2012-12-01 23:57:18 +00:00
m_config . stream () << "[Finished: '" << testInfo . name << "' " ;
2012-08-23 20:08:50 +01:00
ReportCounts ( totals );
2012-12-01 23:57:18 +00:00
m_config . stream () << "]" << std :: endl ;
2012-08-23 20:08:50 +01:00
}
}
private : // helpers
2012-09-07 17:52:35 +01:00
void startSpansLazily () {
2012-08-23 20:08:50 +01:00
if ( ! m_testingSpan . emitted ) {
2012-12-01 23:57:18 +00:00
if ( m_config . name (). empty () )
m_config . stream () << "[Started testing]" << std :: endl ;
2012-08-23 20:08:50 +01:00
else
2012-12-01 23:57:18 +00:00
m_config . stream () << "[Started testing: " << m_config . name () << "]" << std :: endl ;
2012-08-23 20:08:50 +01:00
m_testingSpan . emitted = true ;
}
if ( ! m_groupSpan . emitted && ! m_groupSpan . name . empty () ) {
2012-12-01 23:57:18 +00:00
m_config . stream () << "[Started group: '" << m_groupSpan . name << "']" << std :: endl ;
2012-08-23 20:08:50 +01:00
m_groupSpan . emitted = true ;
}
if ( ! m_testSpan . emitted ) {
2012-12-01 23:57:18 +00:00
m_config . stream () << std :: endl << "[Running: " << m_testSpan . name << "]" << std :: endl ;
2012-08-23 20:08:50 +01:00
m_testSpan . emitted = true ;
}
if ( ! m_sectionSpans . empty () ) {
SpanInfo & sectionSpan = m_sectionSpans . back ();
if ( ! sectionSpan . emitted && ! sectionSpan . name . empty () ) {
if ( m_firstSectionInTestCase ) {
2012-12-01 23:57:18 +00:00
m_config . stream () << " \n " ;
2012-08-23 20:08:50 +01: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-01 23:57:18 +00:00
m_config . stream () << "[Started section: '" << prevSpan . name << "']" << std :: endl ;
2012-08-23 20:08:50 +01:00
prevSpan . emitted = true ;
}
}
}
}
}
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-01 23:57:18 +00:00
m_config . stream () << "[" << prefix << ": " << trimmed << "]" ;
2012-08-23 20:08:50 +01:00
}
else {
2012-12-01 23:57:18 +00:00
m_config . stream () << " \n [" << prefix << "] >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> \n " << trimmed
2012-08-23 20:08:50 +01:00
<< " \n [end of " << prefix << "] <<<<<<<<<<<<<<<<<<<<<<<< \n " ;
}
}
private :
ReporterConfig m_config ;
bool m_firstSectionInTestCase ;
SpanInfo m_testingSpan ;
SpanInfo m_groupSpan ;
SpanInfo m_testSpan ;
std :: vector < SpanInfo > m_sectionSpans ;
bool m_aborted ;
};
} // end namespace Catch
// #included from: ../reporters/catch_reporter_xml.hpp
#define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED
// #included from: ../internal/catch_xmlwriter.hpp
#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED
#include <sstream>
2012-09-29 20:54:03 +01:00
#include <iostream>
2012-08-23 20:08:50 +01:00
#include <string>
#include <vector>
namespace Catch {
class XmlWriter {
public :
class ScopedElement {
public :
ScopedElement ( XmlWriter * writer )
: m_writer ( writer )
{}
ScopedElement ( const ScopedElement & other )
: m_writer ( other . m_writer ){
other . m_writer = NULL ;
}
~ ScopedElement () {
if ( m_writer )
m_writer -> endElement ();
}
2012-12-01 23:57:18 +00:00
ScopedElement & writeText ( const std :: string & text , bool indent = true ) {
m_writer -> writeText ( text , indent );
2012-08-23 20:08:50 +01:00
return * this ;
}
template < typename T >
ScopedElement & writeAttribute ( const std :: string & name , const T & attribute ) {
m_writer -> writeAttribute ( name , attribute );
return * this ;
}
private :
mutable XmlWriter * m_writer ;
};
XmlWriter ()
: m_tagIsOpen ( false ),
m_needsNewline ( false ),
m_os ( & std :: cout )
{}
XmlWriter ( std :: ostream & os )
: m_tagIsOpen ( false ),
m_needsNewline ( false ),
m_os ( & os )
{}
~ XmlWriter () {
while ( ! m_tags . empty () )
endElement ();
}
XmlWriter & operator = ( const XmlWriter & other ) {
XmlWriter temp ( other );
swap ( temp );
return * this ;
}
void swap ( XmlWriter & other ) {
std :: swap ( m_tagIsOpen , other . m_tagIsOpen );
std :: swap ( m_needsNewline , other . m_needsNewline );
std :: swap ( m_tags , other . m_tags );
std :: swap ( m_indent , other . m_indent );
std :: swap ( m_os , other . m_os );
}
XmlWriter & startElement ( const std :: string & name ) {
ensureTagClosed ();
newlineIfNecessary ();
stream () << m_indent << "<" << name ;
m_tags . push_back ( name );
m_indent += " " ;
m_tagIsOpen = true ;
return * this ;
}
ScopedElement scopedElement ( const std :: string & name ) {
ScopedElement scoped ( this );
startElement ( name );
return scoped ;
}
XmlWriter & endElement () {
newlineIfNecessary ();
m_indent = m_indent . substr ( 0 , m_indent . size () - 2 );
if ( m_tagIsOpen ) {
stream () << "/> \n " ;
m_tagIsOpen = false ;
}
else {
stream () << m_indent << "</" << m_tags . back () << "> \n " ;
}
m_tags . pop_back ();
return * this ;
}
XmlWriter & writeAttribute ( const std :: string & name , const std :: string & attribute ) {
if ( ! name . empty () && ! attribute . empty () ) {
stream () << " " << name << "= \" " ;
writeEncodedText ( attribute );
stream () << " \" " ;
}
return * this ;
}
XmlWriter & writeAttribute ( const std :: string & name , bool attribute ) {
stream () << " " << name << "= \" " << ( attribute ? "true" : "false" ) << " \" " ;
return * this ;
}
template < typename T >
XmlWriter & writeAttribute ( const std :: string & name , const T & attribute ) {
if ( ! name . empty () )
stream () << " " << name << "= \" " << attribute << " \" " ;
return * this ;
}
2012-12-01 23:57:18 +00:00
XmlWriter & writeText ( const std :: string & text , bool indent = true ) {
2012-08-23 20:08:50 +01:00
if ( ! text . empty () ){
bool tagWasOpen = m_tagIsOpen ;
ensureTagClosed ();
2012-12-01 23:57:18 +00:00
if ( tagWasOpen && indent )
2012-08-23 20:08:50 +01:00
stream () << m_indent ;
writeEncodedText ( text );
m_needsNewline = true ;
}
return * this ;
}
XmlWriter & writeComment ( const std :: string & text ) {
ensureTagClosed ();
stream () << m_indent << "<!--" << text << "-->" ;
m_needsNewline = true ;
return * this ;
}
XmlWriter & writeBlankLine () {
ensureTagClosed ();
stream () << " \n " ;
return * this ;
}
private :
std :: ostream & stream () {
return * m_os ;
}
void ensureTagClosed () {
if ( m_tagIsOpen ) {
stream () << "> \n " ;
m_tagIsOpen = false ;
}
}
void newlineIfNecessary () {
if ( m_needsNewline ) {
stream () << " \n " ;
m_needsNewline = false ;
}
}
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 );
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 ;
}
bool m_tagIsOpen ;
bool m_needsNewline ;
std :: vector < std :: string > m_tags ;
std :: string m_indent ;
std :: ostream * m_os ;
};
}
namespace Catch {
class XmlReporter : public SharedImpl < IReporter > {
public :
XmlReporter ( const ReporterConfig & config ) : m_config ( config ) {}
static std :: string getDescription () {
return "Reports test results as an XML document" ;
}
virtual ~ XmlReporter ();
private : // IReporter
virtual bool shouldRedirectStdout () const {
return true ;
}
virtual void StartTesting () {
2012-12-01 23:57:18 +00:00
m_xml = XmlWriter ( m_config . stream () );
2012-08-23 20:08:50 +01:00
m_xml . startElement ( "Catch" );
2012-12-01 23:57:18 +00:00
if ( ! m_config . name (). empty () )
m_xml . writeAttribute ( "name" , m_config . name () );
2012-08-23 20:08:50 +01:00
}
virtual void EndTesting ( const Totals & totals ) {
m_xml . scopedElement ( "OverallResults" )
. writeAttribute ( "successes" , totals . assertions . passed )
. writeAttribute ( "failures" , totals . assertions . failed );
m_xml . endElement ();
}
virtual void StartGroup ( const std :: string & groupName ) {
m_xml . startElement ( "Group" )
. writeAttribute ( "name" , groupName );
}
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 ();
}
virtual void StartSection ( const std :: string & sectionName , const std :: string & description ) {
m_xml . startElement ( "Section" )
. writeAttribute ( "name" , sectionName )
. writeAttribute ( "description" , description );
}
2012-08-31 08:10:36 +01:00
virtual void NoAssertionsInSection ( const std :: string & ) {}
virtual void NoAssertionsInTestCase ( const std :: string & ) {}
2012-08-23 20:08:50 +01: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 ();
}
virtual void StartTestCase ( const Catch :: TestCaseInfo & testInfo ) {
2012-12-01 23:57:18 +00:00
m_xml . startElement ( "TestCase" ). writeAttribute ( "name" , testInfo . name );
2012-08-23 20:08:50 +01:00
m_currentTestSuccess = true ;
}
2012-10-28 12:07:17 +00:00
virtual void Result ( const Catch :: AssertionResult & assertionResult ) {
2012-12-01 23:57:18 +00:00
if ( ! m_config . includeSuccessfulResults () && assertionResult . getResultType () == ResultWas :: Ok )
2012-08-23 20:08:50 +01:00
return ;
2012-10-28 12:07:17 +00:00
if ( assertionResult . hasExpression () ) {
2012-08-23 20:08:50 +01:00
m_xml . startElement ( "Expression" )
2012-11-13 09:44:52 +00:00
. writeAttribute ( "success" , assertionResult . succeeded () )
2012-10-28 12:07:17 +00:00
. writeAttribute ( "filename" , assertionResult . getSourceInfo (). file )
. writeAttribute ( "line" , assertionResult . getSourceInfo (). line );
2012-08-23 20:08:50 +01:00
m_xml . scopedElement ( "Original" )
2012-10-28 12:07:17 +00:00
. writeText ( assertionResult . getExpression () );
2012-08-23 20:08:50 +01:00
m_xml . scopedElement ( "Expanded" )
2012-10-28 12:07:17 +00:00
. writeText ( assertionResult . getExpandedExpression () );
2012-11-13 09:44:52 +00:00
m_currentTestSuccess &= assertionResult . succeeded ();
2012-08-23 20:08:50 +01:00
}
2012-10-28 12:07:17 +00:00
switch ( assertionResult . getResultType () ) {
2012-08-23 20:08:50 +01:00
case ResultWas :: ThrewException :
m_xml . scopedElement ( "Exception" )
2012-10-28 12:07:17 +00:00
. writeAttribute ( "filename" , assertionResult . getSourceInfo (). file )
. writeAttribute ( "line" , assertionResult . getSourceInfo (). line )
. writeText ( assertionResult . getMessage () );
2012-08-23 20:08:50 +01:00
m_currentTestSuccess = false ;
break ;
case ResultWas :: Info :
m_xml . scopedElement ( "Info" )
2012-10-28 12:07:17 +00:00
. writeText ( assertionResult . getMessage () );
2012-08-23 20:08:50 +01:00
break ;
case ResultWas :: Warning :
m_xml . scopedElement ( "Warning" )
2012-10-28 12:07:17 +00:00
. writeText ( assertionResult . getMessage () );
2012-08-23 20:08:50 +01:00
break ;
case ResultWas :: ExplicitFailure :
m_xml . scopedElement ( "Failure" )
2012-10-28 12:07:17 +00:00
. writeText ( assertionResult . getMessage () );
2012-08-23 20:08:50 +01: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 12:07:17 +00:00
if ( assertionResult . hasExpression () )
2012-08-23 20:08:50 +01:00
m_xml . endElement ();
}
virtual void Aborted () {
// !TBD
}
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 ();
}
private :
ReporterConfig m_config ;
bool m_currentTestSuccess ;
XmlWriter m_xml ;
};
} // end namespace Catch
// #included from: ../reporters/catch_reporter_junit.hpp
#define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED
2012-12-02 00:05:51 +00:00
#include <assert.h>
2012-08-23 20:08:50 +01:00
namespace Catch {
class JunitReporter : public SharedImpl < IReporter > {
struct TestStats {
std :: string m_element ;
std :: string m_resultType ;
std :: string m_message ;
std :: string m_content ;
};
struct TestCaseStats {
2012-11-04 21:39:38 +00:00
TestCaseStats ( const std :: string & className , const std :: string & name )
: m_className ( className ),
m_name ( name )
{}
2012-08-23 20:08:50 +01:00
double m_timeInSeconds ;
std :: string m_status ;
std :: string m_className ;
std :: string m_name ;
2012-11-21 18:06:13 +00:00
std :: string m_stdOut ;
std :: string m_stdErr ;
2012-08-23 20:08:50 +01:00
std :: vector < TestStats > m_testStats ;
2012-12-01 23:57:18 +00:00
std :: vector < TestCaseStats > m_sections ;
2012-08-23 20:08:50 +01:00
};
struct Stats {
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 )
{}
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 ;
std :: vector < TestCaseStats > m_testCaseStats ;
};
public :
JunitReporter ( const ReporterConfig & config )
: m_config ( config ),
m_testSuiteStats ( "AllTests" ),
m_currentStats ( & m_testSuiteStats )
{}
virtual ~ JunitReporter ();
static std :: string getDescription () {
return "Reports test results in an XML format that looks like Ant's junitreport target" ;
}
private : // IReporter
virtual bool shouldRedirectStdout () const {
return true ;
}
virtual void StartTesting (){}
virtual void StartGroup ( const std :: string & groupName ) {
2012-11-16 08:47:03 +00:00
if ( groupName . empty () )
2012-12-01 23:57:18 +00:00
m_statsForSuites . push_back ( Stats ( m_config . name () ) );
2012-11-16 08:47:03 +00:00
else
m_statsForSuites . push_back ( Stats ( groupName ) );
2012-08-23 20:08:50 +01:00
m_currentStats = & m_statsForSuites . back ();
}
virtual void EndGroup ( const std :: string & , const Totals & totals ) {
m_currentStats -> m_testsCount = totals . assertions . total ();
m_currentStats = & m_testSuiteStats ;
}
virtual void StartSection ( const std :: string & , const std :: string & ){}
2012-08-31 08:10:36 +01:00
virtual void NoAssertionsInSection ( const std :: string & ) {}
virtual void NoAssertionsInTestCase ( const std :: string & ) {}
virtual void EndSection ( const std :: string & , const Counts & ) {}
2012-08-23 20:08:50 +01:00
virtual void StartTestCase ( const Catch :: TestCaseInfo & testInfo ) {
2012-12-01 23:57:18 +00:00
m_currentStats -> m_testCaseStats . push_back ( TestCaseStats ( testInfo . className , testInfo . name ) );
m_currentTestCaseStats . push_back ( & m_currentStats -> m_testCaseStats . back () );
2012-08-23 20:08:50 +01:00
}
2012-10-28 12:07:17 +00:00
virtual void Result ( const Catch :: AssertionResult & assertionResult ) {
2012-12-01 23:57:18 +00:00
if ( assertionResult . getResultType () != ResultWas :: Ok || m_config . includeSuccessfulResults () ) {
2012-08-23 20:08:50 +01:00
TestCaseStats & testCaseStats = m_currentStats -> m_testCaseStats . back ();
TestStats stats ;
std :: ostringstream oss ;
2012-10-28 12:07:17 +00:00
if ( ! assertionResult . getMessage (). empty () )
oss << assertionResult . getMessage () << " at " ;
oss << assertionResult . getSourceInfo ();
2012-08-23 20:08:50 +01:00
stats . m_content = oss . str ();
2012-10-28 12:07:17 +00:00
stats . m_message = assertionResult . getExpandedExpression ();
stats . m_resultType = assertionResult . getTestMacroName ();
2012-08-23 20:08:50 +01:00
2012-10-28 12:07:17 +00:00
switch ( assertionResult . getResultType () ) {
2012-08-23 20:08:50 +01: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 );
}
}
virtual void EndTestCase ( const Catch :: TestCaseInfo & , const Totals & , const std :: string & stdOut , const std :: string & stdErr ) {
2012-12-01 23:57:18 +00:00
m_currentTestCaseStats . pop_back ();
assert ( m_currentTestCaseStats . empty () );
2012-11-21 18:06:13 +00:00
TestCaseStats & testCaseStats = m_currentStats -> m_testCaseStats . back ();
testCaseStats . m_stdOut = stdOut ;
testCaseStats . m_stdErr = stdErr ;
2012-08-23 20:08:50 +01:00
if ( ! stdOut . empty () )
m_stdOut << stdOut << " \n " ;
if ( ! stdErr . empty () )
m_stdErr << stdErr << " \n " ;
}
virtual void Aborted () {
// !TBD
}
virtual void EndTesting ( const Totals & ) {
2012-12-01 23:57:18 +00:00
XmlWriter xml ( m_config . stream () );
2012-08-23 20:08:50 +01:00
2012-12-01 23:57:18 +00:00
if ( m_statsForSuites . size () > 0 )
xml . startElement ( "testsuites" );
2012-08-23 20:08:50 +01:00
2012-12-01 23:57:18 +00:00
std :: vector < Stats >:: const_iterator it = m_statsForSuites . begin ();
std :: vector < Stats >:: const_iterator itEnd = m_statsForSuites . end ();
2012-08-23 20:08:50 +01:00
2012-12-01 23:57:18 +00: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:08:50 +01:00
2012-12-01 23:57:18 +00:00
OutputTestCases ( xml , * it );
2012-08-23 20:08:50 +01:00
}
2012-12-01 23:57:18 +00:00
xml . scopedElement ( "system-out" ). writeText ( trim ( m_stdOut . str () ), false );
xml . scopedElement ( "system-err" ). writeText ( trim ( m_stdErr . str () ), false );
2012-08-23 20:08:50 +01: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 ) {
XmlWriter :: ScopedElement e = xml . scopedElement ( "testcase" );
xml . writeAttribute ( "classname" , it -> m_className );
xml . writeAttribute ( "name" , it -> m_name );
xml . writeAttribute ( "time" , "tbd" );
OutputTestResult ( xml , * it );
2012-11-21 18:06:13 +00:00
std :: string stdOut = trim ( it -> m_stdOut );
if ( ! stdOut . empty () )
2012-12-01 23:57:18 +00:00
xml . scopedElement ( "system-out" ). writeText ( stdOut , false );
2012-11-21 18:06:13 +00:00
std :: string stdErr = trim ( it -> m_stdErr );
if ( ! stdErr . empty () )
2012-12-01 23:57:18 +00:00
xml . scopedElement ( "system-err" ). writeText ( stdErr , false );
2012-08-23 20:08:50 +01: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 );
xml . writeAttribute ( "message" , it -> m_message );
xml . writeAttribute ( "type" , it -> m_resultType );
if ( ! it -> m_content . empty () )
xml . writeText ( it -> m_content );
}
}
}
private :
ReporterConfig m_config ;
bool m_currentTestSuccess ;
Stats m_testSuiteStats ;
Stats * m_currentStats ;
std :: vector < Stats > m_statsForSuites ;
2012-12-01 23:57:18 +00:00
std :: vector < const TestCaseStats *> m_currentTestCaseStats ;
2012-08-23 20:08:50 +01:00
std :: ostringstream m_stdOut ;
std :: ostringstream m_stdErr ;
};
} // end namespace Catch
2012-12-06 08:44:51 +00:00
// #included from: ../reporters/catch_reporter_console.hpp
#define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED
namespace Catch {
struct ConsoleReporter : AccumulatingReporter {
ConsoleReporter ( ReporterConfig const & _config )
2012-12-14 07:50:08 +00:00
: AccumulatingReporter ( _config ),
m_atLeastOneTestCasePrinted ( false )
2012-12-06 08:44:51 +00: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 ;
}
void lazyPrintRunInfo () {
2012-12-14 07:50:08 +00:00
printHeader ( "Started testing" , testRunInfo -> name );
2012-12-06 08:44:51 +00:00
testRunInfo . reset ();
}
void lazyPrintGroupInfo () {
if ( ! unusedGroupInfo -> name . empty () )
2012-12-14 07:50:08 +00:00
printHeader ( "Group" , unusedGroupInfo -> name );
2012-12-06 08:44:51 +00:00
unusedGroupInfo . reset ();
}
void lazyPrintTestCaseInfo () {
2012-12-14 07:50:08 +00:00
printHeader ( "Test case" , unusedTestCaseInfo -> name );
2012-12-06 08:44:51 +00:00
unusedTestCaseInfo . reset ();
}
void lazyPrintSectionInfo () {
2012-12-10 08:54:57 +00:00
std :: vector < ThreadedSectionInfo *> sections ;
for ( ThreadedSectionInfo * section = unusedSectionInfo . get ();
section && ! section -> printed ;
section = section -> parent . get () )
sections . push_back ( section );
2012-12-06 08:44:51 +00:00
2012-12-10 08:54:57 +00:00
typedef std :: vector < ThreadedSectionInfo *>:: const_reverse_iterator It ;
for ( It it = sections . rbegin (), itEnd = sections . rend (); it != itEnd ; ++ it ) {
2012-12-14 07:50:08 +00:00
printHeader ( "Section" , ( * it ) -> name );
2012-12-10 08:54:57 +00:00
( * it ) -> printed = true ;
}
2012-12-06 08:44:51 +00:00
unusedSectionInfo . reset ();
}
2012-12-14 07:50:08 +00:00
static std :: string const & getDashes () {
static const std :: string dashes = "----------------------------------------------------------------" ;
return dashes ;
}
static std :: string const & getDoubleDashes () {
static const std :: string doubleDashes = "================================================================" ;
return doubleDashes ;
}
static std :: string const & getSpaces () {
static const std :: string spaces = " " ;
return spaces ;
}
static std :: string getSpaces ( int spaces ) {
return getSpaces (). substr ( 0 , spaces > 0 ? static_cast < std :: size_t > ( spaces ) : 0 );
}
void printHeader ( std :: string const & _type , std :: string const & _name ) {
std :: size_t labelLen = _type . size () + _name . size () + 8 ;
std :: size_t dashLen = getDashes (). size ();
stream << "-- " << _type << ": '" << _name << "' "
<< getDashes (). substr ( 0 , labelLen < dashLen ? dashLen - labelLen : 0 )
<< std :: endl ;
}
2012-12-06 08:44:51 +00:00
void lazyPrint () {
if ( testRunInfo )
lazyPrintRunInfo ();
if ( unusedGroupInfo )
lazyPrintGroupInfo ();
if ( unusedTestCaseInfo )
lazyPrintTestCaseInfo ();
2012-12-10 08:54:57 +00:00
if ( currentSectionInfo && ! currentSectionInfo -> printed )
2012-12-06 08:44:51 +00:00
lazyPrintSectionInfo ();
}
2012-12-10 08:54:57 +00:00
virtual void assertionStarting ( AssertionInfo const & ) {
2012-12-06 08:44:51 +00:00
}
virtual void assertionEnded ( Ptr < AssertionStats const > const & _assertionStats ) {
2012-12-10 08:54:57 +00:00
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 ();
2012-12-14 07:50:08 +00:00
int inset = printLineInfo ( result . getSourceInfo () );
2012-12-10 08:54:57 +00:00
if ( result . hasExpression () ) {
TextColour colour ( TextColour :: OriginalExpression );
2012-12-14 07:50:08 +00:00
stream << result . getExpression () << " \n " ;
2012-12-10 08:54:57 +00:00
if ( result . succeeded () ) {
TextColour successColour ( TextColour :: Success );
2012-12-14 07:50:08 +00:00
stream << "succeeded" ;
2012-12-10 08:54:57 +00:00
}
else {
TextColour errorColour ( TextColour :: Error );
2012-12-14 07:50:08 +00:00
stream << "failed" ;
2012-12-10 08:54:57 +00:00
if ( result . isOk () ) {
TextColour okAnywayColour ( TextColour :: Success );
stream << " - but was ok" ;
}
}
}
switch ( result . getResultType () ) {
case ResultWas :: ThrewException :
{
TextColour colour ( TextColour :: Error );
if ( result . hasExpression () )
stream << " with unexpected" ;
else
stream << "Unexpected" ;
stream << " exception with message: '" << result . getMessage () << "'" ;
}
break ;
case ResultWas :: DidntThrowException :
{
TextColour colour ( TextColour :: Error );
if ( result . hasExpression () )
stream << " because no exception was thrown where one was expected" ;
else
stream << "No exception thrown where one was expected" ;
}
break ;
case ResultWas :: Info :
{
TextColour colour ( TextColour :: ReconstructedExpression );
streamVariableLengthText ( "info" , result . getMessage () );
}
break ;
case ResultWas :: Warning :
{
TextColour colour ( TextColour :: ReconstructedExpression );
streamVariableLengthText ( "warning" , result . getMessage () );
}
break ;
case ResultWas :: ExplicitFailure :
{
TextColour colour ( TextColour :: Error );
stream << "failed with message: '" << result . getMessage () << "'" ;
}
break ;
case ResultWas :: Unknown : // These cases are here to prevent compiler warnings
case ResultWas :: Ok :
case ResultWas :: FailureBit :
case ResultWas :: ExpressionFailed :
case ResultWas :: Exception :
if ( ! result . hasExpression () ) {
if ( result . succeeded () ) {
TextColour colour ( TextColour :: Success );
stream << " succeeded" ;
}
else {
TextColour colour ( TextColour :: Error );
stream << " failed" ;
if ( result . isOk () ) {
TextColour okAnywayColour ( TextColour :: Success );
stream << " - but was ok" ;
}
}
}
if ( result . hasMessage () ) {
stream << " \n " ;
TextColour colour ( TextColour :: ReconstructedExpression );
streamVariableLengthText ( "with message" , result . getMessage () );
}
break ;
}
if ( result . hasExpandedExpression () ) {
2012-12-14 07:50:08 +00:00
stream << " \n for: " ;
2012-12-10 08:54:57 +00:00
TextColour colour ( TextColour :: ReconstructedExpression );
2012-12-14 07:50:08 +00:00
stream << getSpaces ( inset - 5 ) << result . getExpandedExpression ();
2012-12-10 08:54:57 +00:00
}
2012-12-14 07:50:08 +00:00
stream << " \n " << std :: endl ;
2012-12-10 08:54:57 +00:00
}
void streamVariableLengthText ( std :: string const & prefix , std :: string const & text ) {
std :: string trimmed = trim ( text );
if ( trimmed . find_first_of ( " \r\n " ) == std :: string :: npos ) {
stream << "[" << prefix << ": " << trimmed << "]" ;
}
else {
stream << " \n [" << prefix << "] >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> \n " << trimmed
<< " \n [end of " << prefix << "] <<<<<<<<<<<<<<<<<<<<<<<< \n " ;
}
2012-12-06 08:44:51 +00:00
}
2012-12-11 09:03:14 +00:00
void printAssertionCounts ( std :: string const & label , Counts const & counts ) {
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 08:44:51 +00:00
}
2012-12-11 09:03:14 +00:00
void printTotals ( const Totals & totals ) {
2012-12-06 08:44:51 +00:00
if ( totals . assertions . total () == 0 ) {
stream << "No tests ran" ;
}
else if ( totals . assertions . failed ) {
TextColour colour ( TextColour :: ResultError );
2012-12-11 09:03:14 +00:00
printAssertionCounts ( "test case" , totals . testCases );
2012-12-06 08:44:51 +00:00
if ( totals . testCases . failed > 0 ) {
stream << " (" ;
2012-12-11 09:03:14 +00:00
printAssertionCounts ( "assertion" , totals . assertions );
2012-12-06 08:44:51 +00:00
stream << ")" ;
}
}
else {
TextColour colour ( TextColour :: ResultSuccess );
2012-12-11 09:03:14 +00:00
stream << "All tests passed ("
2012-12-06 08:44:51 +00:00
<< pluralise ( totals . assertions . passed , "assertion" ) << " in "
<< pluralise ( totals . testCases . passed , "test case" ) << ")" ;
}
}
virtual void sectionEnded ( Ptr < SectionStats const > const & _sectionStats ) {
2012-12-11 09:03:14 +00:00
resetLastPrintedLine ();
2012-12-10 08:54:57 +00:00
if ( _sectionStats -> missingAssertions ) {
lazyPrint ();
TextColour colour ( TextColour :: ResultError );
stream << " \n No assertions in section, '" << _sectionStats -> sectionInfo . name << "' \n " << std :: endl ;
}
if ( currentSectionInfo && currentSectionInfo -> printed ) {
2012-12-14 07:50:08 +00:00
printSummarDivider ();
stream << "Summary for section '" << _sectionStats -> sectionInfo . name << "': \n " ;
2012-12-10 08:54:57 +00:00
Counts const & assertions = _sectionStats -> assertions ;
if ( assertions . failed ) {
TextColour colour ( TextColour :: ResultError );
printAssertionCounts ( "assertion" , assertions );
}
else {
TextColour colour ( TextColour :: ResultSuccess );
stream << ( assertions . passed > 1 ? "All " : "" )
<< pluralise ( assertions . passed , "assertion" ) << " passed" ;
}
2012-12-14 07:50:08 +00:00
stream << " \n " << std :: endl ;
2012-12-06 08:44:51 +00:00
}
AccumulatingReporter :: sectionEnded ( _sectionStats );
}
virtual void testCaseEnded ( Ptr < TestCaseStats const > const & _testCaseStats ) {
2012-12-11 09:03:14 +00:00
resetLastPrintedLine ();
2012-12-10 08:54:57 +00:00
if ( _testCaseStats -> missingAssertions ) {
lazyPrint ();
TextColour colour ( TextColour :: ResultError );
stream << " \n No assertions in test case, '" << _testCaseStats -> testInfo . name << "' \n " << std :: endl ;
}
2012-12-06 08:44:51 +00:00
if ( ! unusedTestCaseInfo ) {
2012-12-14 07:50:08 +00:00
m_atLeastOneTestCasePrinted = true ;
printSummarDivider ();
stream << "Summary for test case '" << _testCaseStats -> testInfo . name << "': \n " ;
2012-12-06 08:44:51 +00:00
printTotals ( _testCaseStats -> totals );
2012-12-14 07:50:08 +00:00
stream << " \n " << std :: endl ;
2012-12-06 08:44:51 +00:00
}
AccumulatingReporter :: testCaseEnded ( _testCaseStats );
}
virtual void testGroupEnded ( Ptr < TestGroupStats const > const & _testGroupStats ) {
2012-12-10 08:54:57 +00:00
if ( ! unusedGroupInfo ) {
2012-12-14 07:50:08 +00:00
printSummarDivider ();
stream << "Summary for group '" << _testGroupStats -> groupInfo . name << "': \n " ;
2012-12-10 08:54:57 +00:00
printTotals ( _testGroupStats -> totals );
2012-12-14 07:50:08 +00:00
stream << " \n " << std :: endl ;
2012-12-10 08:54:57 +00:00
}
2012-12-06 08:44:51 +00:00
AccumulatingReporter :: testGroupEnded ( _testGroupStats );
}
virtual void testRunEnded ( Ptr < TestRunStats const > const & _testRunStats ) {
2012-12-14 07:50:08 +00:00
if ( m_atLeastOneTestCasePrinted )
printTotalsDivider ();
stream << "Summary for all tests in '" << _testRunStats -> runInfo . name << "': \n " ;
printTotals ( _testRunStats -> totals );
stream << " \n " << std :: endl ;
2012-12-06 08:44:51 +00:00
AccumulatingReporter :: testRunEnded ( _testRunStats );
}
2012-12-14 07:50:08 +00:00
private :
void printTotalsDivider () {
stream << "================================================================ \n " ;
}
void printSummarDivider () {
stream << "---------------------------------------------------------------- \n " ;
}
static int countDigits ( std :: size_t number ) {
int digits = 1 ;
for ( ; number != 0 ; digits ++ , number /= 10 );
return digits ;
}
// Returns number of characters printed
int printLineInfo ( SourceLineInfo const & lineInfo ) {
if ( lineInfo . empty () )
return 0 ;
if ( m_lastPrintedLine . empty () ||
m_lastPrintedLine . file != lineInfo . file ||
abs ( static_cast < int > ( m_lastPrintedLine . line ) - static_cast < int > ( lineInfo . line ) ) > 20 ) {
TextColour colour ( TextColour :: FileName );
stream << lineInfo << " \n " ;
2012-12-11 09:03:14 +00:00
}
2012-12-14 07:50:08 +00:00
TextColour colour ( TextColour :: FileName );
stream << "[" << lineInfo . line << "] " ;
m_lastPrintedLine = lineInfo ;
return 3 + countDigits ( lineInfo . line );
2012-12-11 09:03:14 +00:00
}
void resetLastPrintedLine () {
m_lastPrintedLine = SourceLineInfo ();
}
2012-12-14 07:50:08 +00:00
bool m_atLeastOneTestCasePrinted ;
2012-12-11 09:03:14 +00:00
SourceLineInfo m_lastPrintedLine ;
2012-12-06 08:44:51 +00:00
};
INTERNAL_CATCH_REGISTER_REPORTER ( "console" , ConsoleReporter )
} // end namespace Catch
2012-08-13 07:46:10 +01: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-01 23:57:18 +00:00
IStreamingReporter ::~ IStreamingReporter () {}
LegacyReporterAdapter ::~ LegacyReporterAdapter () {}
AssertionStats ::~ AssertionStats () {}
SectionStats ::~ SectionStats () {}
TestCaseStats ::~ TestCaseStats () {}
TestGroupStats ::~ TestGroupStats () {}
TestRunStats ::~ TestRunStats () {}
2012-12-06 08:44:51 +00:00
ThreadedSectionInfo ::~ ThreadedSectionInfo () {}
2012-12-01 23:57:18 +00:00
2012-08-13 07:46:10 +01:00
BasicReporter ::~ BasicReporter () {}
2012-12-06 08:44:51 +00:00
AccumulatingReporter ::~ AccumulatingReporter () {}
ConsoleReporter ::~ ConsoleReporter () {}
2012-08-13 07:46:10 +01:00
IRunner ::~ IRunner () {}
IMutableContext ::~ IMutableContext () {}
IConfig ::~ IConfig () {}
XmlReporter ::~ XmlReporter () {}
JunitReporter ::~ JunitReporter () {}
TestRegistry ::~ TestRegistry () {}
FreeFunctionTestCase ::~ FreeFunctionTestCase () {}
IGeneratorInfo ::~ IGeneratorInfo () {}
IGeneratorsForTest ::~ IGeneratorsForTest () {}
2012-09-24 08:30:13 +01:00
TagParser ::~ TagParser () {}
TagExtracter ::~ TagExtracter () {}
TagExpressionParser ::~ TagExpressionParser () {}
2012-08-13 07:46:10 +01:00
2012-10-12 07:58:17 +01:00
Matchers :: Impl :: StdString :: Equals ::~ Equals () {}
Matchers :: Impl :: StdString :: Contains ::~ Contains () {}
Matchers :: Impl :: StdString :: StartsWith ::~ StartsWith () {}
Matchers :: Impl :: StdString :: EndsWith ::~ EndsWith () {}
2012-08-13 07:46:10 +01:00
void Config :: dummy () {}
2012-12-01 23:57:18 +00: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 20:08:50 +01:00
2012-08-13 07:46:10 +01:00
}
2012-08-16 18:48:50 +01:00
#ifdef __clang__
2012-08-13 07:46:10 +01:00
#pragma clang diagnostic pop
2011-05-24 08:23:02 +01:00
#endif
2012-09-17 01:42:29 -04:00
2012-08-16 18:48:50 +01:00
#endif
2011-05-24 08:23:02 +01:00
#ifdef CATCH_CONFIG_MAIN
// #included from: internal/catch_default_main.hpp
2012-08-09 07:47:30 +01:00
#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED
2011-05-24 08:23:02 +01:00
2012-05-11 08:17:16 +01:00
#ifndef __OBJC__
2011-05-24 08:23:02 +01:00
2012-05-11 08:17:16 +01:00
// Standard C/C++ main entry point
int main ( int argc , char * const argv []) {
return Catch :: Main ( argc , argv );
}
#else // __OBJC__
// Objective-C entry point
int main ( int argc , char * const argv []) {
2012-03-17 18:20:06 +00:00
#if !CATCH_ARC_ENABLED
2011-05-24 08:23:02 +01:00
NSAutoreleasePool * pool = [[ NSAutoreleasePool alloc ] init ];
2012-03-17 18:20:06 +00:00
#endif
2011-05-24 08:23:02 +01:00
Catch :: registerTestMethods ();
int result = Catch :: Main ( argc , ( char * const * ) argv );
2012-03-17 18:20:06 +00:00
#if !CATCH_ARC_ENABLED
2011-05-24 08:23:02 +01:00
[ pool drain ];
2012-03-17 18:20:06 +00:00
#endif
2011-05-24 08:23:02 +01:00
2012-02-18 09:58:30 +00:00
return result ;
2011-05-24 08:23:02 +01:00
}
2012-05-11 08:17:16 +01:00
#endif // __OBJC__
2011-05-24 08:23:02 +01:00
#endif
//////
2012-07-20 18:43:48 +01:00
// If this config identifier is defined then all CATCH macros are prefixed with CATCH_
#ifdef CATCH_CONFIG_PREFIX_ALL
2012-11-10 18:46:39 +00: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 18:43:48 +01:00
2012-11-10 18:46:39 +00: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 18:43:48 +01:00
2012-11-10 18:46:39 +00: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 09:45:29 +00:00
#define CATCH_CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CATCH_CHECK_NOFAIL" )
2012-07-20 18:43:48 +01:00
2012-11-10 18:46:39 +00: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 18:43:48 +01:00
2012-11-10 18:46:39 +00:00
#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" )
#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THAT" )
2012-07-20 18:43:48 +01:00
2012-11-10 18:46:39 +00:00
#define CATCH_INFO( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Info, Catch::ResultDisposition::ContinueOnFailure, "CATCH_INFO" )
#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 12:07:17 +00:00
#define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_SCOPED_INFO( msg, "CATCH_SCOPED_INFO" )
2012-11-10 18:46:39 +00:00
#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_MSG( #msg " := " << msg, Catch::ResultWas::Info, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CAPTURE" )
2012-10-28 12:07:17 +00:00
#define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_SCOPED_INFO( #msg " := " << msg, "CATCH_SCOPED_CAPTURE" )
2012-07-20 18:43:48 +01: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-01 23:57:18 +00:00
#define CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType )
2012-07-20 18:43:48 +01:00
#define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required
#else
2012-11-10 18:46:39 +00: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 08:23:02 +01:00
2012-11-10 18:46:39 +00: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 08:23:02 +01:00
2012-11-10 18:46:39 +00: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 09:44:52 +00:00
#define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CHECK_NOFAIL" )
2011-05-24 08:23:02 +01:00
2012-11-10 18:46:39 +00: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 08:23:02 +01:00
2012-11-10 18:46:39 +00:00
#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THAT" )
#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "REQUIRE_THAT" )
2012-03-04 21:22:36 +00:00
2012-11-10 18:46:39 +00:00
#define INFO( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Info, Catch::ResultDisposition::ContinueOnFailure, "INFO" )
#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 12:07:17 +00:00
#define SCOPED_INFO( msg ) INTERNAL_CATCH_SCOPED_INFO( msg, "SCOPED_INFO" )
2012-11-10 18:46:39 +00:00
#define CAPTURE( msg ) INTERNAL_CATCH_MSG( #msg " := " << msg, Catch::ResultWas::Info, Catch::ResultDisposition::ContinueOnFailure, "CAPTURE" )
2012-10-28 12:07:17 +00:00
#define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_SCOPED_INFO( #msg " := " << msg, "SCOPED_CAPTURE" )
2011-05-24 08:23:02 +01: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 18:43:48 +01:00
#define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
2011-05-24 08:23:02 +01:00
#define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
2012-12-01 23:57:18 +00:00
#define REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType )
2011-05-24 08:23:02 +01:00
#define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
2012-07-20 18:43:48 +01:00
#endif
#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )
2011-05-24 08:23:02 +01:00
using Catch :: Detail :: Approx ;
2012-08-16 18:48:50 +01:00
#ifdef __clang__
2012-08-13 07:46:10 +01:00
#pragma clang diagnostic pop
2012-08-16 18:48:50 +01:00
#endif
2012-08-13 07:46:10 +01:00
2012-05-09 19:37:51 +01:00
#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
2011-05-24 08:23:02 +01:00