|
|
|
|
|
|
|
|
/* |
|
|
/* |
|
|
* Catch v2.0.0-develop.6 |
|
|
|
|
|
* Generated: 2017-10-31 15:09:47.277913 |
|
|
|
|
|
|
|
|
* Catch v2.0.1 |
|
|
|
|
|
* Generated: 2017-11-03 11:53:39.642003 |
|
|
* ---------------------------------------------------------- |
|
|
* ---------------------------------------------------------- |
|
|
* This file has been merged from multiple headers. Please don't edit it directly |
|
|
* This file has been merged from multiple headers. Please don't edit it directly |
|
|
* Copyright (c) 2017 Two Blue Cubes Ltd. All rights reserved. |
|
|
* Copyright (c) 2017 Two Blue Cubes Ltd. All rights reserved. |
|
|
|
|
|
|
|
|
do{ if( !(condition) ) CATCH_ERROR( msg ); } while(false) |
|
|
do{ if( !(condition) ) CATCH_ERROR( msg ); } while(false) |
|
|
|
|
|
|
|
|
// end catch_enforce.h |
|
|
// end catch_enforce.h |
|
|
#include <cmath> |
|
|
|
|
|
|
|
|
|
|
|
#include <type_traits> |
|
|
#include <type_traits> |
|
|
|
|
|
|
|
|
namespace Catch { |
|
|
namespace Catch { |
|
|
namespace Detail { |
|
|
namespace Detail { |
|
|
|
|
|
|
|
|
double dmax(double lhs, double rhs); |
|
|
|
|
|
|
|
|
|
|
|
class Approx { |
|
|
class Approx { |
|
|
|
|
|
private: |
|
|
|
|
|
bool equalityComparisonImpl(double other) const; |
|
|
|
|
|
|
|
|
public: |
|
|
public: |
|
|
explicit Approx ( double value ); |
|
|
explicit Approx ( double value ); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> |
|
|
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> |
|
|
friend bool operator == ( const T& lhs, Approx const& rhs ) { |
|
|
friend bool operator == ( const T& lhs, Approx const& rhs ) { |
|
|
// Thanks to Richard Harris for his help refining this formula |
|
|
|
|
|
auto lhs_v = static_cast<double>(lhs); |
|
|
auto lhs_v = static_cast<double>(lhs); |
|
|
bool relativeOK = std::fabs(lhs_v - rhs.m_value) < rhs.m_epsilon * (rhs.m_scale + |
|
|
|
|
|
dmax(std::fabs(lhs_v), std::fabs(rhs.m_value))); |
|
|
|
|
|
if (relativeOK) { |
|
|
|
|
|
return true; |
|
|
|
|
|
} |
|
|
|
|
|
return std::fabs(lhs_v - rhs.m_value) <= rhs.m_margin; |
|
|
|
|
|
|
|
|
return rhs.equalityComparisonImpl(lhs_v); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> |
|
|
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> |
|
|
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> |
|
|
Approx& epsilon( T const& newEpsilon ) { |
|
|
Approx& epsilon( T const& newEpsilon ) { |
|
|
m_epsilon = static_cast<double>(newEpsilon); |
|
|
|
|
|
|
|
|
double epsilonAsDouble = static_cast<double>(newEpsilon); |
|
|
|
|
|
CATCH_ENFORCE(epsilonAsDouble >= 0 && epsilonAsDouble <= 1.0, |
|
|
|
|
|
"Invalid Approx::epsilon: " << epsilonAsDouble |
|
|
|
|
|
<< ", Approx::epsilon has to be between 0 and 1"); |
|
|
|
|
|
m_epsilon = epsilonAsDouble; |
|
|
return *this; |
|
|
return *this; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> |
|
|
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> |
|
|
Approx& margin( T const& newMargin ) { |
|
|
Approx& margin( T const& newMargin ) { |
|
|
m_margin = static_cast<double>(newMargin); |
|
|
|
|
|
CATCH_ENFORCE(m_margin >= 0, "Invalid Approx::margin: " << m_margin << ", Approx::Margin has to be non-negative."); |
|
|
|
|
|
|
|
|
double marginAsDouble = static_cast<double>(newMargin); |
|
|
|
|
|
CATCH_ENFORCE(marginAsDouble >= 0, |
|
|
|
|
|
"Invalid Approx::margin: " << marginAsDouble |
|
|
|
|
|
<< ", Approx::Margin has to be non-negative."); |
|
|
|
|
|
m_margin = marginAsDouble; |
|
|
return *this; |
|
|
return *this; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Cpp files will be included in the single-header file here |
|
|
// Cpp files will be included in the single-header file here |
|
|
// start catch_approx.cpp |
|
|
// start catch_approx.cpp |
|
|
|
|
|
|
|
|
|
|
|
#include <cmath> |
|
|
#include <limits> |
|
|
#include <limits> |
|
|
|
|
|
|
|
|
|
|
|
namespace { |
|
|
|
|
|
|
|
|
|
|
|
// Performs equivalent check of std::fabs(lhs - rhs) <= margin |
|
|
|
|
|
// But without the subtraction to allow for INFINITY in comparison |
|
|
|
|
|
bool marginComparison(double lhs, double rhs, double margin) { |
|
|
|
|
|
return (lhs + margin >= rhs) && (rhs + margin >= lhs); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
namespace Catch { |
|
|
namespace Catch { |
|
|
namespace Detail { |
|
|
namespace Detail { |
|
|
|
|
|
|
|
|
double dmax(double lhs, double rhs) { |
|
|
|
|
|
if (lhs < rhs) { |
|
|
|
|
|
return rhs; |
|
|
|
|
|
} |
|
|
|
|
|
return lhs; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Approx::Approx ( double value ) |
|
|
Approx::Approx ( double value ) |
|
|
: m_epsilon( std::numeric_limits<float>::epsilon()*100 ), |
|
|
: m_epsilon( std::numeric_limits<float>::epsilon()*100 ), |
|
|
m_margin( 0.0 ), |
|
|
m_margin( 0.0 ), |
|
|
m_scale( 1.0 ), |
|
|
|
|
|
|
|
|
m_scale( 0.0 ), |
|
|
m_value( value ) |
|
|
m_value( value ) |
|
|
{} |
|
|
{} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return oss.str(); |
|
|
return oss.str(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool Approx::equalityComparisonImpl(const double other) const { |
|
|
|
|
|
// First try with fixed margin, then compute margin based on epsilon, scale and Approx's value |
|
|
|
|
|
// Thanks to Richard Harris for his help refining the scaled margin value |
|
|
|
|
|
return marginComparison(m_value, other, m_margin) || marginComparison(m_value, other, m_epsilon * (m_scale + std::fabs(m_value))); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
} // end namespace Detail |
|
|
} // end namespace Detail |
|
|
|
|
|
|
|
|
std::string StringMaker<Catch::Detail::Approx>::convert(Catch::Detail::Approx const& value) { |
|
|
std::string StringMaker<Catch::Detail::Approx>::convert(Catch::Detail::Approx const& value) { |
|
|
|
|
|
|
|
|
clara::Parser m_cli; |
|
|
clara::Parser m_cli; |
|
|
ConfigData m_configData; |
|
|
ConfigData m_configData; |
|
|
std::shared_ptr<Config> m_config; |
|
|
std::shared_ptr<Config> m_config; |
|
|
|
|
|
bool m_startupExceptions = false; |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
} // end namespace Catch |
|
|
} // end namespace Catch |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Session::Session() { |
|
|
Session::Session() { |
|
|
static bool alreadyInstantiated = false; |
|
|
static bool alreadyInstantiated = false; |
|
|
if( alreadyInstantiated ) |
|
|
|
|
|
CATCH_INTERNAL_ERROR( "Only one instance of Catch::Session can ever be used" ); |
|
|
|
|
|
|
|
|
if( alreadyInstantiated ) { |
|
|
|
|
|
try { CATCH_INTERNAL_ERROR( "Only one instance of Catch::Session can ever be used" ); } |
|
|
|
|
|
catch(...) { getMutableRegistryHub().registerStartupException(); } |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const auto& exceptions = getRegistryHub().getStartupExceptionRegistry().getExceptions(); |
|
|
|
|
|
if ( !exceptions.empty() ) { |
|
|
|
|
|
m_startupExceptions = true; |
|
|
|
|
|
Colour colourGuard( Colour::Red ); |
|
|
|
|
|
Catch::cerr() << "Errors occured during startup!" << '\n'; |
|
|
|
|
|
// iterate over all exceptions and notify user |
|
|
|
|
|
for ( const auto& ex_ptr : exceptions ) { |
|
|
|
|
|
try { |
|
|
|
|
|
std::rethrow_exception(ex_ptr); |
|
|
|
|
|
} catch ( std::exception const& ex ) { |
|
|
|
|
|
Catch::cerr() << Column( ex.what() ).indent(2) << '\n'; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
alreadyInstantiated = true; |
|
|
alreadyInstantiated = true; |
|
|
m_cli = makeCommandLineParser( m_configData ); |
|
|
m_cli = makeCommandLineParser( m_configData ); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
int Session::applyCommandLine( int argc, char* argv[] ) { |
|
|
int Session::applyCommandLine( int argc, char* argv[] ) { |
|
|
|
|
|
if( m_startupExceptions ) |
|
|
|
|
|
return 1; |
|
|
|
|
|
|
|
|
auto result = m_cli.parse( clara::Args( argc, argv ) ); |
|
|
auto result = m_cli.parse( clara::Args( argc, argv ) ); |
|
|
if( !result ) { |
|
|
if( !result ) { |
|
|
Catch::cerr() |
|
|
Catch::cerr() |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
int Session::run( int argc, char* argv[] ) { |
|
|
int Session::run( int argc, char* argv[] ) { |
|
|
const auto& exceptions = getRegistryHub().getStartupExceptionRegistry().getExceptions(); |
|
|
|
|
|
if ( !exceptions.empty() ) { |
|
|
|
|
|
Catch::cerr() << "Errors occured during startup!" << '\n'; |
|
|
|
|
|
// iterate over all exceptions and notify user |
|
|
|
|
|
for ( const auto& ex_ptr : exceptions ) { |
|
|
|
|
|
try { |
|
|
|
|
|
std::rethrow_exception(ex_ptr); |
|
|
|
|
|
} catch ( std::exception const& ex ) { |
|
|
|
|
|
Catch::cerr() << ex.what() << '\n'; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if( m_startupExceptions ) |
|
|
return 1; |
|
|
return 1; |
|
|
} |
|
|
|
|
|
int returnCode = applyCommandLine( argc, argv ); |
|
|
int returnCode = applyCommandLine( argc, argv ); |
|
|
if( returnCode == 0 ) |
|
|
if( returnCode == 0 ) |
|
|
returnCode = run(); |
|
|
returnCode = run(); |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
int Session::runInternal() { |
|
|
int Session::runInternal() { |
|
|
|
|
|
if( m_startupExceptions ) |
|
|
|
|
|
return 1; |
|
|
|
|
|
|
|
|
if( m_configData.showHelp || m_configData.libIdentify ) |
|
|
if( m_configData.showHelp || m_configData.libIdentify ) |
|
|
return 0; |
|
|
return 0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
Version const& libraryVersion() { |
|
|
Version const& libraryVersion() { |
|
|
static Version version( 2, 0, 0, "develop", 6 ); |
|
|
|
|
|
|
|
|
static Version version( 2, 0, 1, "", 0 ); |
|
|
return version; |
|
|
return version; |
|
|
} |
|
|
} |
|
|
|
|
|
|