9428 lines
328 KiB
C++
9428 lines
328 KiB
C++
/*
|
|
* CATCH v1.1 build 14 (develop branch)
|
|
* Generated: 2015-03-04 18:32:24.627737
|
|
* ----------------------------------------------------------
|
|
* This file has been merged from multiple headers. Please don't edit it directly
|
|
* Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved.
|
|
*
|
|
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
*/
|
|
#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
|
|
#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
|
|
|
|
#define TWOBLUECUBES_CATCH_HPP_INCLUDED
|
|
|
|
// #included from: internal/catch_suppress_warnings.h
|
|
|
|
#define TWOBLUECUBES_CATCH_SUPPRESS_WARNINGS_H_INCLUDED
|
|
|
|
#ifdef __clang__
|
|
# ifdef __ICC // icpc defines the __clang__ macro
|
|
# pragma warning(push)
|
|
# pragma warning(disable: 161 1682)
|
|
# else // __ICC
|
|
# pragma clang diagnostic ignored "-Wglobal-constructors"
|
|
# pragma clang diagnostic ignored "-Wvariadic-macros"
|
|
# pragma clang diagnostic ignored "-Wc99-extensions"
|
|
# pragma clang diagnostic ignored "-Wunused-variable"
|
|
# pragma clang diagnostic push
|
|
# pragma clang diagnostic ignored "-Wpadded"
|
|
# pragma clang diagnostic ignored "-Wc++98-compat"
|
|
# pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
|
|
# endif
|
|
#elif defined __GNUC__
|
|
# pragma GCC diagnostic ignored "-Wvariadic-macros"
|
|
# pragma GCC diagnostic ignored "-Wunused-variable"
|
|
# pragma GCC diagnostic push
|
|
# pragma GCC diagnostic ignored "-Wpadded"
|
|
#endif
|
|
|
|
#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER)
|
|
# define CATCH_IMPL
|
|
#endif
|
|
|
|
#ifdef CATCH_IMPL
|
|
# ifndef CLARA_CONFIG_MAIN
|
|
# define CLARA_CONFIG_MAIN_NOT_DEFINED
|
|
# define CLARA_CONFIG_MAIN
|
|
# endif
|
|
#endif
|
|
|
|
// #included from: internal/catch_notimplemented_exception.h
|
|
#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED
|
|
|
|
// #included from: catch_common.h
|
|
#define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED
|
|
|
|
#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
|
|
#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line )
|
|
#define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
|
|
|
|
#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr
|
|
#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr )
|
|
|
|
#include <sstream>
|
|
#include <stdexcept>
|
|
#include <algorithm>
|
|
|
|
// #included from: catch_compiler_capabilities.h
|
|
#define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED
|
|
|
|
// Much of the following code is based on Boost (1.53)
|
|
|
|
#ifdef __clang__
|
|
|
|
# if __has_feature(cxx_nullptr)
|
|
# define CATCH_CONFIG_CPP11_NULLPTR
|
|
# endif
|
|
|
|
# if __has_feature(cxx_noexcept)
|
|
# define CATCH_CONFIG_CPP11_NOEXCEPT
|
|
# endif
|
|
|
|
#endif // __clang__
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// Borland
|
|
#ifdef __BORLANDC__
|
|
|
|
#if (__BORLANDC__ > 0x582 )
|
|
//#define CATCH_CONFIG_SFINAE // Not confirmed
|
|
#endif
|
|
|
|
#endif // __BORLANDC__
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// EDG
|
|
#ifdef __EDG_VERSION__
|
|
|
|
#if (__EDG_VERSION__ > 238 )
|
|
//#define CATCH_CONFIG_SFINAE // Not confirmed
|
|
#endif
|
|
|
|
#endif // __EDG_VERSION__
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// Digital Mars
|
|
#ifdef __DMC__
|
|
|
|
#if (__DMC__ > 0x840 )
|
|
//#define CATCH_CONFIG_SFINAE // Not confirmed
|
|
#endif
|
|
|
|
#endif // __DMC__
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// GCC
|
|
#ifdef __GNUC__
|
|
|
|
#if __GNUC__ < 3
|
|
|
|
#if (__GNUC_MINOR__ >= 96 )
|
|
//#define CATCH_CONFIG_SFINAE
|
|
#endif
|
|
|
|
#elif __GNUC__ >= 3
|
|
|
|
// #define CATCH_CONFIG_SFINAE // Taking this out completely for now
|
|
|
|
#endif // __GNUC__ < 3
|
|
|
|
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) )
|
|
|
|
#define CATCH_CONFIG_CPP11_NULLPTR
|
|
#endif
|
|
|
|
#endif // __GNUC__
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// Visual C++
|
|
#ifdef _MSC_VER
|
|
|
|
#if (_MSC_VER >= 1600)
|
|
#define CATCH_CONFIG_CPP11_NULLPTR
|
|
#endif
|
|
|
|
#if (_MSC_VER >= 1310 ) // (VC++ 7.0+)
|
|
//#define CATCH_CONFIG_SFINAE // Not confirmed
|
|
#endif
|
|
|
|
#endif // _MSC_VER
|
|
|
|
// Use variadic macros if the compiler supports them
|
|
#if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \
|
|
( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \
|
|
( defined __GNUC__ && __GNUC__ >= 3 ) || \
|
|
( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L )
|
|
|
|
#ifndef CATCH_CONFIG_NO_VARIADIC_MACROS
|
|
#define CATCH_CONFIG_VARIADIC_MACROS
|
|
#endif
|
|
|
|
#endif
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// C++ language feature support
|
|
|
|
// detect language version:
|
|
#if (__cplusplus == 201103L)
|
|
# define CATCH_CPP11
|
|
# define CATCH_CPP11_OR_GREATER
|
|
#elif (__cplusplus >= 201103L)
|
|
# define CATCH_CPP11_OR_GREATER
|
|
#endif
|
|
|
|
// noexcept support:
|
|
#if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT)
|
|
# define CATCH_NOEXCEPT noexcept
|
|
# define CATCH_NOEXCEPT_IS(x) noexcept(x)
|
|
#else
|
|
# define CATCH_NOEXCEPT throw()
|
|
# define CATCH_NOEXCEPT_IS(x)
|
|
#endif
|
|
|
|
namespace Catch {
|
|
|
|
class NonCopyable {
|
|
#ifdef CATCH_CPP11_OR_GREATER
|
|
NonCopyable( NonCopyable const& ) = delete;
|
|
NonCopyable( NonCopyable && ) = delete;
|
|
NonCopyable& operator = ( NonCopyable const& ) = delete;
|
|
NonCopyable& operator = ( NonCopyable && ) = delete;
|
|
#else
|
|
NonCopyable( NonCopyable const& info );
|
|
NonCopyable& operator = ( NonCopyable const& );
|
|
#endif
|
|
|
|
protected:
|
|
NonCopyable() {}
|
|
virtual ~NonCopyable();
|
|
};
|
|
|
|
class SafeBool {
|
|
public:
|
|
typedef void (SafeBool::*type)() const;
|
|
|
|
static type makeSafe( bool value ) {
|
|
return value ? &SafeBool::trueValue : 0;
|
|
}
|
|
private:
|
|
void trueValue() const {}
|
|
};
|
|
|
|
template<typename ContainerT>
|
|
inline void deleteAll( ContainerT& container ) {
|
|
typename ContainerT::const_iterator it = container.begin();
|
|
typename ContainerT::const_iterator itEnd = container.end();
|
|
for(; it != itEnd; ++it )
|
|
delete *it;
|
|
}
|
|
template<typename AssociativeContainerT>
|
|
inline void deleteAllValues( AssociativeContainerT& container ) {
|
|
typename AssociativeContainerT::const_iterator it = container.begin();
|
|
typename AssociativeContainerT::const_iterator itEnd = container.end();
|
|
for(; it != itEnd; ++it )
|
|
delete it->second;
|
|
}
|
|
|
|
bool startsWith( std::string const& s, std::string const& prefix );
|
|
bool endsWith( std::string const& s, std::string const& suffix );
|
|
bool contains( std::string const& s, std::string const& infix );
|
|
void toLowerInPlace( std::string& s );
|
|
std::string toLower( std::string const& s );
|
|
std::string trim( std::string const& str );
|
|
bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis );
|
|
|
|
struct pluralise {
|
|
pluralise( std::size_t count, std::string const& label );
|
|
|
|
friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser );
|
|
|
|
std::size_t m_count;
|
|
std::string m_label;
|
|
};
|
|
|
|
struct SourceLineInfo {
|
|
|
|
SourceLineInfo();
|
|
SourceLineInfo( char const* _file, std::size_t _line );
|
|
SourceLineInfo( SourceLineInfo const& other );
|
|
# ifdef CATCH_CPP11_OR_GREATER
|
|
SourceLineInfo( SourceLineInfo && ) = default;
|
|
SourceLineInfo& operator = ( SourceLineInfo const& ) = default;
|
|
SourceLineInfo& operator = ( SourceLineInfo && ) = default;
|
|
# endif
|
|
bool empty() const;
|
|
bool operator == ( SourceLineInfo const& other ) const;
|
|
bool operator < ( SourceLineInfo const& other ) const;
|
|
|
|
std::string file;
|
|
std::size_t line;
|
|
};
|
|
|
|
std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info );
|
|
|
|
// This is just here to avoid compiler warnings with macro constants and boolean literals
|
|
inline bool isTrue( bool value ){ return value; }
|
|
inline bool alwaysTrue() { return true; }
|
|
inline bool alwaysFalse() { return false; }
|
|
|
|
void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo );
|
|
|
|
// Use this in variadic streaming macros to allow
|
|
// >> +StreamEndStop
|
|
// as well as
|
|
// >> stuff +StreamEndStop
|
|
struct StreamEndStop {
|
|
std::string operator+() {
|
|
return std::string();
|
|
}
|
|
};
|
|
template<typename T>
|
|
T const& operator + ( T const& value, StreamEndStop ) {
|
|
return value;
|
|
}
|
|
}
|
|
|
|
#define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) )
|
|
#define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO );
|
|
|
|
#include <ostream>
|
|
|
|
namespace Catch {
|
|
|
|
class NotImplementedException : public std::exception
|
|
{
|
|
public:
|
|
NotImplementedException( SourceLineInfo const& lineInfo );
|
|
NotImplementedException( NotImplementedException const& ) {}
|
|
|
|
virtual ~NotImplementedException() CATCH_NOEXCEPT {}
|
|
|
|
virtual const char* what() const CATCH_NOEXCEPT;
|
|
|
|
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
|
|
|
|
// #included from: catch_interfaces_generators.h
|
|
#define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED
|
|
|
|
#include <string>
|
|
|
|
namespace Catch {
|
|
|
|
struct IGeneratorInfo {
|
|
virtual ~IGeneratorInfo();
|
|
virtual bool moveNext() = 0;
|
|
virtual std::size_t getCurrentIndex() const = 0;
|
|
};
|
|
|
|
struct IGeneratorsForTest {
|
|
virtual ~IGeneratorsForTest();
|
|
|
|
virtual IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) = 0;
|
|
virtual bool moveNext() = 0;
|
|
};
|
|
|
|
IGeneratorsForTest* createGeneratorsForTest();
|
|
|
|
} // end namespace Catch
|
|
|
|
// #included from: catch_ptr.hpp
|
|
#define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED
|
|
|
|
#ifdef __clang__
|
|
#pragma clang diagnostic push
|
|
#pragma clang diagnostic ignored "-Wpadded"
|
|
#endif
|
|
|
|
namespace Catch {
|
|
|
|
// An intrusive reference counting smart pointer.
|
|
// T must implement addRef() and release() methods
|
|
// typically implementing the IShared interface
|
|
template<typename T>
|
|
class Ptr {
|
|
public:
|
|
Ptr() : m_p( NULL ){}
|
|
Ptr( T* p ) : m_p( p ){
|
|
if( m_p )
|
|
m_p->addRef();
|
|
}
|
|
Ptr( Ptr const& other ) : m_p( other.m_p ){
|
|
if( m_p )
|
|
m_p->addRef();
|
|
}
|
|
~Ptr(){
|
|
if( m_p )
|
|
m_p->release();
|
|
}
|
|
void reset() {
|
|
if( m_p )
|
|
m_p->release();
|
|
m_p = NULL;
|
|
}
|
|
Ptr& operator = ( T* p ){
|
|
Ptr temp( p );
|
|
swap( temp );
|
|
return *this;
|
|
}
|
|
Ptr& operator = ( Ptr const& other ){
|
|
Ptr temp( other );
|
|
swap( temp );
|
|
return *this;
|
|
}
|
|
void swap( Ptr& other ) { std::swap( m_p, other.m_p ); }
|
|
T* get() { return m_p; }
|
|
const T* get() const{ return m_p; }
|
|
T& operator*() const { return *m_p; }
|
|
T* operator->() const { return m_p; }
|
|
bool operator !() const { return m_p == NULL; }
|
|
operator SafeBool::type() const { return SafeBool::makeSafe( m_p != NULL ); }
|
|
|
|
private:
|
|
T* m_p;
|
|
};
|
|
|
|
struct IShared : NonCopyable {
|
|
virtual ~IShared();
|
|
virtual void addRef() const = 0;
|
|
virtual void release() const = 0;
|
|
};
|
|
|
|
template<typename T = IShared>
|
|
struct SharedImpl : T {
|
|
|
|
SharedImpl() : m_rc( 0 ){}
|
|
|
|
virtual void addRef() const {
|
|
++m_rc;
|
|
}
|
|
virtual void release() const {
|
|
if( --m_rc == 0 )
|
|
delete this;
|
|
}
|
|
|
|
mutable unsigned int m_rc;
|
|
};
|
|
|
|
} // end namespace Catch
|
|
|
|
#ifdef __clang__
|
|
#pragma clang diagnostic pop
|
|
#endif
|
|
|
|
#include <memory>
|
|
#include <vector>
|
|
#include <stdlib.h>
|
|
|
|
namespace Catch {
|
|
|
|
class TestCase;
|
|
class Stream;
|
|
struct IResultCapture;
|
|
struct IRunner;
|
|
struct IGeneratorsForTest;
|
|
struct IConfig;
|
|
|
|
struct IContext
|
|
{
|
|
virtual ~IContext();
|
|
|
|
virtual IResultCapture* getResultCapture() = 0;
|
|
virtual IRunner* getRunner() = 0;
|
|
virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) = 0;
|
|
virtual bool advanceGeneratorsForCurrentTest() = 0;
|
|
virtual Ptr<IConfig const> getConfig() const = 0;
|
|
};
|
|
|
|
struct IMutableContext : IContext
|
|
{
|
|
virtual ~IMutableContext();
|
|
virtual void setResultCapture( IResultCapture* resultCapture ) = 0;
|
|
virtual void setRunner( IRunner* runner ) = 0;
|
|
virtual void setConfig( Ptr<IConfig const> const& config ) = 0;
|
|
};
|
|
|
|
IContext& getCurrentContext();
|
|
IMutableContext& getCurrentMutableContext();
|
|
void cleanUpContext();
|
|
Stream createStream( std::string const& streamName );
|
|
|
|
}
|
|
|
|
// #included from: internal/catch_test_registry.hpp
|
|
#define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED
|
|
|
|
// #included from: catch_interfaces_testcase.h
|
|
#define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED
|
|
|
|
#include <vector>
|
|
|
|
namespace Catch {
|
|
|
|
class TestSpec;
|
|
|
|
struct ITestCase : IShared {
|
|
virtual void invoke () const = 0;
|
|
protected:
|
|
virtual ~ITestCase();
|
|
};
|
|
|
|
class TestCase;
|
|
struct IConfig;
|
|
|
|
struct ITestCaseRegistry {
|
|
virtual ~ITestCaseRegistry();
|
|
virtual std::vector<TestCase> const& getAllTests() const = 0;
|
|
virtual void getFilteredTests( TestSpec const& testSpec, IConfig const& config, std::vector<TestCase>& matchingTestCases, bool negated = false ) const = 0;
|
|
|
|
};
|
|
}
|
|
|
|
namespace Catch {
|
|
|
|
template<typename C>
|
|
class MethodTestCase : public SharedImpl<ITestCase> {
|
|
|
|
public:
|
|
MethodTestCase( void (C::*method)() ) : m_method( method ) {}
|
|
|
|
virtual void invoke() const {
|
|
C obj;
|
|
(obj.*m_method)();
|
|
}
|
|
|
|
private:
|
|
virtual ~MethodTestCase() {}
|
|
|
|
void (C::*m_method)();
|
|
};
|
|
|
|
typedef void(*TestFunction)();
|
|
|
|
struct NameAndDesc {
|
|
NameAndDesc( const char* _name = "", const char* _description= "" )
|
|
: name( _name ), description( _description )
|
|
{}
|
|
|
|
const char* name;
|
|
const char* description;
|
|
};
|
|
|
|
struct AutoReg {
|
|
|
|
AutoReg( TestFunction function,
|
|
SourceLineInfo const& lineInfo,
|
|
NameAndDesc const& nameAndDesc );
|
|
|
|
template<typename C>
|
|
AutoReg( void (C::*method)(),
|
|
char const* className,
|
|
NameAndDesc const& nameAndDesc,
|
|
SourceLineInfo const& lineInfo ) {
|
|
registerTestCase( new MethodTestCase<C>( method ),
|
|
className,
|
|
nameAndDesc,
|
|
lineInfo );
|
|
}
|
|
|
|
void registerTestCase( ITestCase* testCase,
|
|
char const* className,
|
|
NameAndDesc const& nameAndDesc,
|
|
SourceLineInfo const& lineInfo );
|
|
|
|
~AutoReg();
|
|
|
|
private:
|
|
AutoReg( AutoReg const& );
|
|
void operator= ( AutoReg const& );
|
|
};
|
|
|
|
} // end namespace Catch
|
|
|
|
#ifdef CATCH_CONFIG_VARIADIC_MACROS
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
#define INTERNAL_CATCH_TESTCASE( ... ) \
|
|
static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \
|
|
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\
|
|
static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )()
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
#define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
|
|
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); }
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
#define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... )\
|
|
namespace{ \
|
|
struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \
|
|
void test(); \
|
|
}; \
|
|
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \
|
|
} \
|
|
void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test()
|
|
|
|
#else
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
#define INTERNAL_CATCH_TESTCASE( Name, Desc ) \
|
|
static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \
|
|
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\
|
|
static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )()
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
#define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \
|
|
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); }
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
#define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\
|
|
namespace{ \
|
|
struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \
|
|
void test(); \
|
|
}; \
|
|
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \
|
|
} \
|
|
void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test()
|
|
|
|
#endif
|
|
|
|
// #included from: internal/catch_capture.hpp
|
|
#define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
|
|
|
|
// #included from: catch_result_builder.h
|
|
#define TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED
|
|
|
|
// #included from: catch_result_type.h
|
|
#define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED
|
|
|
|
namespace Catch {
|
|
|
|
// ResultWas::OfType enum
|
|
struct ResultWas { enum OfType {
|
|
Unknown = -1,
|
|
Ok = 0,
|
|
Info = 1,
|
|
Warning = 2,
|
|
|
|
FailureBit = 0x10,
|
|
|
|
ExpressionFailed = FailureBit | 1,
|
|
ExplicitFailure = FailureBit | 2,
|
|
|
|
Exception = 0x100 | FailureBit,
|
|
|
|
ThrewException = Exception | 1,
|
|
DidntThrowException = Exception | 2,
|
|
|
|
FatalErrorCondition = 0x200 | FailureBit
|
|
|
|
}; };
|
|
|
|
inline bool isOk( ResultWas::OfType resultType ) {
|
|
return ( resultType & ResultWas::FailureBit ) == 0;
|
|
}
|
|
inline bool isJustInfo( int flags ) {
|
|
return flags == ResultWas::Info;
|
|
}
|
|
|
|
// ResultDisposition::Flags enum
|
|
struct ResultDisposition { enum Flags {
|
|
Normal = 0x00,
|
|
|
|
ContinueOnFailure = 0x01, // Failures fail test, but execution continues
|
|
FalseTest = 0x02, // Prefix expression with !
|
|
SuppressFail = 0x04 // Failures are reported but do not fail the test
|
|
}; };
|
|
|
|
inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) {
|
|
return static_cast<ResultDisposition::Flags>( static_cast<int>( lhs ) | static_cast<int>( rhs ) );
|
|
}
|
|
|
|
inline bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; }
|
|
inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; }
|
|
inline bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; }
|
|
|
|
} // end namespace Catch
|
|
|
|
// #included from: catch_assertionresult.h
|
|
#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED
|
|
|
|
#include <string>
|
|
|
|
namespace Catch {
|
|
|
|
struct AssertionInfo
|
|
{
|
|
AssertionInfo() {}
|
|
AssertionInfo( std::string const& _macroName,
|
|
SourceLineInfo const& _lineInfo,
|
|
std::string const& _capturedExpression,
|
|
ResultDisposition::Flags _resultDisposition );
|
|
|
|
std::string macroName;
|
|
SourceLineInfo lineInfo;
|
|
std::string capturedExpression;
|
|
ResultDisposition::Flags resultDisposition;
|
|
};
|
|
|
|
struct AssertionResultData
|
|
{
|
|
AssertionResultData() : resultType( ResultWas::Unknown ) {}
|
|
|
|
std::string reconstructedExpression;
|
|
std::string message;
|
|
ResultWas::OfType resultType;
|
|
};
|
|
|
|
class AssertionResult {
|
|
public:
|
|
AssertionResult();
|
|
AssertionResult( AssertionInfo const& info, AssertionResultData const& data );
|
|
~AssertionResult();
|
|
# ifdef CATCH_CPP11_OR_GREATER
|
|
AssertionResult( AssertionResult const& ) = default;
|
|
AssertionResult( AssertionResult && ) = default;
|
|
AssertionResult& operator = ( AssertionResult const& ) = default;
|
|
AssertionResult& operator = ( AssertionResult && ) = default;
|
|
# endif
|
|
|
|
bool isOk() const;
|
|
bool succeeded() const;
|
|
ResultWas::OfType getResultType() const;
|
|
bool hasExpression() const;
|
|
bool hasMessage() const;
|
|
std::string getExpression() const;
|
|
std::string getExpressionInMacro() const;
|
|
bool hasExpandedExpression() const;
|
|
std::string getExpandedExpression() const;
|
|
std::string getMessage() const;
|
|
SourceLineInfo getSourceInfo() const;
|
|
std::string getTestMacroName() const;
|
|
|
|
protected:
|
|
AssertionInfo m_info;
|
|
AssertionResultData m_resultData;
|
|
};
|
|
|
|
} // end namespace Catch
|
|
|
|
namespace Catch {
|
|
|
|
struct TestFailureException{};
|
|
|
|
template<typename T> class ExpressionLhs;
|
|
|
|
struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison;
|
|
|
|
struct CopyableStream {
|
|
CopyableStream() {}
|
|
CopyableStream( CopyableStream const& other ) {
|
|
oss << other.oss.str();
|
|
}
|
|
CopyableStream& operator=( CopyableStream const& other ) {
|
|
oss.str("");
|
|
oss << other.oss.str();
|
|
return *this;
|
|
}
|
|
std::ostringstream oss;
|
|
};
|
|
|
|
class ResultBuilder {
|
|
public:
|
|
ResultBuilder( char const* macroName,
|
|
SourceLineInfo const& lineInfo,
|
|
char const* capturedExpression,
|
|
ResultDisposition::Flags resultDisposition );
|
|
|
|
template<typename T>
|
|
ExpressionLhs<T const&> operator->* ( T const& operand );
|
|
ExpressionLhs<bool> operator->* ( bool value );
|
|
|
|
template<typename T>
|
|
ResultBuilder& operator << ( T const& value ) {
|
|
m_stream.oss << value;
|
|
return *this;
|
|
}
|
|
|
|
template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& );
|
|
template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& );
|
|
|
|
ResultBuilder& setResultType( ResultWas::OfType result );
|
|
ResultBuilder& setResultType( bool result );
|
|
ResultBuilder& setLhs( std::string const& lhs );
|
|
ResultBuilder& setRhs( std::string const& rhs );
|
|
ResultBuilder& setOp( std::string const& op );
|
|
|
|
void endExpression();
|
|
|
|
std::string reconstructExpression() const;
|
|
AssertionResult build() const;
|
|
|
|
void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal );
|
|
void captureResult( ResultWas::OfType resultType );
|
|
void captureExpression();
|
|
void react();
|
|
bool shouldDebugBreak() const;
|
|
bool allowThrows() const;
|
|
|
|
private:
|
|
AssertionInfo m_assertionInfo;
|
|
AssertionResultData m_data;
|
|
struct ExprComponents {
|
|
ExprComponents() : testFalse( false ) {}
|
|
bool testFalse;
|
|
std::string lhs, rhs, op;
|
|
} m_exprComponents;
|
|
CopyableStream m_stream;
|
|
|
|
bool m_shouldDebugBreak;
|
|
bool m_shouldThrow;
|
|
};
|
|
|
|
} // namespace Catch
|
|
|
|
// Include after due to circular dependency:
|
|
// #included from: catch_expression_lhs.hpp
|
|
#define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED
|
|
|
|
// #included from: catch_evaluate.hpp
|
|
#define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED
|
|
|
|
#ifdef _MSC_VER
|
|
#pragma warning(push)
|
|
#pragma warning(disable:4389) // '==' : signed/unsigned mismatch
|
|
#endif
|
|
|
|
#include <cstddef>
|
|
|
|
namespace Catch {
|
|
namespace Internal {
|
|
|
|
enum Operator {
|
|
IsEqualTo,
|
|
IsNotEqualTo,
|
|
IsLessThan,
|
|
IsGreaterThan,
|
|
IsLessThanOrEqualTo,
|
|
IsGreaterThanOrEqualTo
|
|
};
|
|
|
|
template<Operator Op> struct OperatorTraits { static const char* getName(){ return "*error*"; } };
|
|
template<> struct OperatorTraits<IsEqualTo> { static const char* getName(){ return "=="; } };
|
|
template<> struct OperatorTraits<IsNotEqualTo> { static const char* getName(){ return "!="; } };
|
|
template<> struct OperatorTraits<IsLessThan> { static const char* getName(){ return "<"; } };
|
|
template<> struct OperatorTraits<IsGreaterThan> { static const char* getName(){ return ">"; } };
|
|
template<> struct OperatorTraits<IsLessThanOrEqualTo> { static const char* getName(){ return "<="; } };
|
|
template<> struct OperatorTraits<IsGreaterThanOrEqualTo>{ static const char* getName(){ return ">="; } };
|
|
|
|
template<typename T>
|
|
inline T& opCast(T const& t) { return const_cast<T&>(t); }
|
|
|
|
// nullptr_t support based on pull request #154 from Konstantin Baumann
|
|
#ifdef CATCH_CONFIG_CPP11_NULLPTR
|
|
inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; }
|
|
#endif // CATCH_CONFIG_CPP11_NULLPTR
|
|
|
|
// So the compare overloads can be operator agnostic we convey the operator as a template
|
|
// enum, which is used to specialise an Evaluator for doing the comparison.
|
|
template<typename T1, typename T2, Operator Op>
|
|
class Evaluator{};
|
|
|
|
template<typename T1, typename T2>
|
|
struct Evaluator<T1, T2, IsEqualTo> {
|
|
static bool evaluate( T1 const& lhs, T2 const& rhs) {
|
|
return opCast( lhs ) == opCast( rhs );
|
|
}
|
|
};
|
|
template<typename T1, typename T2>
|
|
struct Evaluator<T1, T2, IsNotEqualTo> {
|
|
static bool evaluate( T1 const& lhs, T2 const& rhs ) {
|
|
return opCast( lhs ) != opCast( rhs );
|
|
}
|
|
};
|
|
template<typename T1, typename T2>
|
|
struct Evaluator<T1, T2, IsLessThan> {
|
|
static bool evaluate( T1 const& lhs, T2 const& rhs ) {
|
|
return opCast( lhs ) < opCast( rhs );
|
|
}
|
|
};
|
|
template<typename T1, typename T2>
|
|
struct Evaluator<T1, T2, IsGreaterThan> {
|
|
static bool evaluate( T1 const& lhs, T2 const& rhs ) {
|
|
return opCast( lhs ) > opCast( rhs );
|
|
}
|
|
};
|
|
template<typename T1, typename T2>
|
|
struct Evaluator<T1, T2, IsGreaterThanOrEqualTo> {
|
|
static bool evaluate( T1 const& lhs, T2 const& rhs ) {
|
|
return opCast( lhs ) >= opCast( rhs );
|
|
}
|
|
};
|
|
template<typename T1, typename T2>
|
|
struct Evaluator<T1, T2, IsLessThanOrEqualTo> {
|
|
static bool evaluate( T1 const& lhs, T2 const& rhs ) {
|
|
return opCast( lhs ) <= opCast( rhs );
|
|
}
|
|
};
|
|
|
|
template<Operator Op, typename T1, typename T2>
|
|
bool applyEvaluator( T1 const& lhs, T2 const& rhs ) {
|
|
return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
|
|
}
|
|
|
|
// This level of indirection allows us to specialise for integer types
|
|
// to avoid signed/ unsigned warnings
|
|
|
|
// "base" overload
|
|
template<Operator Op, typename T1, typename T2>
|
|
bool compare( T1 const& lhs, T2 const& rhs ) {
|
|
return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
|
|
}
|
|
|
|
// unsigned X to int
|
|
template<Operator Op> bool compare( unsigned int lhs, int rhs ) {
|
|
return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
|
|
}
|
|
template<Operator Op> bool compare( unsigned long lhs, int rhs ) {
|
|
return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
|
|
}
|
|
template<Operator Op> bool compare( unsigned char lhs, int rhs ) {
|
|
return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
|
|
}
|
|
|
|
// unsigned X to long
|
|
template<Operator Op> bool compare( unsigned int lhs, long rhs ) {
|
|
return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
|
|
}
|
|
template<Operator Op> bool compare( unsigned long lhs, long rhs ) {
|
|
return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
|
|
}
|
|
template<Operator Op> bool compare( unsigned char lhs, long rhs ) {
|
|
return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
|
|
}
|
|
|
|
// int to unsigned X
|
|
template<Operator Op> bool compare( int lhs, unsigned int rhs ) {
|
|
return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
|
|
}
|
|
template<Operator Op> bool compare( int lhs, unsigned long rhs ) {
|
|
return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
|
|
}
|
|
template<Operator Op> bool compare( int lhs, unsigned char rhs ) {
|
|
return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
|
|
}
|
|
|
|
// long to unsigned X
|
|
template<Operator Op> bool compare( long lhs, unsigned int rhs ) {
|
|
return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
|
|
}
|
|
template<Operator Op> bool compare( long lhs, unsigned long rhs ) {
|
|
return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
|
|
}
|
|
template<Operator Op> bool compare( long lhs, unsigned char rhs ) {
|
|
return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
|
|
}
|
|
|
|
// pointer to long (when comparing against NULL)
|
|
template<Operator Op, typename T> bool compare( long lhs, T* rhs ) {
|
|
return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
|
|
}
|
|
template<Operator Op, typename T> bool compare( T* lhs, long rhs ) {
|
|
return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
|
|
}
|
|
|
|
// pointer to int (when comparing against NULL)
|
|
template<Operator Op, typename T> bool compare( int lhs, T* rhs ) {
|
|
return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
|
|
}
|
|
template<Operator Op, typename T> bool compare( T* lhs, int rhs ) {
|
|
return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
|
|
}
|
|
|
|
#ifdef CATCH_CONFIG_CPP11_NULLPTR
|
|
// pointer to nullptr_t (when comparing against nullptr)
|
|
template<Operator Op, typename T> bool compare( std::nullptr_t, T* rhs ) {
|
|
return Evaluator<T*, T*, Op>::evaluate( NULL, rhs );
|
|
}
|
|
template<Operator Op, typename T> bool compare( T* lhs, std::nullptr_t ) {
|
|
return Evaluator<T*, T*, Op>::evaluate( lhs, NULL );
|
|
}
|
|
#endif // CATCH_CONFIG_CPP11_NULLPTR
|
|
|
|
} // end of namespace Internal
|
|
} // end of namespace Catch
|
|
|
|
#ifdef _MSC_VER
|
|
#pragma warning(pop)
|
|
#endif
|
|
|
|
// #included from: catch_tostring.h
|
|
#define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED
|
|
|
|
// #included from: catch_sfinae.hpp
|
|
#define TWOBLUECUBES_CATCH_SFINAE_HPP_INCLUDED
|
|
|
|
// Try to detect if the current compiler supports SFINAE
|
|
|
|
namespace Catch {
|
|
|
|
struct TrueType {
|
|
static const bool value = true;
|
|
typedef void Enable;
|
|
char sizer[1];
|
|
};
|
|
struct FalseType {
|
|
static const bool value = false;
|
|
typedef void Disable;
|
|
char sizer[2];
|
|
};
|
|
|
|
#ifdef CATCH_CONFIG_SFINAE
|
|
|
|
template<bool> struct NotABooleanExpression;
|
|
|
|
template<bool c> struct If : NotABooleanExpression<c> {};
|
|
template<> struct If<true> : TrueType {};
|
|
template<> struct If<false> : FalseType {};
|
|
|
|
template<int size> struct SizedIf;
|
|
template<> struct SizedIf<sizeof(TrueType)> : TrueType {};
|
|
template<> struct SizedIf<sizeof(FalseType)> : FalseType {};
|
|
|
|
#endif // CATCH_CONFIG_SFINAE
|
|
|
|
} // end namespace Catch
|
|
|
|
#include <sstream>
|
|
#include <iomanip>
|
|
#include <limits>
|
|
#include <vector>
|
|
#include <cstddef>
|
|
|
|
#ifdef __OBJC__
|
|
// #included from: catch_objc_arc.hpp
|
|
#define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED
|
|
|
|
#import <Foundation/Foundation.h>
|
|
|
|
#ifdef __has_feature
|
|
#define CATCH_ARC_ENABLED __has_feature(objc_arc)
|
|
#else
|
|
#define CATCH_ARC_ENABLED 0
|
|
#endif
|
|
|
|
void arcSafeRelease( NSObject* obj );
|
|
id performOptionalSelector( id obj, SEL sel );
|
|
|
|
#if !CATCH_ARC_ENABLED
|
|
inline void arcSafeRelease( NSObject* obj ) {
|
|
[obj release];
|
|
}
|
|
inline id performOptionalSelector( id obj, SEL sel ) {
|
|
if( [obj respondsToSelector: sel] )
|
|
return [obj performSelector: sel];
|
|
return nil;
|
|
}
|
|
#define CATCH_UNSAFE_UNRETAINED
|
|
#define CATCH_ARC_STRONG
|
|
#else
|
|
inline void arcSafeRelease( NSObject* ){}
|
|
inline id performOptionalSelector( id obj, SEL sel ) {
|
|
#ifdef __clang__
|
|
#pragma clang diagnostic push
|
|
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
|
|
#endif
|
|
if( [obj respondsToSelector: sel] )
|
|
return [obj performSelector: sel];
|
|
#ifdef __clang__
|
|
#pragma clang diagnostic pop
|
|
#endif
|
|
return nil;
|
|
}
|
|
#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained
|
|
#define CATCH_ARC_STRONG __strong
|
|
#endif
|
|
|
|
#endif
|
|
|
|
#ifdef CATCH_CPP11_OR_GREATER
|
|
#include <tuple>
|
|
#include <type_traits>
|
|
#endif
|
|
|
|
namespace Catch {
|
|
|
|
// Why we're here.
|
|
template<typename T>
|
|
std::string toString( T const& value );
|
|
|
|
// Built in overloads
|
|
|
|
std::string toString( std::string const& value );
|
|
std::string toString( std::wstring const& value );
|
|
std::string toString( const char* const value );
|
|
std::string toString( char* const value );
|
|
std::string toString( const wchar_t* const value );
|
|
std::string toString( wchar_t* const value );
|
|
std::string toString( int value );
|
|
std::string toString( unsigned long value );
|
|
std::string toString( unsigned int value );
|
|
std::string toString( const double value );
|
|
std::string toString( const float value );
|
|
std::string toString( bool value );
|
|
std::string toString( char value );
|
|
std::string toString( signed char value );
|
|
std::string toString( unsigned char value );
|
|
|
|
#ifdef CATCH_CONFIG_CPP11_NULLPTR
|
|
std::string toString( std::nullptr_t );
|
|
#endif
|
|
|
|
#ifdef __OBJC__
|
|
std::string toString( NSString const * const& nsstring );
|
|
std::string toString( NSString * CATCH_ARC_STRONG const& nsstring );
|
|
std::string toString( NSObject* const& nsObject );
|
|
#endif
|
|
|
|
namespace Detail {
|
|
|
|
extern std::string unprintableString;
|
|
|
|
// SFINAE is currently disabled by default for all compilers.
|
|
// If the non SFINAE version of IsStreamInsertable is ambiguous for you
|
|
// and your compiler supports SFINAE, try #defining CATCH_CONFIG_SFINAE
|
|
#ifdef CATCH_CONFIG_SFINAE
|
|
|
|
template<typename T>
|
|
class IsStreamInsertableHelper {
|
|
template<int N> struct TrueIfSizeable : TrueType {};
|
|
|
|
template<typename T2>
|
|
static TrueIfSizeable<sizeof((*(std::ostream*)0) << *((T2 const*)0))> dummy(T2*);
|
|
static FalseType dummy(...);
|
|
|
|
public:
|
|
typedef SizedIf<sizeof(dummy((T*)0))> type;
|
|
};
|
|
|
|
template<typename T>
|
|
struct IsStreamInsertable : IsStreamInsertableHelper<T>::type {};
|
|
|
|
#else
|
|
|
|
struct BorgType {
|
|
template<typename T> BorgType( T const& );
|
|
};
|
|
|
|
TrueType& testStreamable( std::ostream& );
|
|
FalseType testStreamable( FalseType );
|
|
|
|
FalseType operator<<( std::ostream const&, BorgType const& );
|
|
|
|
template<typename T>
|
|
struct IsStreamInsertable {
|
|
static std::ostream &s;
|
|
static T const&t;
|
|
enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) };
|
|
};
|
|
|
|
#endif
|
|
|
|
#if defined(CATCH_CPP11_OR_GREATER)
|
|
template<typename T,
|
|
bool IsEnum = std::is_enum<T>::value
|
|
>
|
|
struct EnumStringMaker
|
|
{
|
|
static std::string convert( T const& ) { return unprintableString; }
|
|
};
|
|
|
|
template<typename T>
|
|
struct EnumStringMaker<T,true>
|
|
{
|
|
static std::string convert( T const& v )
|
|
{
|
|
return ::Catch::toString(
|
|
static_cast<typename std::underlying_type<T>::type>(v)
|
|
);
|
|
}
|
|
};
|
|
#endif
|
|
template<bool C>
|
|
struct StringMakerBase {
|
|
#if defined(CATCH_CPP11_OR_GREATER)
|
|
template<typename T>
|
|
static std::string convert( T const& v )
|
|
{
|
|
return EnumStringMaker<T>::convert( v );
|
|
}
|
|
#else
|
|
template<typename T>
|
|
static std::string convert( T const& ) { return unprintableString; }
|
|
#endif
|
|
};
|
|
|
|
template<>
|
|
struct StringMakerBase<true> {
|
|
template<typename T>
|
|
static std::string convert( T const& _value ) {
|
|
std::ostringstream oss;
|
|
oss << _value;
|
|
return oss.str();
|
|
}
|
|
};
|
|
|
|
std::string rawMemoryToString( const void *object, std::size_t size );
|
|
|
|
template<typename T>
|
|
inline std::string rawMemoryToString( const T& object ) {
|
|
return rawMemoryToString( &object, sizeof(object) );
|
|
}
|
|
|
|
} // end namespace Detail
|
|
|
|
template<typename T>
|
|
struct StringMaker :
|
|
Detail::StringMakerBase<Detail::IsStreamInsertable<T>::value> {};
|
|
|
|
template<typename T>
|
|
struct StringMaker<T*> {
|
|
template<typename U>
|
|
static std::string convert( U* p ) {
|
|
if( !p )
|
|
return INTERNAL_CATCH_STRINGIFY( NULL );
|
|
else
|
|
return Detail::rawMemoryToString( p );
|
|
}
|
|
};
|
|
|
|
template<typename R, typename C>
|
|
struct StringMaker<R C::*> {
|
|
static std::string convert( R C::* p ) {
|
|
if( !p )
|
|
return INTERNAL_CATCH_STRINGIFY( NULL );
|
|
else
|
|
return Detail::rawMemoryToString( p );
|
|
}
|
|
};
|
|
|
|
namespace Detail {
|
|
template<typename InputIterator>
|
|
std::string rangeToString( InputIterator first, InputIterator last );
|
|
}
|
|
|
|
//template<typename T, typename Allocator>
|
|
//struct StringMaker<std::vector<T, Allocator> > {
|
|
// static std::string convert( std::vector<T,Allocator> const& v ) {
|
|
// return Detail::rangeToString( v.begin(), v.end() );
|
|
// }
|
|
//};
|
|
|
|
template<typename T, typename Allocator>
|
|
std::string toString( std::vector<T,Allocator> const& v ) {
|
|
return Detail::rangeToString( v.begin(), v.end() );
|
|
}
|
|
|
|
#ifdef CATCH_CPP11_OR_GREATER
|
|
|
|
// toString for tuples
|
|
namespace TupleDetail {
|
|
template<
|
|
typename Tuple,
|
|
std::size_t N = 0,
|
|
bool = (N < std::tuple_size<Tuple>::value)
|
|
>
|
|
struct ElementPrinter {
|
|
static void print( const Tuple& tuple, std::ostream& os )
|
|
{
|
|
os << ( N ? ", " : " " )
|
|
<< Catch::toString(std::get<N>(tuple));
|
|
ElementPrinter<Tuple,N+1>::print(tuple,os);
|
|
}
|
|
};
|
|
|
|
template<
|
|
typename Tuple,
|
|
std::size_t N
|
|
>
|
|
struct ElementPrinter<Tuple,N,false> {
|
|
static void print( const Tuple&, std::ostream& ) {}
|
|
};
|
|
|
|
}
|
|
|
|
template<typename ...Types>
|
|
struct StringMaker<std::tuple<Types...>> {
|
|
|
|
static std::string convert( const std::tuple<Types...>& tuple )
|
|
{
|
|
std::ostringstream os;
|
|
os << '{';
|
|
TupleDetail::ElementPrinter<std::tuple<Types...>>::print( tuple, os );
|
|
os << " }";
|
|
return os.str();
|
|
}
|
|
};
|
|
#endif
|
|
|
|
namespace Detail {
|
|
template<typename T>
|
|
std::string makeString( T const& value ) {
|
|
return StringMaker<T>::convert( value );
|
|
}
|
|
} // end namespace Detail
|
|
|
|
/// \brief converts any type to a string
|
|
///
|
|
/// The default template forwards on to ostringstream - except when an
|
|
/// ostringstream overload does not exist - in which case it attempts to detect
|
|
/// that and writes {?}.
|
|
/// Overload (not specialise) this template for custom typs that you don't want
|
|
/// to provide an ostream overload for.
|
|
template<typename T>
|
|
std::string toString( T const& value ) {
|
|
return StringMaker<T>::convert( value );
|
|
}
|
|
|
|
namespace Detail {
|
|
template<typename InputIterator>
|
|
std::string rangeToString( InputIterator first, InputIterator last ) {
|
|
std::ostringstream oss;
|
|
oss << "{ ";
|
|
if( first != last ) {
|
|
oss << Catch::toString( *first );
|
|
for( ++first ; first != last ; ++first )
|
|
oss << ", " << Catch::toString( *first );
|
|
}
|
|
oss << " }";
|
|
return oss.str();
|
|
}
|
|
}
|
|
|
|
} // end namespace Catch
|
|
|
|
namespace Catch {
|
|
|
|
// Wraps the LHS of an expression and captures the operator and RHS (if any) -
|
|
// wrapping them all in a ResultBuilder object
|
|
template<typename T>
|
|
class ExpressionLhs {
|
|
ExpressionLhs& operator = ( ExpressionLhs const& );
|
|
# ifdef CATCH_CPP11_OR_GREATER
|
|
ExpressionLhs& operator = ( ExpressionLhs && ) = delete;
|
|
# endif
|
|
|
|
public:
|
|
ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ) {}
|
|
# ifdef CATCH_CPP11_OR_GREATER
|
|
ExpressionLhs( ExpressionLhs const& ) = default;
|
|
ExpressionLhs( ExpressionLhs && ) = default;
|
|
# endif
|
|
|
|
template<typename RhsT>
|
|
ResultBuilder& operator == ( RhsT const& rhs ) {
|
|
return captureExpression<Internal::IsEqualTo>( rhs );
|
|
}
|
|
|
|
template<typename RhsT>
|
|
ResultBuilder& operator != ( RhsT const& rhs ) {
|
|
return captureExpression<Internal::IsNotEqualTo>( rhs );
|
|
}
|
|
|
|
template<typename RhsT>
|
|
ResultBuilder& operator < ( RhsT const& rhs ) {
|
|
return captureExpression<Internal::IsLessThan>( rhs );
|
|
}
|
|
|
|
template<typename RhsT>
|
|
ResultBuilder& operator > ( RhsT const& rhs ) {
|
|
return captureExpression<Internal::IsGreaterThan>( rhs );
|
|
}
|
|
|
|
template<typename RhsT>
|
|
ResultBuilder& operator <= ( RhsT const& rhs ) {
|
|
return captureExpression<Internal::IsLessThanOrEqualTo>( rhs );
|
|
}
|
|
|
|
template<typename RhsT>
|
|
ResultBuilder& operator >= ( RhsT const& rhs ) {
|
|
return captureExpression<Internal::IsGreaterThanOrEqualTo>( rhs );
|
|
}
|
|
|
|
ResultBuilder& operator == ( bool rhs ) {
|
|
return captureExpression<Internal::IsEqualTo>( rhs );
|
|
}
|
|
|
|
ResultBuilder& operator != ( bool rhs ) {
|
|
return captureExpression<Internal::IsNotEqualTo>( rhs );
|
|
}
|
|
|
|
void endExpression() {
|
|
bool value = m_lhs ? true : false;
|
|
m_rb
|
|
.setLhs( Catch::toString( value ) )
|
|
.setResultType( value )
|
|
.endExpression();
|
|
}
|
|
|
|
// 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 + ( RhsT const& );
|
|
template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( RhsT const& );
|
|
template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( RhsT const& );
|
|
template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( RhsT const& );
|
|
template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& );
|
|
template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& );
|
|
|
|
private:
|
|
template<Internal::Operator Op, typename RhsT>
|
|
ResultBuilder& captureExpression( RhsT const& rhs ) {
|
|
return m_rb
|
|
.setResultType( Internal::compare<Op>( m_lhs, rhs ) )
|
|
.setLhs( Catch::toString( m_lhs ) )
|
|
.setRhs( Catch::toString( rhs ) )
|
|
.setOp( Internal::OperatorTraits<Op>::getName() );
|
|
}
|
|
|
|
private:
|
|
ResultBuilder& m_rb;
|
|
T m_lhs;
|
|
};
|
|
|
|
} // end namespace Catch
|
|
|
|
|
|
namespace Catch {
|
|
|
|
template<typename T>
|
|
inline ExpressionLhs<T const&> ResultBuilder::operator->* ( T const& operand ) {
|
|
return ExpressionLhs<T const&>( *this, operand );
|
|
}
|
|
|
|
inline ExpressionLhs<bool> ResultBuilder::operator->* ( bool value ) {
|
|
return ExpressionLhs<bool>( *this, value );
|
|
}
|
|
|
|
} // namespace Catch
|
|
|
|
// #included from: catch_message.h
|
|
#define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED
|
|
|
|
#include <string>
|
|
|
|
namespace Catch {
|
|
|
|
struct MessageInfo {
|
|
MessageInfo( std::string const& _macroName,
|
|
SourceLineInfo const& _lineInfo,
|
|
ResultWas::OfType _type );
|
|
|
|
std::string macroName;
|
|
SourceLineInfo lineInfo;
|
|
ResultWas::OfType type;
|
|
std::string message;
|
|
unsigned int sequence;
|
|
|
|
bool operator == ( MessageInfo const& other ) const {
|
|
return sequence == other.sequence;
|
|
}
|
|
bool operator < ( MessageInfo const& other ) const {
|
|
return sequence < other.sequence;
|
|
}
|
|
private:
|
|
static unsigned int globalCount;
|
|
};
|
|
|
|
struct MessageBuilder {
|
|
MessageBuilder( std::string const& macroName,
|
|
SourceLineInfo const& lineInfo,
|
|
ResultWas::OfType type )
|
|
: m_info( macroName, lineInfo, type )
|
|
{}
|
|
|
|
template<typename T>
|
|
MessageBuilder& operator << ( T const& value ) {
|
|
m_stream << value;
|
|
return *this;
|
|
}
|
|
|
|
MessageInfo m_info;
|
|
std::ostringstream m_stream;
|
|
};
|
|
|
|
class ScopedMessage {
|
|
public:
|
|
ScopedMessage( MessageBuilder const& builder );
|
|
ScopedMessage( ScopedMessage const& other );
|
|
~ScopedMessage();
|
|
|
|
MessageInfo m_info;
|
|
};
|
|
|
|
} // end namespace Catch
|
|
|
|
// #included from: catch_interfaces_capture.h
|
|
#define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED
|
|
|
|
#include <string>
|
|
|
|
namespace Catch {
|
|
|
|
class TestCase;
|
|
class AssertionResult;
|
|
struct AssertionInfo;
|
|
struct SectionInfo;
|
|
struct MessageInfo;
|
|
class ScopedMessageBuilder;
|
|
struct Counts;
|
|
|
|
struct IResultCapture {
|
|
|
|
virtual ~IResultCapture();
|
|
|
|
virtual void assertionEnded( AssertionResult const& result ) = 0;
|
|
virtual bool sectionStarted( SectionInfo const& sectionInfo,
|
|
Counts& assertions ) = 0;
|
|
virtual void sectionEnded( SectionInfo const& name, Counts const& assertions, double _durationInSeconds ) = 0;
|
|
virtual void pushScopedMessage( MessageInfo const& message ) = 0;
|
|
virtual void popScopedMessage( MessageInfo const& message ) = 0;
|
|
|
|
virtual std::string getCurrentTestName() const = 0;
|
|
virtual const AssertionResult* getLastResult() const = 0;
|
|
|
|
virtual void handleFatalErrorCondition( std::string const& message ) = 0;
|
|
};
|
|
|
|
IResultCapture& getResultCapture();
|
|
}
|
|
|
|
// #included from: catch_debugger.h
|
|
#define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED
|
|
|
|
// #included from: catch_platform.h
|
|
#define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED
|
|
|
|
#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
|
|
#define CATCH_PLATFORM_MAC
|
|
#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
|
|
#define CATCH_PLATFORM_IPHONE
|
|
#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
|
|
#define CATCH_PLATFORM_WINDOWS
|
|
#endif
|
|
|
|
#include <string>
|
|
|
|
namespace Catch{
|
|
|
|
bool isDebuggerActive();
|
|
void writeToDebugConsole( std::string const& text );
|
|
}
|
|
|
|
#ifdef CATCH_PLATFORM_MAC
|
|
|
|
// The following code snippet based on:
|
|
// http://cocoawithlove.com/2008/03/break-into-debugger.html
|
|
#ifdef DEBUG
|
|
#if defined(__ppc64__) || defined(__ppc__)
|
|
#define CATCH_BREAK_INTO_DEBUGGER() \
|
|
if( Catch::isDebuggerActive() ) { \
|
|
__asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \
|
|
: : : "memory","r0","r3","r4" ); \
|
|
}
|
|
#else
|
|
#define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );}
|
|
#endif
|
|
#endif
|
|
|
|
#elif defined(_MSC_VER)
|
|
#define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { __debugbreak(); }
|
|
#elif defined(__MINGW32__)
|
|
extern "C" __declspec(dllimport) void __stdcall DebugBreak();
|
|
#define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { DebugBreak(); }
|
|
#endif
|
|
|
|
#ifndef CATCH_BREAK_INTO_DEBUGGER
|
|
#define CATCH_BREAK_INTO_DEBUGGER() Catch::alwaysTrue();
|
|
#endif
|
|
|
|
// #included from: catch_interfaces_runner.h
|
|
#define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED
|
|
|
|
namespace Catch {
|
|
class TestCase;
|
|
|
|
struct IRunner {
|
|
virtual ~IRunner();
|
|
virtual bool aborting() const = 0;
|
|
};
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// In the event of a failure works out if the debugger needs to be invoked
|
|
// and/or an exception thrown and takes appropriate action.
|
|
// This needs to be done as a macro so the debugger will stop in the user
|
|
// source code rather than in Catch library code
|
|
#define INTERNAL_CATCH_REACT( resultBuilder ) \
|
|
if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \
|
|
resultBuilder.react();
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
#define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \
|
|
do { \
|
|
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
|
|
try { \
|
|
( __catchResult->*expr ).endExpression(); \
|
|
} \
|
|
catch( ... ) { \
|
|
__catchResult.useActiveException( Catch::ResultDisposition::Normal ); \
|
|
} \
|
|
INTERNAL_CATCH_REACT( __catchResult ) \
|
|
} while( Catch::isTrue( false && (expr) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
#define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \
|
|
INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \
|
|
if( Catch::getResultCapture().getLastResult()->succeeded() )
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
#define INTERNAL_CATCH_ELSE( expr, resultDisposition, macroName ) \
|
|
INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \
|
|
if( !Catch::getResultCapture().getLastResult()->succeeded() )
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
#define INTERNAL_CATCH_NO_THROW( expr, resultDisposition, macroName ) \
|
|
do { \
|
|
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
|
|
try { \
|
|
expr; \
|
|
__catchResult.captureResult( Catch::ResultWas::Ok ); \
|
|
} \
|
|
catch( ... ) { \
|
|
__catchResult.useActiveException( resultDisposition ); \
|
|
} \
|
|
INTERNAL_CATCH_REACT( __catchResult ) \
|
|
} while( Catch::alwaysFalse() )
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
#define INTERNAL_CATCH_THROWS( expr, resultDisposition, macroName ) \
|
|
do { \
|
|
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
|
|
if( __catchResult.allowThrows() ) \
|
|
try { \
|
|
expr; \
|
|
__catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \
|
|
} \
|
|
catch( ... ) { \
|
|
__catchResult.captureResult( Catch::ResultWas::Ok ); \
|
|
} \
|
|
else \
|
|
__catchResult.captureResult( Catch::ResultWas::Ok ); \
|
|
INTERNAL_CATCH_REACT( __catchResult ) \
|
|
} while( Catch::alwaysFalse() )
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
#define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, resultDisposition, macroName ) \
|
|
do { \
|
|
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
|
|
if( __catchResult.allowThrows() ) \
|
|
try { \
|
|
expr; \
|
|
__catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \
|
|
} \
|
|
catch( exceptionType ) { \
|
|
__catchResult.captureResult( Catch::ResultWas::Ok ); \
|
|
} \
|
|
catch( ... ) { \
|
|
__catchResult.useActiveException( resultDisposition ); \
|
|
} \
|
|
else \
|
|
__catchResult.captureResult( Catch::ResultWas::Ok ); \
|
|
INTERNAL_CATCH_REACT( __catchResult ) \
|
|
} while( Catch::alwaysFalse() )
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
#ifdef CATCH_CONFIG_VARIADIC_MACROS
|
|
#define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, ... ) \
|
|
do { \
|
|
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
|
|
__catchResult << __VA_ARGS__ + ::Catch::StreamEndStop(); \
|
|
__catchResult.captureResult( messageType ); \
|
|
INTERNAL_CATCH_REACT( __catchResult ) \
|
|
} while( Catch::alwaysFalse() )
|
|
#else
|
|
#define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, log ) \
|
|
do { \
|
|
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
|
|
__catchResult << log + ::Catch::StreamEndStop(); \
|
|
__catchResult.captureResult( messageType ); \
|
|
INTERNAL_CATCH_REACT( __catchResult ) \
|
|
} while( Catch::alwaysFalse() )
|
|
#endif
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
#define INTERNAL_CATCH_INFO( log, macroName ) \
|
|
Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log;
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
#define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \
|
|
do { \
|
|
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg " " #matcher, resultDisposition ); \
|
|
try { \
|
|
std::string matcherAsString = ::Catch::Matchers::matcher.toString(); \
|
|
__catchResult \
|
|
.setLhs( Catch::toString( arg ) ) \
|
|
.setRhs( matcherAsString == Catch::Detail::unprintableString ? #matcher : matcherAsString ) \
|
|
.setOp( "matches" ) \
|
|
.setResultType( ::Catch::Matchers::matcher.match( arg ) ); \
|
|
__catchResult.captureExpression(); \
|
|
} catch( ... ) { \
|
|
__catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \
|
|
} \
|
|
INTERNAL_CATCH_REACT( __catchResult ) \
|
|
} while( Catch::alwaysFalse() )
|
|
|
|
// #included from: internal/catch_section.h
|
|
#define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED
|
|
|
|
// #included from: catch_section_info.h
|
|
#define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED
|
|
|
|
namespace Catch {
|
|
|
|
struct SectionInfo {
|
|
SectionInfo
|
|
( SourceLineInfo const& _lineInfo,
|
|
std::string const& _name,
|
|
std::string const& _description = std::string() );
|
|
|
|
std::string name;
|
|
std::string description;
|
|
SourceLineInfo lineInfo;
|
|
};
|
|
|
|
} // end namespace Catch
|
|
|
|
// #included from: catch_totals.hpp
|
|
#define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED
|
|
|
|
#include <cstddef>
|
|
|
|
namespace Catch {
|
|
|
|
struct Counts {
|
|
Counts() : passed( 0 ), failed( 0 ), failedButOk( 0 ) {}
|
|
|
|
Counts operator - ( Counts const& other ) const {
|
|
Counts diff;
|
|
diff.passed = passed - other.passed;
|
|
diff.failed = failed - other.failed;
|
|
diff.failedButOk = failedButOk - other.failedButOk;
|
|
return diff;
|
|
}
|
|
Counts& operator += ( Counts const& other ) {
|
|
passed += other.passed;
|
|
failed += other.failed;
|
|
failedButOk += other.failedButOk;
|
|
return *this;
|
|
}
|
|
|
|
std::size_t total() const {
|
|
return passed + failed + failedButOk;
|
|
}
|
|
bool allPassed() const {
|
|
return failed == 0 && failedButOk == 0;
|
|
}
|
|
bool allOk() const {
|
|
return failed == 0;
|
|
}
|
|
|
|
std::size_t passed;
|
|
std::size_t failed;
|
|
std::size_t failedButOk;
|
|
};
|
|
|
|
struct Totals {
|
|
|
|
Totals operator - ( Totals const& other ) const {
|
|
Totals diff;
|
|
diff.assertions = assertions - other.assertions;
|
|
diff.testCases = testCases - other.testCases;
|
|
return diff;
|
|
}
|
|
|
|
Totals delta( Totals const& prevTotals ) const {
|
|
Totals diff = *this - prevTotals;
|
|
if( diff.assertions.failed > 0 )
|
|
++diff.testCases.failed;
|
|
else if( diff.assertions.failedButOk > 0 )
|
|
++diff.testCases.failedButOk;
|
|
else
|
|
++diff.testCases.passed;
|
|
return diff;
|
|
}
|
|
|
|
Totals& operator += ( Totals const& other ) {
|
|
assertions += other.assertions;
|
|
testCases += other.testCases;
|
|
return *this;
|
|
}
|
|
|
|
Counts assertions;
|
|
Counts testCases;
|
|
};
|
|
}
|
|
|
|
// #included from: catch_timer.h
|
|
#define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED
|
|
|
|
#ifdef CATCH_PLATFORM_WINDOWS
|
|
typedef unsigned long long uint64_t;
|
|
#else
|
|
#include <stdint.h>
|
|
#endif
|
|
|
|
namespace Catch {
|
|
|
|
class Timer {
|
|
public:
|
|
Timer() : m_ticks( 0 ) {}
|
|
void start();
|
|
unsigned int getElapsedMicroseconds() const;
|
|
unsigned int getElapsedMilliseconds() const;
|
|
double getElapsedSeconds() const;
|
|
|
|
private:
|
|
uint64_t m_ticks;
|
|
};
|
|
|
|
} // namespace Catch
|
|
|
|
#include <string>
|
|
|
|
namespace Catch {
|
|
|
|
class Section : NonCopyable {
|
|
public:
|
|
Section( SectionInfo const& info );
|
|
~Section();
|
|
|
|
// This indicates whether the section should be executed or not
|
|
operator bool() const;
|
|
|
|
private:
|
|
SectionInfo m_info;
|
|
|
|
std::string m_name;
|
|
Counts m_assertions;
|
|
bool m_sectionIncluded;
|
|
Timer m_timer;
|
|
};
|
|
|
|
} // end namespace Catch
|
|
|
|
#ifdef CATCH_CONFIG_VARIADIC_MACROS
|
|
#define INTERNAL_CATCH_SECTION( ... ) \
|
|
if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) )
|
|
#else
|
|
#define INTERNAL_CATCH_SECTION( name, desc ) \
|
|
if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, name, desc ) )
|
|
#endif
|
|
|
|
// #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<int>( 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>
|
|
// #included from: catch_interfaces_registry_hub.h
|
|
#define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED
|
|
|
|
#include <string>
|
|
|
|
namespace Catch {
|
|
|
|
class TestCase;
|
|
struct ITestCaseRegistry;
|
|
struct IExceptionTranslatorRegistry;
|
|
struct IExceptionTranslator;
|
|
struct IReporterRegistry;
|
|
struct IReporterFactory;
|
|
|
|
struct IRegistryHub {
|
|
virtual ~IRegistryHub();
|
|
|
|
virtual IReporterRegistry const& getReporterRegistry() const = 0;
|
|
virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0;
|
|
virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0;
|
|
};
|
|
|
|
struct IMutableRegistryHub {
|
|
virtual ~IMutableRegistryHub();
|
|
virtual void registerReporter( std::string const& name, IReporterFactory* factory ) = 0;
|
|
virtual void registerTest( TestCase const& testInfo ) = 0;
|
|
virtual void registerTranslator( const IExceptionTranslator* translator ) = 0;
|
|
};
|
|
|
|
IRegistryHub& getRegistryHub();
|
|
IMutableRegistryHub& getMutableRegistryHub();
|
|
void cleanUp();
|
|
std::string translateActiveException();
|
|
|
|
}
|
|
|
|
|
|
namespace Catch {
|
|
|
|
typedef std::string(*exceptionTranslateFunction)();
|
|
|
|
struct IExceptionTranslator {
|
|
virtual ~IExceptionTranslator();
|
|
virtual std::string translate() const = 0;
|
|
};
|
|
|
|
struct IExceptionTranslatorRegistry {
|
|
virtual ~IExceptionTranslatorRegistry();
|
|
|
|
virtual std::string translateActiveException() const = 0;
|
|
};
|
|
|
|
class ExceptionTranslatorRegistrar {
|
|
template<typename T>
|
|
class ExceptionTranslator : public IExceptionTranslator {
|
|
public:
|
|
|
|
ExceptionTranslator( std::string(*translateFunction)( T& ) )
|
|
: m_translateFunction( translateFunction )
|
|
{}
|
|
|
|
virtual std::string translate() const {
|
|
try {
|
|
throw;
|
|
}
|
|
catch( T& ex ) {
|
|
return m_translateFunction( ex );
|
|
}
|
|
}
|
|
|
|
protected:
|
|
std::string(*m_translateFunction)( T& );
|
|
};
|
|
|
|
public:
|
|
template<typename T>
|
|
ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) {
|
|
getMutableRegistryHub().registerTranslator
|
|
( new ExceptionTranslator<T>( translateFunction ) );
|
|
}
|
|
};
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) \
|
|
static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ); \
|
|
namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ) ); }\
|
|
static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature )
|
|
|
|
// #included from: internal/catch_approx.hpp
|
|
#define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
|
|
|
|
#include <cmath>
|
|
#include <limits>
|
|
|
|
namespace Catch {
|
|
namespace Detail {
|
|
|
|
class Approx {
|
|
public:
|
|
explicit Approx ( double value )
|
|
: m_epsilon( std::numeric_limits<float>::epsilon()*100 ),
|
|
m_scale( 1.0 ),
|
|
m_value( value )
|
|
{}
|
|
|
|
Approx( Approx const& other )
|
|
: m_epsilon( other.m_epsilon ),
|
|
m_scale( other.m_scale ),
|
|
m_value( other.m_value )
|
|
{}
|
|
|
|
static Approx custom() {
|
|
return Approx( 0 );
|
|
}
|
|
|
|
Approx operator()( double value ) {
|
|
Approx approx( value );
|
|
approx.epsilon( m_epsilon );
|
|
approx.scale( m_scale );
|
|
return approx;
|
|
}
|
|
|
|
friend bool operator == ( double lhs, Approx const& rhs ) {
|
|
// Thanks to Richard Harris for his help refining this formula
|
|
return fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs), fabs(rhs.m_value) ) );
|
|
}
|
|
|
|
friend bool operator == ( Approx const& lhs, double rhs ) {
|
|
return operator==( rhs, lhs );
|
|
}
|
|
|
|
friend bool operator != ( double lhs, Approx const& rhs ) {
|
|
return !operator==( lhs, rhs );
|
|
}
|
|
|
|
friend bool operator != ( Approx const& lhs, double rhs ) {
|
|
return !operator==( rhs, lhs );
|
|
}
|
|
|
|
Approx& epsilon( double newEpsilon ) {
|
|
m_epsilon = newEpsilon;
|
|
return *this;
|
|
}
|
|
|
|
Approx& scale( double newScale ) {
|
|
m_scale = newScale;
|
|
return *this;
|
|
}
|
|
|
|
std::string toString() const {
|
|
std::ostringstream oss;
|
|
oss << "Approx( " << Catch::toString( m_value ) << " )";
|
|
return oss.str();
|
|
}
|
|
|
|
private:
|
|
double m_epsilon;
|
|
double m_scale;
|
|
double m_value;
|
|
};
|
|
}
|
|
|
|
template<>
|
|
inline std::string toString<Detail::Approx>( Detail::Approx const& value ) {
|
|
return value.toString();
|
|
}
|
|
|
|
} // end namespace Catch
|
|
|
|
// #included from: internal/catch_matchers.hpp
|
|
#define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED
|
|
|
|
namespace Catch {
|
|
namespace Matchers {
|
|
namespace Impl {
|
|
|
|
template<typename ExpressionT>
|
|
struct Matcher : SharedImpl<IShared>
|
|
{
|
|
typedef ExpressionT ExpressionType;
|
|
|
|
virtual ~Matcher() {}
|
|
virtual Ptr<Matcher> clone() const = 0;
|
|
virtual bool match( ExpressionT const& expr ) const = 0;
|
|
virtual std::string toString() const = 0;
|
|
};
|
|
|
|
template<typename DerivedT, typename ExpressionT>
|
|
struct MatcherImpl : Matcher<ExpressionT> {
|
|
|
|
virtual Ptr<Matcher<ExpressionT> > clone() const {
|
|
return Ptr<Matcher<ExpressionT> >( new DerivedT( static_cast<DerivedT const&>( *this ) ) );
|
|
}
|
|
};
|
|
|
|
namespace Generic {
|
|
|
|
template<typename ExpressionT>
|
|
class AllOf : public MatcherImpl<AllOf<ExpressionT>, ExpressionT> {
|
|
public:
|
|
|
|
AllOf() {}
|
|
AllOf( AllOf const& other ) : m_matchers( other.m_matchers ) {}
|
|
|
|
AllOf& add( Matcher<ExpressionT> const& matcher ) {
|
|
m_matchers.push_back( matcher.clone() );
|
|
return *this;
|
|
}
|
|
virtual bool match( ExpressionT const& expr ) const
|
|
{
|
|
for( std::size_t i = 0; i < m_matchers.size(); ++i )
|
|
if( !m_matchers[i]->match( expr ) )
|
|
return false;
|
|
return true;
|
|
}
|
|
virtual std::string toString() const {
|
|
std::ostringstream oss;
|
|
oss << "( ";
|
|
for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
|
|
if( i != 0 )
|
|
oss << " and ";
|
|
oss << m_matchers[i]->toString();
|
|
}
|
|
oss << " )";
|
|
return oss.str();
|
|
}
|
|
|
|
private:
|
|
std::vector<Ptr<Matcher<ExpressionT> > > m_matchers;
|
|
};
|
|
|
|
template<typename ExpressionT>
|
|
class AnyOf : public MatcherImpl<AnyOf<ExpressionT>, ExpressionT> {
|
|
public:
|
|
|
|
AnyOf() {}
|
|
AnyOf( AnyOf const& other ) : m_matchers( other.m_matchers ) {}
|
|
|
|
AnyOf& add( Matcher<ExpressionT> const& matcher ) {
|
|
m_matchers.push_back( matcher.clone() );
|
|
return *this;
|
|
}
|
|
virtual bool match( ExpressionT const& expr ) const
|
|
{
|
|
for( std::size_t i = 0; i < m_matchers.size(); ++i )
|
|
if( m_matchers[i]->match( expr ) )
|
|
return true;
|
|
return false;
|
|
}
|
|
virtual std::string toString() const {
|
|
std::ostringstream oss;
|
|
oss << "( ";
|
|
for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
|
|
if( i != 0 )
|
|
oss << " or ";
|
|
oss << m_matchers[i]->toString();
|
|
}
|
|
oss << " )";
|
|
return oss.str();
|
|
}
|
|
|
|
private:
|
|
std::vector<Ptr<Matcher<ExpressionT> > > m_matchers;
|
|
};
|
|
|
|
}
|
|
|
|
namespace StdString {
|
|
|
|
inline std::string makeString( std::string const& str ) { return str; }
|
|
inline std::string makeString( const char* str ) { return str ? std::string( str ) : std::string(); }
|
|
|
|
struct Equals : MatcherImpl<Equals, std::string> {
|
|
Equals( std::string const& str ) : m_str( str ){}
|
|
Equals( Equals const& other ) : m_str( other.m_str ){}
|
|
|
|
virtual ~Equals();
|
|
|
|
virtual bool match( std::string const& expr ) const {
|
|
return m_str == expr;
|
|
}
|
|
virtual std::string toString() const {
|
|
return "equals: \"" + m_str + "\"";
|
|
}
|
|
|
|
std::string m_str;
|
|
};
|
|
|
|
struct Contains : MatcherImpl<Contains, std::string> {
|
|
Contains( std::string const& substr ) : m_substr( substr ){}
|
|
Contains( Contains const& other ) : m_substr( other.m_substr ){}
|
|
|
|
virtual ~Contains();
|
|
|
|
virtual bool match( std::string const& expr ) const {
|
|
return expr.find( m_substr ) != std::string::npos;
|
|
}
|
|
virtual std::string toString() const {
|
|
return "contains: \"" + m_substr + "\"";
|
|
}
|
|
|
|
std::string m_substr;
|
|
};
|
|
|
|
struct StartsWith : MatcherImpl<StartsWith, std::string> {
|
|
StartsWith( std::string const& substr ) : m_substr( substr ){}
|
|
StartsWith( StartsWith const& other ) : m_substr( other.m_substr ){}
|
|
|
|
virtual ~StartsWith();
|
|
|
|
virtual bool match( std::string const& expr ) const {
|
|
return expr.find( m_substr ) == 0;
|
|
}
|
|
virtual std::string toString() const {
|
|
return "starts with: \"" + m_substr + "\"";
|
|
}
|
|
|
|
std::string m_substr;
|
|
};
|
|
|
|
struct EndsWith : MatcherImpl<EndsWith, std::string> {
|
|
EndsWith( std::string const& substr ) : m_substr( substr ){}
|
|
EndsWith( EndsWith const& other ) : m_substr( other.m_substr ){}
|
|
|
|
virtual ~EndsWith();
|
|
|
|
virtual bool match( std::string const& expr ) const {
|
|
return expr.find( m_substr ) == expr.size() - m_substr.size();
|
|
}
|
|
virtual std::string toString() const {
|
|
return "ends with: \"" + m_substr + "\"";
|
|
}
|
|
|
|
std::string m_substr;
|
|
};
|
|
} // namespace StdString
|
|
} // namespace Impl
|
|
|
|
// The following functions create the actual matcher objects.
|
|
// This allows the types to be inferred
|
|
template<typename ExpressionT>
|
|
inline Impl::Generic::AllOf<ExpressionT> AllOf( Impl::Matcher<ExpressionT> const& m1,
|
|
Impl::Matcher<ExpressionT> const& m2 ) {
|
|
return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 );
|
|
}
|
|
template<typename ExpressionT>
|
|
inline Impl::Generic::AllOf<ExpressionT> AllOf( Impl::Matcher<ExpressionT> const& m1,
|
|
Impl::Matcher<ExpressionT> const& m2,
|
|
Impl::Matcher<ExpressionT> const& m3 ) {
|
|
return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 ).add( m3 );
|
|
}
|
|
template<typename ExpressionT>
|
|
inline Impl::Generic::AnyOf<ExpressionT> AnyOf( Impl::Matcher<ExpressionT> const& m1,
|
|
Impl::Matcher<ExpressionT> const& m2 ) {
|
|
return Impl::Generic::AnyOf<ExpressionT>().add( m1 ).add( m2 );
|
|
}
|
|
template<typename ExpressionT>
|
|
inline Impl::Generic::AnyOf<ExpressionT> AnyOf( Impl::Matcher<ExpressionT> const& m1,
|
|
Impl::Matcher<ExpressionT> const& m2,
|
|
Impl::Matcher<ExpressionT> const& m3 ) {
|
|
return Impl::Generic::AnyOf<ExpressionT>().add( m1 ).add( m2 ).add( m3 );
|
|
}
|
|
|
|
inline Impl::StdString::Equals Equals( std::string const& str ) {
|
|
return Impl::StdString::Equals( str );
|
|
}
|
|
inline Impl::StdString::Equals Equals( const char* str ) {
|
|
return Impl::StdString::Equals( Impl::StdString::makeString( str ) );
|
|
}
|
|
inline Impl::StdString::Contains Contains( std::string const& substr ) {
|
|
return Impl::StdString::Contains( substr );
|
|
}
|
|
inline Impl::StdString::Contains Contains( const char* substr ) {
|
|
return Impl::StdString::Contains( Impl::StdString::makeString( substr ) );
|
|
}
|
|
inline Impl::StdString::StartsWith StartsWith( std::string const& substr ) {
|
|
return Impl::StdString::StartsWith( substr );
|
|
}
|
|
inline Impl::StdString::StartsWith StartsWith( const char* substr ) {
|
|
return Impl::StdString::StartsWith( Impl::StdString::makeString( substr ) );
|
|
}
|
|
inline Impl::StdString::EndsWith EndsWith( std::string const& substr ) {
|
|
return Impl::StdString::EndsWith( substr );
|
|
}
|
|
inline Impl::StdString::EndsWith EndsWith( const char* substr ) {
|
|
return Impl::StdString::EndsWith( Impl::StdString::makeString( substr ) );
|
|
}
|
|
|
|
} // namespace Matchers
|
|
|
|
using namespace Matchers;
|
|
|
|
} // namespace Catch
|
|
|
|
// #included from: internal/catch_interfaces_tag_alias_registry.h
|
|
#define TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED
|
|
|
|
// #included from: catch_tag_alias.h
|
|
#define TWOBLUECUBES_CATCH_TAG_ALIAS_H_INCLUDED
|
|
|
|
#include <string>
|
|
|
|
namespace Catch {
|
|
|
|
struct TagAlias {
|
|
TagAlias( std::string _tag, SourceLineInfo _lineInfo ) : tag( _tag ), lineInfo( _lineInfo ) {}
|
|
|
|
std::string tag;
|
|
SourceLineInfo lineInfo;
|
|
};
|
|
|
|
struct RegistrarForTagAliases {
|
|
RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo );
|
|
};
|
|
|
|
} // end namespace Catch
|
|
|
|
#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); }
|
|
// #included from: catch_option.hpp
|
|
#define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED
|
|
|
|
namespace Catch {
|
|
|
|
// An optional type
|
|
template<typename T>
|
|
class Option {
|
|
public:
|
|
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 ) {
|
|
if( &_other != this ) {
|
|
reset();
|
|
if( _other )
|
|
nullableValue = new( storage ) T( *_other );
|
|
}
|
|
return *this;
|
|
}
|
|
Option& operator = ( T const& _value ) {
|
|
reset();
|
|
nullableValue = new( storage ) T( _value );
|
|
return *this;
|
|
}
|
|
|
|
void reset() {
|
|
if( nullableValue )
|
|
nullableValue->~T();
|
|
nullableValue = NULL;
|
|
}
|
|
|
|
T& operator*() { return *nullableValue; }
|
|
T const& operator*() const { return *nullableValue; }
|
|
T* operator->() { return nullableValue; }
|
|
const T* operator->() const { return nullableValue; }
|
|
|
|
T valueOr( T const& defaultValue ) const {
|
|
return nullableValue ? *nullableValue : defaultValue;
|
|
}
|
|
|
|
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
|
|
|
|
namespace Catch {
|
|
|
|
struct ITagAliasRegistry {
|
|
virtual ~ITagAliasRegistry();
|
|
virtual Option<TagAlias> find( std::string const& alias ) const = 0;
|
|
virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0;
|
|
|
|
static ITagAliasRegistry const& get();
|
|
};
|
|
|
|
} // end namespace Catch
|
|
|
|
// These files are included here so the single_include script doesn't put them
|
|
// in the conditionally compiled sections
|
|
// #included from: internal/catch_test_case_info.h
|
|
#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED
|
|
|
|
#include <string>
|
|
#include <set>
|
|
|
|
#ifdef __clang__
|
|
#pragma clang diagnostic push
|
|
#pragma clang diagnostic ignored "-Wpadded"
|
|
#endif
|
|
|
|
namespace Catch {
|
|
|
|
struct ITestCase;
|
|
|
|
struct TestCaseInfo {
|
|
enum SpecialProperties{
|
|
None = 0,
|
|
IsHidden = 1 << 1,
|
|
ShouldFail = 1 << 2,
|
|
MayFail = 1 << 3,
|
|
Throws = 1 << 4
|
|
};
|
|
|
|
TestCaseInfo( std::string const& _name,
|
|
std::string const& _className,
|
|
std::string const& _description,
|
|
std::set<std::string> const& _tags,
|
|
SourceLineInfo const& _lineInfo );
|
|
|
|
TestCaseInfo( TestCaseInfo const& other );
|
|
|
|
bool isHidden() const;
|
|
bool throws() const;
|
|
bool okToFail() const;
|
|
bool expectedToFail() const;
|
|
|
|
std::string name;
|
|
std::string className;
|
|
std::string description;
|
|
std::set<std::string> tags;
|
|
std::set<std::string> lcaseTags;
|
|
std::string tagsAsString;
|
|
SourceLineInfo lineInfo;
|
|
SpecialProperties properties;
|
|
};
|
|
|
|
class TestCase : public TestCaseInfo {
|
|
public:
|
|
|
|
TestCase( ITestCase* testCase, TestCaseInfo const& info );
|
|
TestCase( TestCase const& other );
|
|
|
|
TestCase withName( std::string const& _newName ) const;
|
|
|
|
void invoke() const;
|
|
|
|
TestCaseInfo const& getTestCaseInfo() const;
|
|
|
|
void swap( TestCase& other );
|
|
bool operator == ( TestCase const& other ) const;
|
|
bool operator < ( TestCase const& other ) const;
|
|
TestCase& operator = ( TestCase const& other );
|
|
|
|
private:
|
|
Ptr<ITestCase> test;
|
|
};
|
|
|
|
TestCase makeTestCase( ITestCase* testCase,
|
|
std::string const& className,
|
|
std::string const& name,
|
|
std::string const& description,
|
|
SourceLineInfo const& lineInfo );
|
|
}
|
|
|
|
#ifdef __clang__
|
|
#pragma clang diagnostic pop
|
|
#endif
|
|
|
|
|
|
#ifdef __OBJC__
|
|
// #included from: internal/catch_objc.hpp
|
|
#define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED
|
|
|
|
#import <objc/runtime.h>
|
|
|
|
#include <string>
|
|
|
|
// NB. Any general catch headers included here must be included
|
|
// in catch.hpp first to make sure they are included by the single
|
|
// header for non obj-usage
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// This protocol is really only here for (self) documenting purposes, since
|
|
// all its methods are optional.
|
|
@protocol OcFixture
|
|
|
|
@optional
|
|
|
|
-(void) setUp;
|
|
-(void) tearDown;
|
|
|
|
@end
|
|
|
|
namespace Catch {
|
|
|
|
class OcMethod : public SharedImpl<ITestCase> {
|
|
|
|
public:
|
|
OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {}
|
|
|
|
virtual void invoke() const {
|
|
id obj = [[m_cls alloc] init];
|
|
|
|
performOptionalSelector( obj, @selector(setUp) );
|
|
performOptionalSelector( obj, m_sel );
|
|
performOptionalSelector( obj, @selector(tearDown) );
|
|
|
|
arcSafeRelease( obj );
|
|
}
|
|
private:
|
|
virtual ~OcMethod() {}
|
|
|
|
Class m_cls;
|
|
SEL m_sel;
|
|
};
|
|
|
|
namespace Detail{
|
|
|
|
inline std::string getAnnotation( Class cls,
|
|
std::string const& annotationName,
|
|
std::string const& testCaseName ) {
|
|
NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()];
|
|
SEL sel = NSSelectorFromString( selStr );
|
|
arcSafeRelease( selStr );
|
|
id value = performOptionalSelector( cls, sel );
|
|
if( value )
|
|
return [(NSString*)value UTF8String];
|
|
return "";
|
|
}
|
|
}
|
|
|
|
inline size_t registerTestMethods() {
|
|
size_t noTestMethods = 0;
|
|
int noClasses = objc_getClassList( NULL, 0 );
|
|
|
|
Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses);
|
|
objc_getClassList( classes, noClasses );
|
|
|
|
for( int c = 0; c < noClasses; c++ ) {
|
|
Class cls = classes[c];
|
|
{
|
|
u_int count;
|
|
Method* methods = class_copyMethodList( cls, &count );
|
|
for( u_int m = 0; m < count ; m++ ) {
|
|
SEL selector = method_getName(methods[m]);
|
|
std::string methodName = sel_getName(selector);
|
|
if( startsWith( methodName, "Catch_TestCase_" ) ) {
|
|
std::string testCaseName = methodName.substr( 15 );
|
|
std::string name = Detail::getAnnotation( cls, "Name", testCaseName );
|
|
std::string desc = Detail::getAnnotation( cls, "Description", testCaseName );
|
|
const char* className = class_getName( cls );
|
|
|
|
getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo() ) );
|
|
noTestMethods++;
|
|
}
|
|
}
|
|
free(methods);
|
|
}
|
|
}
|
|
return noTestMethods;
|
|
}
|
|
|
|
namespace Matchers {
|
|
namespace Impl {
|
|
namespace NSStringMatchers {
|
|
|
|
template<typename MatcherT>
|
|
struct StringHolder : MatcherImpl<MatcherT, NSString*>{
|
|
StringHolder( NSString* substr ) : m_substr( [substr copy] ){}
|
|
StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){}
|
|
StringHolder() {
|
|
arcSafeRelease( m_substr );
|
|
}
|
|
|
|
NSString* m_substr;
|
|
};
|
|
|
|
struct Equals : StringHolder<Equals> {
|
|
Equals( NSString* substr ) : StringHolder( substr ){}
|
|
|
|
virtual bool match( ExpressionType const& str ) const {
|
|
return (str != nil || m_substr == nil ) &&
|
|
[str isEqualToString:m_substr];
|
|
}
|
|
|
|
virtual std::string toString() const {
|
|
return "equals string: " + Catch::toString( m_substr );
|
|
}
|
|
};
|
|
|
|
struct Contains : StringHolder<Contains> {
|
|
Contains( NSString* substr ) : StringHolder( substr ){}
|
|
|
|
virtual bool match( ExpressionType const& str ) const {
|
|
return (str != nil || m_substr == nil ) &&
|
|
[str rangeOfString |