mirror of
https://github.com/catchorg/Catch2.git
synced 2025-01-15 22:58:02 +00:00
Compare commits
7 Commits
ab0ca2f566
...
a25d83d8c4
Author | SHA1 | Date | |
---|---|---|---|
|
a25d83d8c4 | ||
|
f7d7aa9eb2 | ||
|
ca5af2e85b | ||
|
904c47a634 | ||
|
afc8b28c07 | ||
|
a6baa6dda6 | ||
|
5c9367d4f1 |
@ -10,7 +10,6 @@
|
||||
|
||||
namespace Catch {
|
||||
namespace Matchers {
|
||||
namespace Exception {
|
||||
|
||||
bool ExceptionMessageMatcher::match(std::exception const& ex) const {
|
||||
return ex.what() == m_message;
|
||||
@ -20,11 +19,9 @@ std::string ExceptionMessageMatcher::describe() const {
|
||||
return "exception message matches \"" + m_message + "\"";
|
||||
}
|
||||
|
||||
}
|
||||
Exception::ExceptionMessageMatcher Message(std::string const& message) {
|
||||
return Exception::ExceptionMessageMatcher(message);
|
||||
ExceptionMessageMatcher Message(std::string const& message) {
|
||||
return ExceptionMessageMatcher(message);
|
||||
}
|
||||
|
||||
// namespace Exception
|
||||
} // namespace Matchers
|
||||
} // namespace Catch
|
||||
|
@ -11,7 +11,6 @@
|
||||
|
||||
namespace Catch {
|
||||
namespace Matchers {
|
||||
namespace Exception {
|
||||
|
||||
class ExceptionMessageMatcher final : public MatcherBase<std::exception> {
|
||||
std::string m_message;
|
||||
@ -26,9 +25,8 @@ public:
|
||||
std::string describe() const override;
|
||||
};
|
||||
|
||||
} // namespace Exception
|
||||
|
||||
Exception::ExceptionMessageMatcher Message(std::string const& message);
|
||||
//! Creates a matcher that checks whether a std derived exception has the provided message
|
||||
ExceptionMessageMatcher Message(std::string const& message);
|
||||
|
||||
} // namespace Matchers
|
||||
} // namespace Catch
|
||||
|
@ -99,13 +99,15 @@ void write(std::ostream& out, FloatingPoint num) {
|
||||
} // end anonymous namespace
|
||||
|
||||
namespace Matchers {
|
||||
namespace Floating {
|
||||
namespace Detail {
|
||||
|
||||
enum class FloatingPointKind : uint8_t {
|
||||
Float,
|
||||
Double
|
||||
};
|
||||
|
||||
} // end namespace Detail
|
||||
|
||||
|
||||
WithinAbsMatcher::WithinAbsMatcher(double target, double margin)
|
||||
:m_target{ target }, m_margin{ margin } {
|
||||
@ -124,9 +126,9 @@ namespace Floating {
|
||||
}
|
||||
|
||||
|
||||
WithinUlpsMatcher::WithinUlpsMatcher(double target, uint64_t ulps, FloatingPointKind baseType)
|
||||
WithinUlpsMatcher::WithinUlpsMatcher(double target, uint64_t ulps, Detail::FloatingPointKind baseType)
|
||||
:m_target{ target }, m_ulps{ ulps }, m_type{ baseType } {
|
||||
CATCH_ENFORCE(m_type == FloatingPointKind::Double
|
||||
CATCH_ENFORCE(m_type == Detail::FloatingPointKind::Double
|
||||
|| m_ulps < (std::numeric_limits<uint32_t>::max)(),
|
||||
"Provided ULP is impossibly large for a float comparison.");
|
||||
}
|
||||
@ -139,12 +141,12 @@ namespace Floating {
|
||||
|
||||
bool WithinUlpsMatcher::match(double const& matchee) const {
|
||||
switch (m_type) {
|
||||
case FloatingPointKind::Float:
|
||||
case Detail::FloatingPointKind::Float:
|
||||
return almostEqualUlps<float>(static_cast<float>(matchee), static_cast<float>(m_target), m_ulps);
|
||||
case FloatingPointKind::Double:
|
||||
case Detail::FloatingPointKind::Double:
|
||||
return almostEqualUlps<double>(matchee, m_target, m_ulps);
|
||||
default:
|
||||
CATCH_INTERNAL_ERROR( "Unknown FloatingPointKind value" );
|
||||
CATCH_INTERNAL_ERROR( "Unknown Detail::FloatingPointKind value" );
|
||||
}
|
||||
}
|
||||
|
||||
@ -157,7 +159,7 @@ namespace Floating {
|
||||
|
||||
ret << "is within " << m_ulps << " ULPs of ";
|
||||
|
||||
if (m_type == FloatingPointKind::Float) {
|
||||
if (m_type == Detail::FloatingPointKind::Float) {
|
||||
write(ret, static_cast<float>(m_target));
|
||||
ret << 'f';
|
||||
} else {
|
||||
@ -165,7 +167,7 @@ namespace Floating {
|
||||
}
|
||||
|
||||
ret << " ([";
|
||||
if (m_type == FloatingPointKind::Double) {
|
||||
if (m_type == Detail::FloatingPointKind::Double) {
|
||||
write(ret, step(m_target, static_cast<double>(-INFINITY), m_ulps));
|
||||
ret << ", ";
|
||||
write(ret, step(m_target, static_cast<double>( INFINITY), m_ulps));
|
||||
@ -199,39 +201,35 @@ namespace Floating {
|
||||
return sstr.str();
|
||||
}
|
||||
|
||||
}// namespace Floating
|
||||
|
||||
|
||||
|
||||
Floating::WithinUlpsMatcher WithinULP(double target, uint64_t maxUlpDiff) {
|
||||
return Floating::WithinUlpsMatcher(target, maxUlpDiff, Floating::FloatingPointKind::Double);
|
||||
WithinUlpsMatcher WithinULP(double target, uint64_t maxUlpDiff) {
|
||||
return WithinUlpsMatcher(target, maxUlpDiff, Detail::FloatingPointKind::Double);
|
||||
}
|
||||
|
||||
Floating::WithinUlpsMatcher WithinULP(float target, uint64_t maxUlpDiff) {
|
||||
return Floating::WithinUlpsMatcher(target, maxUlpDiff, Floating::FloatingPointKind::Float);
|
||||
WithinUlpsMatcher WithinULP(float target, uint64_t maxUlpDiff) {
|
||||
return WithinUlpsMatcher(target, maxUlpDiff, Detail::FloatingPointKind::Float);
|
||||
}
|
||||
|
||||
Floating::WithinAbsMatcher WithinAbs(double target, double margin) {
|
||||
return Floating::WithinAbsMatcher(target, margin);
|
||||
WithinAbsMatcher WithinAbs(double target, double margin) {
|
||||
return WithinAbsMatcher(target, margin);
|
||||
}
|
||||
|
||||
Floating::WithinRelMatcher WithinRel(double target, double eps) {
|
||||
return Floating::WithinRelMatcher(target, eps);
|
||||
WithinRelMatcher WithinRel(double target, double eps) {
|
||||
return WithinRelMatcher(target, eps);
|
||||
}
|
||||
|
||||
Floating::WithinRelMatcher WithinRel(double target) {
|
||||
return Floating::WithinRelMatcher(target, std::numeric_limits<double>::epsilon() * 100);
|
||||
WithinRelMatcher WithinRel(double target) {
|
||||
return WithinRelMatcher(target, std::numeric_limits<double>::epsilon() * 100);
|
||||
}
|
||||
|
||||
Floating::WithinRelMatcher WithinRel(float target, float eps) {
|
||||
return Floating::WithinRelMatcher(target, eps);
|
||||
WithinRelMatcher WithinRel(float target, float eps) {
|
||||
return WithinRelMatcher(target, eps);
|
||||
}
|
||||
|
||||
Floating::WithinRelMatcher WithinRel(float target) {
|
||||
return Floating::WithinRelMatcher(target, std::numeric_limits<float>::epsilon() * 100);
|
||||
WithinRelMatcher WithinRel(float target) {
|
||||
return WithinRelMatcher(target, std::numeric_limits<float>::epsilon() * 100);
|
||||
}
|
||||
|
||||
|
||||
} // namespace Matchers
|
||||
} // namespace Catch
|
||||
|
||||
|
@ -12,57 +12,59 @@
|
||||
namespace Catch {
|
||||
namespace Matchers {
|
||||
|
||||
namespace Floating {
|
||||
|
||||
namespace Detail {
|
||||
enum class FloatingPointKind : uint8_t;
|
||||
}
|
||||
|
||||
struct WithinAbsMatcher final : MatcherBase<double> {
|
||||
WithinAbsMatcher(double target, double margin);
|
||||
bool match(double const& matchee) const override;
|
||||
std::string describe() const override;
|
||||
private:
|
||||
double m_target;
|
||||
double m_margin;
|
||||
};
|
||||
struct WithinAbsMatcher final : MatcherBase<double> {
|
||||
WithinAbsMatcher(double target, double margin);
|
||||
bool match(double const& matchee) const override;
|
||||
std::string describe() const override;
|
||||
private:
|
||||
double m_target;
|
||||
double m_margin;
|
||||
};
|
||||
|
||||
struct WithinUlpsMatcher final : MatcherBase<double> {
|
||||
WithinUlpsMatcher(double target, uint64_t ulps, FloatingPointKind baseType);
|
||||
bool match(double const& matchee) const override;
|
||||
std::string describe() const override;
|
||||
private:
|
||||
double m_target;
|
||||
uint64_t m_ulps;
|
||||
FloatingPointKind m_type;
|
||||
};
|
||||
struct WithinUlpsMatcher final : MatcherBase<double> {
|
||||
WithinUlpsMatcher(double target, uint64_t ulps, Detail::FloatingPointKind baseType);
|
||||
bool match(double const& matchee) const override;
|
||||
std::string describe() const override;
|
||||
private:
|
||||
double m_target;
|
||||
uint64_t m_ulps;
|
||||
Detail::FloatingPointKind m_type;
|
||||
};
|
||||
|
||||
// Given IEEE-754 format for floats and doubles, we can assume
|
||||
// that float -> double promotion is lossless. Given this, we can
|
||||
// assume that if we do the standard relative comparison of
|
||||
// |lhs - rhs| <= epsilon * max(fabs(lhs), fabs(rhs)), then we get
|
||||
// the same result if we do this for floats, as if we do this for
|
||||
// doubles that were promoted from floats.
|
||||
struct WithinRelMatcher final : MatcherBase<double> {
|
||||
WithinRelMatcher(double target, double epsilon);
|
||||
bool match(double const& matchee) const override;
|
||||
std::string describe() const override;
|
||||
private:
|
||||
double m_target;
|
||||
double m_epsilon;
|
||||
};
|
||||
// Given IEEE-754 format for floats and doubles, we can assume
|
||||
// that float -> double promotion is lossless. Given this, we can
|
||||
// assume that if we do the standard relative comparison of
|
||||
// |lhs - rhs| <= epsilon * max(fabs(lhs), fabs(rhs)), then we get
|
||||
// the same result if we do this for floats, as if we do this for
|
||||
// doubles that were promoted from floats.
|
||||
struct WithinRelMatcher final : MatcherBase<double> {
|
||||
WithinRelMatcher(double target, double epsilon);
|
||||
bool match(double const& matchee) const override;
|
||||
std::string describe() const override;
|
||||
private:
|
||||
double m_target;
|
||||
double m_epsilon;
|
||||
};
|
||||
|
||||
} // namespace Floating
|
||||
//! Creates a matcher that accepts doubles within certain ULP range of target
|
||||
WithinUlpsMatcher WithinULP(double target, uint64_t maxUlpDiff);
|
||||
//! Creates a matcher that accepts floats within certain ULP range of target
|
||||
WithinUlpsMatcher WithinULP(float target, uint64_t maxUlpDiff);
|
||||
//! Creates a matcher that accepts numbers within certain range of target
|
||||
WithinAbsMatcher WithinAbs(double target, double margin);
|
||||
|
||||
// The following functions create the actual matcher objects.
|
||||
// This allows the types to be inferred
|
||||
Floating::WithinUlpsMatcher WithinULP(double target, uint64_t maxUlpDiff);
|
||||
Floating::WithinUlpsMatcher WithinULP(float target, uint64_t maxUlpDiff);
|
||||
Floating::WithinAbsMatcher WithinAbs(double target, double margin);
|
||||
Floating::WithinRelMatcher WithinRel(double target, double eps);
|
||||
// defaults epsilon to 100*numeric_limits<double>::epsilon()
|
||||
Floating::WithinRelMatcher WithinRel(double target);
|
||||
Floating::WithinRelMatcher WithinRel(float target, float eps);
|
||||
// defaults epsilon to 100*numeric_limits<float>::epsilon()
|
||||
Floating::WithinRelMatcher WithinRel(float target);
|
||||
//! Creates a matcher that accepts doubles within certain relative range of target
|
||||
WithinRelMatcher WithinRel(double target, double eps);
|
||||
//! Creates a matcher that accepts doubles within 100*DBL_EPS relative range of target
|
||||
WithinRelMatcher WithinRel(double target);
|
||||
//! Creates a matcher that accepts doubles within certain relative range of target
|
||||
WithinRelMatcher WithinRel(float target, float eps);
|
||||
//! Creates a matcher that accepts floats within 100*FLT_EPS relative range of target
|
||||
WithinRelMatcher WithinRel(float target);
|
||||
|
||||
} // namespace Matchers
|
||||
} // namespace Catch
|
||||
|
@ -1,6 +1,6 @@
|
||||
#include <catch2/matchers/catch_matchers_predicate.hpp>
|
||||
|
||||
std::string Catch::Matchers::Generic::Detail::finalizeDescription(const std::string& desc) {
|
||||
std::string Catch::Matchers::Detail::finalizeDescription(const std::string& desc) {
|
||||
if (desc.empty()) {
|
||||
return "matches undescribed predicate";
|
||||
} else {
|
||||
|
@ -16,11 +16,10 @@
|
||||
|
||||
namespace Catch {
|
||||
namespace Matchers {
|
||||
namespace Generic {
|
||||
|
||||
namespace Detail {
|
||||
std::string finalizeDescription(const std::string& desc);
|
||||
}
|
||||
} // namespace Detail
|
||||
|
||||
template <typename T, typename Predicate>
|
||||
class PredicateMatcher final : public MatcherBase<T> {
|
||||
@ -42,17 +41,16 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Generic
|
||||
|
||||
// The following functions create the actual matcher objects.
|
||||
// The user has to explicitly specify type to the function, because
|
||||
// inferring std::function<bool(T const&)> is hard (but possible) and
|
||||
// requires a lot of TMP.
|
||||
/**
|
||||
* Creates a matcher that calls delegates `match` to the provided predicate.
|
||||
*
|
||||
* The user has to explicitly specify the argument type to the matcher
|
||||
*/
|
||||
template<typename T, typename Pred>
|
||||
Generic::PredicateMatcher<T, Pred> Predicate(Pred&& predicate, std::string const& description = "") {
|
||||
PredicateMatcher<T, Pred> Predicate(Pred&& predicate, std::string const& description = "") {
|
||||
static_assert(is_callable<Pred(T)>::value, "Predicate not callable with argument T");
|
||||
static_assert(std::is_same<bool, FunctionReturnType<Pred, T>>::value, "Predicate does not return bool");
|
||||
return Generic::PredicateMatcher<T, Pred>(std::forward<Pred>(predicate), description);
|
||||
return PredicateMatcher<T, Pred>(std::forward<Pred>(predicate), description);
|
||||
}
|
||||
|
||||
} // namespace Matchers
|
||||
|
@ -12,103 +12,99 @@
|
||||
namespace Catch {
|
||||
namespace Matchers {
|
||||
|
||||
namespace StdString {
|
||||
|
||||
CasedString::CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity )
|
||||
: m_caseSensitivity( caseSensitivity ),
|
||||
m_str( adjustString( str ) )
|
||||
{}
|
||||
std::string CasedString::adjustString( std::string const& str ) const {
|
||||
return m_caseSensitivity == CaseSensitive::No
|
||||
? toLower( str )
|
||||
: str;
|
||||
}
|
||||
std::string CasedString::caseSensitivitySuffix() const {
|
||||
return m_caseSensitivity == CaseSensitive::No
|
||||
? " (case insensitive)"
|
||||
: std::string();
|
||||
}
|
||||
|
||||
|
||||
StringMatcherBase::StringMatcherBase( std::string const& operation, CasedString const& comparator )
|
||||
: m_comparator( comparator ),
|
||||
m_operation( operation ) {
|
||||
}
|
||||
|
||||
std::string StringMatcherBase::describe() const {
|
||||
std::string description;
|
||||
description.reserve(5 + m_operation.size() + m_comparator.m_str.size() +
|
||||
m_comparator.caseSensitivitySuffix().size());
|
||||
description += m_operation;
|
||||
description += ": \"";
|
||||
description += m_comparator.m_str;
|
||||
description += "\"";
|
||||
description += m_comparator.caseSensitivitySuffix();
|
||||
return description;
|
||||
}
|
||||
|
||||
EqualsMatcher::EqualsMatcher( CasedString const& comparator ) : StringMatcherBase( "equals", comparator ) {}
|
||||
|
||||
bool EqualsMatcher::match( std::string const& source ) const {
|
||||
return m_comparator.adjustString( source ) == m_comparator.m_str;
|
||||
}
|
||||
|
||||
|
||||
ContainsMatcher::ContainsMatcher( CasedString const& comparator ) : StringMatcherBase( "contains", comparator ) {}
|
||||
|
||||
bool ContainsMatcher::match( std::string const& source ) const {
|
||||
return contains( m_comparator.adjustString( source ), m_comparator.m_str );
|
||||
}
|
||||
|
||||
|
||||
StartsWithMatcher::StartsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "starts with", comparator ) {}
|
||||
|
||||
bool StartsWithMatcher::match( std::string const& source ) const {
|
||||
return startsWith( m_comparator.adjustString( source ), m_comparator.m_str );
|
||||
}
|
||||
|
||||
|
||||
EndsWithMatcher::EndsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "ends with", comparator ) {}
|
||||
|
||||
bool EndsWithMatcher::match( std::string const& source ) const {
|
||||
return endsWith( m_comparator.adjustString( source ), m_comparator.m_str );
|
||||
}
|
||||
|
||||
|
||||
|
||||
RegexMatcher::RegexMatcher(std::string regex, CaseSensitive::Choice caseSensitivity): m_regex(std::move(regex)), m_caseSensitivity(caseSensitivity) {}
|
||||
|
||||
bool RegexMatcher::match(std::string const& matchee) const {
|
||||
auto flags = std::regex::ECMAScript; // ECMAScript is the default syntax option anyway
|
||||
if (m_caseSensitivity == CaseSensitive::Choice::No) {
|
||||
flags |= std::regex::icase;
|
||||
}
|
||||
auto reg = std::regex(m_regex, flags);
|
||||
return std::regex_match(matchee, reg);
|
||||
}
|
||||
|
||||
std::string RegexMatcher::describe() const {
|
||||
return "matches " + ::Catch::Detail::stringify(m_regex) + ((m_caseSensitivity == CaseSensitive::Choice::Yes)? " case sensitively" : " case insensitively");
|
||||
}
|
||||
|
||||
} // namespace StdString
|
||||
|
||||
|
||||
StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity ) {
|
||||
return StdString::EqualsMatcher( StdString::CasedString( str, caseSensitivity) );
|
||||
CasedString::CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity )
|
||||
: m_caseSensitivity( caseSensitivity ),
|
||||
m_str( adjustString( str ) )
|
||||
{}
|
||||
std::string CasedString::adjustString( std::string const& str ) const {
|
||||
return m_caseSensitivity == CaseSensitive::No
|
||||
? toLower( str )
|
||||
: str;
|
||||
}
|
||||
StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity ) {
|
||||
return StdString::ContainsMatcher( StdString::CasedString( str, caseSensitivity) );
|
||||
}
|
||||
StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity ) {
|
||||
return StdString::EndsWithMatcher( StdString::CasedString( str, caseSensitivity) );
|
||||
}
|
||||
StdString::StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity ) {
|
||||
return StdString::StartsWithMatcher( StdString::CasedString( str, caseSensitivity) );
|
||||
std::string CasedString::caseSensitivitySuffix() const {
|
||||
return m_caseSensitivity == CaseSensitive::No
|
||||
? " (case insensitive)"
|
||||
: std::string();
|
||||
}
|
||||
|
||||
StdString::RegexMatcher Matches(std::string const& regex, CaseSensitive::Choice caseSensitivity) {
|
||||
return StdString::RegexMatcher(regex, caseSensitivity);
|
||||
|
||||
StringMatcherBase::StringMatcherBase( std::string const& operation, CasedString const& comparator )
|
||||
: m_comparator( comparator ),
|
||||
m_operation( operation ) {
|
||||
}
|
||||
|
||||
std::string StringMatcherBase::describe() const {
|
||||
std::string description;
|
||||
description.reserve(5 + m_operation.size() + m_comparator.m_str.size() +
|
||||
m_comparator.caseSensitivitySuffix().size());
|
||||
description += m_operation;
|
||||
description += ": \"";
|
||||
description += m_comparator.m_str;
|
||||
description += "\"";
|
||||
description += m_comparator.caseSensitivitySuffix();
|
||||
return description;
|
||||
}
|
||||
|
||||
StringEqualsMatcher::StringEqualsMatcher( CasedString const& comparator ) : StringMatcherBase( "equals", comparator ) {}
|
||||
|
||||
bool StringEqualsMatcher::match( std::string const& source ) const {
|
||||
return m_comparator.adjustString( source ) == m_comparator.m_str;
|
||||
}
|
||||
|
||||
|
||||
StringContainsMatcher::StringContainsMatcher( CasedString const& comparator ) : StringMatcherBase( "contains", comparator ) {}
|
||||
|
||||
bool StringContainsMatcher::match( std::string const& source ) const {
|
||||
return contains( m_comparator.adjustString( source ), m_comparator.m_str );
|
||||
}
|
||||
|
||||
|
||||
StartsWithMatcher::StartsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "starts with", comparator ) {}
|
||||
|
||||
bool StartsWithMatcher::match( std::string const& source ) const {
|
||||
return startsWith( m_comparator.adjustString( source ), m_comparator.m_str );
|
||||
}
|
||||
|
||||
|
||||
EndsWithMatcher::EndsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "ends with", comparator ) {}
|
||||
|
||||
bool EndsWithMatcher::match( std::string const& source ) const {
|
||||
return endsWith( m_comparator.adjustString( source ), m_comparator.m_str );
|
||||
}
|
||||
|
||||
|
||||
|
||||
RegexMatcher::RegexMatcher(std::string regex, CaseSensitive::Choice caseSensitivity): m_regex(std::move(regex)), m_caseSensitivity(caseSensitivity) {}
|
||||
|
||||
bool RegexMatcher::match(std::string const& matchee) const {
|
||||
auto flags = std::regex::ECMAScript; // ECMAScript is the default syntax option anyway
|
||||
if (m_caseSensitivity == CaseSensitive::Choice::No) {
|
||||
flags |= std::regex::icase;
|
||||
}
|
||||
auto reg = std::regex(m_regex, flags);
|
||||
return std::regex_match(matchee, reg);
|
||||
}
|
||||
|
||||
std::string RegexMatcher::describe() const {
|
||||
return "matches " + ::Catch::Detail::stringify(m_regex) + ((m_caseSensitivity == CaseSensitive::Choice::Yes)? " case sensitively" : " case insensitively");
|
||||
}
|
||||
|
||||
|
||||
StringEqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity ) {
|
||||
return StringEqualsMatcher( CasedString( str, caseSensitivity) );
|
||||
}
|
||||
StringContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity ) {
|
||||
return StringContainsMatcher( CasedString( str, caseSensitivity) );
|
||||
}
|
||||
EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity ) {
|
||||
return EndsWithMatcher( CasedString( str, caseSensitivity) );
|
||||
}
|
||||
StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity ) {
|
||||
return StartsWithMatcher( CasedString( str, caseSensitivity) );
|
||||
}
|
||||
|
||||
RegexMatcher Matches(std::string const& regex, CaseSensitive::Choice caseSensitivity) {
|
||||
return RegexMatcher(regex, caseSensitivity);
|
||||
}
|
||||
|
||||
} // namespace Matchers
|
||||
|
@ -15,64 +15,60 @@
|
||||
namespace Catch {
|
||||
namespace Matchers {
|
||||
|
||||
namespace StdString {
|
||||
struct CasedString {
|
||||
CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity );
|
||||
std::string adjustString( std::string const& str ) const;
|
||||
std::string caseSensitivitySuffix() const;
|
||||
|
||||
struct CasedString
|
||||
{
|
||||
CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity );
|
||||
std::string adjustString( std::string const& str ) const;
|
||||
std::string caseSensitivitySuffix() const;
|
||||
CaseSensitive::Choice m_caseSensitivity;
|
||||
std::string m_str;
|
||||
};
|
||||
|
||||
CaseSensitive::Choice m_caseSensitivity;
|
||||
std::string m_str;
|
||||
};
|
||||
struct StringMatcherBase : MatcherBase<std::string> {
|
||||
StringMatcherBase( std::string const& operation, CasedString const& comparator );
|
||||
std::string describe() const override;
|
||||
|
||||
struct StringMatcherBase : MatcherBase<std::string> {
|
||||
StringMatcherBase( std::string const& operation, CasedString const& comparator );
|
||||
std::string describe() const override;
|
||||
CasedString m_comparator;
|
||||
std::string m_operation;
|
||||
};
|
||||
|
||||
CasedString m_comparator;
|
||||
std::string m_operation;
|
||||
};
|
||||
struct StringEqualsMatcher final : StringMatcherBase {
|
||||
StringEqualsMatcher( CasedString const& comparator );
|
||||
bool match( std::string const& source ) const override;
|
||||
};
|
||||
struct StringContainsMatcher final : StringMatcherBase {
|
||||
StringContainsMatcher( CasedString const& comparator );
|
||||
bool match( std::string const& source ) const override;
|
||||
};
|
||||
struct StartsWithMatcher final : StringMatcherBase {
|
||||
StartsWithMatcher( CasedString const& comparator );
|
||||
bool match( std::string const& source ) const override;
|
||||
};
|
||||
struct EndsWithMatcher final : StringMatcherBase {
|
||||
EndsWithMatcher( CasedString const& comparator );
|
||||
bool match( std::string const& source ) const override;
|
||||
};
|
||||
|
||||
struct EqualsMatcher final : StringMatcherBase {
|
||||
EqualsMatcher( CasedString const& comparator );
|
||||
bool match( std::string const& source ) const override;
|
||||
};
|
||||
struct ContainsMatcher final : StringMatcherBase {
|
||||
ContainsMatcher( CasedString const& comparator );
|
||||
bool match( std::string const& source ) const override;
|
||||
};
|
||||
struct StartsWithMatcher final : StringMatcherBase {
|
||||
StartsWithMatcher( CasedString const& comparator );
|
||||
bool match( std::string const& source ) const override;
|
||||
};
|
||||
struct EndsWithMatcher final : StringMatcherBase {
|
||||
EndsWithMatcher( CasedString const& comparator );
|
||||
bool match( std::string const& source ) const override;
|
||||
};
|
||||
struct RegexMatcher final : MatcherBase<std::string> {
|
||||
RegexMatcher( std::string regex, CaseSensitive::Choice caseSensitivity );
|
||||
bool match( std::string const& matchee ) const override;
|
||||
std::string describe() const override;
|
||||
|
||||
struct RegexMatcher final : MatcherBase<std::string> {
|
||||
RegexMatcher( std::string regex, CaseSensitive::Choice caseSensitivity );
|
||||
bool match( std::string const& matchee ) const override;
|
||||
std::string describe() const override;
|
||||
private:
|
||||
std::string m_regex;
|
||||
CaseSensitive::Choice m_caseSensitivity;
|
||||
};
|
||||
|
||||
private:
|
||||
std::string m_regex;
|
||||
CaseSensitive::Choice m_caseSensitivity;
|
||||
};
|
||||
|
||||
} // namespace StdString
|
||||
|
||||
|
||||
// The following functions create the actual matcher objects.
|
||||
// This allows the types to be inferred
|
||||
|
||||
StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
|
||||
StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
|
||||
StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
|
||||
StdString::StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
|
||||
StdString::RegexMatcher Matches( std::string const& regex, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
|
||||
//! Creates matcher that accepts strings that are exactly equal to `str`
|
||||
StringEqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
|
||||
//! Creates matcher that accepts strings that contain `str`
|
||||
StringContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
|
||||
//! Creates matcher that accepts strings that _end_ with `str`
|
||||
EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
|
||||
//! Creates matcher that accepts strings that _start_ with `str`
|
||||
StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
|
||||
//! Creates matcher that accepts strings matching `regex`
|
||||
RegexMatcher Matches( std::string const& regex, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
|
||||
|
||||
} // namespace Matchers
|
||||
} // namespace Catch
|
||||
|
@ -41,7 +41,7 @@ namespace Matchers {
|
||||
|
||||
template<std::size_t N>
|
||||
std::array<void const*, N+1> array_cat(void const* lhs, std::array<void const*, N> && rhs) {
|
||||
std::array<void const*, N+1> arr{lhs};
|
||||
std::array<void const*, N + 1> arr{ {lhs} };
|
||||
std::copy_n(rhs.begin(), N, arr.begin() + 1);
|
||||
return arr;
|
||||
}
|
||||
@ -129,6 +129,33 @@ namespace Matchers {
|
||||
}
|
||||
|
||||
std::array<void const*, sizeof...(MatcherTs)> m_matchers;
|
||||
|
||||
//! Avoids type nesting for `GenericAllOf && GenericAllOf` case
|
||||
template<typename... MatchersRHS>
|
||||
friend
|
||||
MatchAllOfGeneric<MatcherTs..., MatchersRHS...> operator && (
|
||||
MatchAllOfGeneric<MatcherTs...>&& lhs,
|
||||
MatchAllOfGeneric<MatchersRHS...>&& rhs) {
|
||||
return MatchAllOfGeneric<MatcherTs..., MatchersRHS...>{array_cat(std::move(lhs.m_matchers), std::move(rhs.m_matchers))};
|
||||
}
|
||||
|
||||
//! Avoids type nesting for `GenericAllOf && some matcher` case
|
||||
template<typename MatcherRHS>
|
||||
friend std::enable_if_t<is_matcher<MatcherRHS>::value,
|
||||
MatchAllOfGeneric<MatcherTs..., MatcherRHS>> operator && (
|
||||
MatchAllOfGeneric<MatcherTs...>&& lhs,
|
||||
MatcherRHS const& rhs) {
|
||||
return MatchAllOfGeneric<MatcherTs..., MatcherRHS>{array_cat(std::move(lhs.m_matchers), static_cast<void const*>(&rhs))};
|
||||
}
|
||||
|
||||
//! Avoids type nesting for `some matcher && GenericAllOf` case
|
||||
template<typename MatcherLHS>
|
||||
friend std::enable_if_t<is_matcher<MatcherLHS>::value,
|
||||
MatchAllOfGeneric<MatcherLHS, MatcherTs...>> operator && (
|
||||
MatcherLHS const& lhs,
|
||||
MatchAllOfGeneric<MatcherTs...>&& rhs) {
|
||||
return MatchAllOfGeneric<MatcherLHS, MatcherTs...>{array_cat(static_cast<void const*>(std::addressof(lhs)), std::move(rhs.m_matchers))};
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -152,6 +179,32 @@ namespace Matchers {
|
||||
}
|
||||
|
||||
std::array<void const*, sizeof...(MatcherTs)> m_matchers;
|
||||
|
||||
//! Avoids type nesting for `GenericAnyOf || GenericAnyOf` case
|
||||
template<typename... MatchersRHS>
|
||||
friend MatchAnyOfGeneric<MatcherTs..., MatchersRHS...> operator || (
|
||||
MatchAnyOfGeneric<MatcherTs...>&& lhs,
|
||||
MatchAnyOfGeneric<MatchersRHS...>&& rhs) {
|
||||
return MatchAnyOfGeneric<MatcherTs..., MatchersRHS...>{array_cat(std::move(lhs.m_matchers), std::move(rhs.m_matchers))};
|
||||
}
|
||||
|
||||
//! Avoids type nesting for `GenericAnyOf || some matcher` case
|
||||
template<typename MatcherRHS>
|
||||
friend std::enable_if_t<is_matcher<MatcherRHS>::value,
|
||||
MatchAnyOfGeneric<MatcherTs..., MatcherRHS>> operator || (
|
||||
MatchAnyOfGeneric<MatcherTs...>&& lhs,
|
||||
MatcherRHS const& rhs) {
|
||||
return MatchAnyOfGeneric<MatcherTs..., MatcherRHS>{array_cat(std::move(lhs.m_matchers), static_cast<void const*>(std::addressof(rhs)))};
|
||||
}
|
||||
|
||||
//! Avoids type nesting for `some matcher || GenericAnyOf` case
|
||||
template<typename MatcherLHS>
|
||||
friend std::enable_if_t<is_matcher<MatcherLHS>::value,
|
||||
MatchAnyOfGeneric<MatcherLHS, MatcherTs...>> operator || (
|
||||
MatcherLHS const& lhs,
|
||||
MatchAnyOfGeneric<MatcherTs...>&& rhs) {
|
||||
return MatchAnyOfGeneric<MatcherLHS, MatcherTs...>{array_cat(static_cast<void const*>(std::addressof(lhs)), std::move(rhs.m_matchers))};
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -174,7 +227,7 @@ namespace Matchers {
|
||||
}
|
||||
|
||||
//! Negating negation can just unwrap and return underlying matcher
|
||||
friend MatcherT const& operator ! (Detail::MatchNotOfGeneric<MatcherT> const& matcher) {
|
||||
friend MatcherT const& operator ! (MatchNotOfGeneric<MatcherT> const& matcher) {
|
||||
return matcher.m_matcher;
|
||||
}
|
||||
private:
|
||||
@ -229,44 +282,6 @@ namespace Matchers {
|
||||
return { lhs, rhs };
|
||||
}
|
||||
|
||||
|
||||
// avoid deep nesting of matcher templates
|
||||
template<typename... MatchersLHS, typename... MatchersRHS>
|
||||
Detail::MatchAllOfGeneric<MatchersLHS..., MatchersRHS...>
|
||||
operator && (Detail::MatchAllOfGeneric<MatchersLHS...>&& lhs, Detail::MatchAllOfGeneric<MatchersRHS...>&& rhs) {
|
||||
return Detail::MatchAllOfGeneric<MatchersLHS..., MatchersRHS...>{Detail::array_cat(std::move(lhs.m_matchers), std::move(rhs.m_matchers))};
|
||||
}
|
||||
|
||||
template<typename... MatchersLHS, typename MatcherRHS>
|
||||
std::enable_if_t<Detail::is_matcher<MatcherRHS>::value, Detail::MatchAllOfGeneric<MatchersLHS..., MatcherRHS>>
|
||||
operator && (Detail::MatchAllOfGeneric<MatchersLHS...>&& lhs, MatcherRHS const& rhs) {
|
||||
return Detail::MatchAllOfGeneric<MatchersLHS..., MatcherRHS>{Detail::array_cat(std::move(lhs.m_matchers), static_cast<void const*>(&rhs))};
|
||||
}
|
||||
|
||||
template<typename MatcherLHS, typename... MatchersRHS>
|
||||
std::enable_if_t<Detail::is_matcher<MatcherLHS>::value, Detail::MatchAllOfGeneric<MatcherLHS, MatchersRHS...>>
|
||||
operator && (MatcherLHS const& lhs, Detail::MatchAllOfGeneric<MatchersRHS...>&& rhs) {
|
||||
return Detail::MatchAllOfGeneric<MatcherLHS, MatchersRHS...>{Detail::array_cat(static_cast<void const*>(std::addressof(lhs)), std::move(rhs.m_matchers))};
|
||||
}
|
||||
|
||||
template<typename... MatchersLHS, typename... MatchersRHS>
|
||||
Detail::MatchAnyOfGeneric<MatchersLHS..., MatchersRHS...>
|
||||
operator || (Detail::MatchAnyOfGeneric<MatchersLHS...>&& lhs, Detail::MatchAnyOfGeneric<MatchersRHS...>&& rhs) {
|
||||
return Detail::MatchAnyOfGeneric<MatchersLHS..., MatchersRHS...>{Detail::array_cat(std::move(lhs.m_matchers), std::move(rhs.m_matchers))};
|
||||
}
|
||||
|
||||
template<typename... MatchersLHS, typename MatcherRHS>
|
||||
std::enable_if_t<Detail::is_matcher<MatcherRHS>::value, Detail::MatchAnyOfGeneric<MatchersLHS..., MatcherRHS>>
|
||||
operator || (Detail::MatchAnyOfGeneric<MatchersLHS...>&& lhs, MatcherRHS const& rhs) {
|
||||
return Detail::MatchAnyOfGeneric<MatchersLHS..., MatcherRHS>{Detail::array_cat(std::move(lhs.m_matchers), static_cast<void const*>(std::addressof(rhs)))};
|
||||
}
|
||||
|
||||
template<typename MatcherLHS, typename... MatchersRHS>
|
||||
std::enable_if_t<Detail::is_matcher<MatcherLHS>::value, Detail::MatchAnyOfGeneric<MatcherLHS, MatchersRHS...>>
|
||||
operator || (MatcherLHS const& lhs, Detail::MatchAnyOfGeneric<MatchersRHS...>&& rhs) {
|
||||
return Detail::MatchAnyOfGeneric<MatcherLHS, MatchersRHS...>{Detail::array_cat(static_cast<void const*>(std::addressof(lhs)), std::move(rhs.m_matchers))};
|
||||
}
|
||||
|
||||
} // namespace Matchers
|
||||
} // namespace Catch
|
||||
|
||||
|
@ -16,164 +16,172 @@
|
||||
namespace Catch {
|
||||
namespace Matchers {
|
||||
|
||||
namespace Vector {
|
||||
template<typename T>
|
||||
struct ContainsElementMatcher final : MatcherBase<std::vector<T>> {
|
||||
template<typename T>
|
||||
struct ContainsElementMatcher final : MatcherBase<std::vector<T>> {
|
||||
|
||||
ContainsElementMatcher(T const &comparator) : m_comparator( comparator) {}
|
||||
ContainsElementMatcher(T const& comparator):
|
||||
m_comparator(comparator)
|
||||
{}
|
||||
|
||||
bool match(std::vector<T> const &v) const override {
|
||||
for (auto const& el : v) {
|
||||
if (el == m_comparator) {
|
||||
return true;
|
||||
bool match(std::vector<T> const& v) const override {
|
||||
for (auto const& el : v) {
|
||||
if (el == m_comparator) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string describe() const override {
|
||||
return "Contains: " + ::Catch::Detail::stringify( m_comparator );
|
||||
}
|
||||
|
||||
T const& m_comparator;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct ContainsMatcher final : MatcherBase<std::vector<T>> {
|
||||
|
||||
ContainsMatcher(std::vector<T> const& comparator):
|
||||
m_comparator(comparator)
|
||||
{}
|
||||
|
||||
bool match(std::vector<T> const& v) const override {
|
||||
// !TBD: see note in EqualsMatcher
|
||||
if (m_comparator.size() > v.size())
|
||||
return false;
|
||||
for (auto const& comparator : m_comparator) {
|
||||
auto present = false;
|
||||
for (const auto& el : v) {
|
||||
if (el == comparator) {
|
||||
present = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!present) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
std::string describe() const override {
|
||||
return "Contains: " + ::Catch::Detail::stringify( m_comparator );
|
||||
}
|
||||
|
||||
std::vector<T> const& m_comparator;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct EqualsMatcher final : MatcherBase<std::vector<T>> {
|
||||
|
||||
EqualsMatcher(std::vector<T> const &comparator) : m_comparator( comparator ) {}
|
||||
|
||||
bool match(std::vector<T> const &v) const override {
|
||||
// !TBD: This currently works if all elements can be compared using !=
|
||||
// - a more general approach would be via a compare template that defaults
|
||||
// to using !=. but could be specialised for, e.g. std::vector<T> etc
|
||||
// - then just call that directly
|
||||
if (m_comparator.size() != v.size())
|
||||
return false;
|
||||
for (std::size_t i = 0; i < v.size(); ++i)
|
||||
if (m_comparator[i] != v[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
std::string describe() const override {
|
||||
return "Equals: " + ::Catch::Detail::stringify( m_comparator );
|
||||
}
|
||||
std::vector<T> const& m_comparator;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct ApproxMatcher final : MatcherBase<std::vector<T>> {
|
||||
|
||||
ApproxMatcher(std::vector<T> const& comparator) : m_comparator( comparator ) {}
|
||||
|
||||
bool match(std::vector<T> const &v) const override {
|
||||
if (m_comparator.size() != v.size())
|
||||
return false;
|
||||
for (std::size_t i = 0; i < v.size(); ++i)
|
||||
if (m_comparator[i] != approx(v[i]))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
std::string describe() const override {
|
||||
return "is approx: " + ::Catch::Detail::stringify( m_comparator );
|
||||
}
|
||||
template <typename = std::enable_if_t<std::is_constructible<double, T>::value>>
|
||||
ApproxMatcher& epsilon( T const& newEpsilon ) {
|
||||
approx.epsilon(newEpsilon);
|
||||
return *this;
|
||||
}
|
||||
template <typename = std::enable_if_t<std::is_constructible<double, T>::value>>
|
||||
ApproxMatcher& margin( T const& newMargin ) {
|
||||
approx.margin(newMargin);
|
||||
return *this;
|
||||
}
|
||||
template <typename = std::enable_if_t<std::is_constructible<double, T>::value>>
|
||||
ApproxMatcher& scale( T const& newScale ) {
|
||||
approx.scale(newScale);
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::vector<T> const& m_comparator;
|
||||
mutable Catch::Approx approx = Catch::Approx::custom();
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct UnorderedEqualsMatcher final : MatcherBase<std::vector<T>> {
|
||||
UnorderedEqualsMatcher(std::vector<T> const& target) : m_target(target) {}
|
||||
bool match(std::vector<T> const& vec) const override {
|
||||
// Note: This is a reimplementation of std::is_permutation,
|
||||
// because I don't want to include <algorithm> inside the common path
|
||||
if (m_target.size() != vec.size()) {
|
||||
return false;
|
||||
}
|
||||
return std::is_permutation(m_target.begin(), m_target.end(), vec.begin());
|
||||
}
|
||||
|
||||
std::string describe() const override {
|
||||
return "Contains: " + ::Catch::Detail::stringify( m_comparator );
|
||||
}
|
||||
std::string describe() const override {
|
||||
return "UnorderedEquals: " + ::Catch::Detail::stringify(m_target);
|
||||
}
|
||||
private:
|
||||
std::vector<T> const& m_target;
|
||||
};
|
||||
|
||||
T const& m_comparator;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct ContainsMatcher final : MatcherBase<std::vector<T>> {
|
||||
|
||||
ContainsMatcher(std::vector<T> const &comparator) : m_comparator( comparator ) {}
|
||||
|
||||
bool match(std::vector<T> const &v) const override {
|
||||
// !TBD: see note in EqualsMatcher
|
||||
if (m_comparator.size() > v.size())
|
||||
return false;
|
||||
for (auto const& comparator : m_comparator) {
|
||||
auto present = false;
|
||||
for (const auto& el : v) {
|
||||
if (el == comparator) {
|
||||
present = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!present) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
std::string describe() const override {
|
||||
return "Contains: " + ::Catch::Detail::stringify( m_comparator );
|
||||
}
|
||||
|
||||
std::vector<T> const& m_comparator;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct EqualsMatcher final : MatcherBase<std::vector<T>> {
|
||||
|
||||
EqualsMatcher(std::vector<T> const &comparator) : m_comparator( comparator ) {}
|
||||
|
||||
bool match(std::vector<T> const &v) const override {
|
||||
// !TBD: This currently works if all elements can be compared using !=
|
||||
// - a more general approach would be via a compare template that defaults
|
||||
// to using !=. but could be specialised for, e.g. std::vector<T> etc
|
||||
// - then just call that directly
|
||||
if (m_comparator.size() != v.size())
|
||||
return false;
|
||||
for (std::size_t i = 0; i < v.size(); ++i)
|
||||
if (m_comparator[i] != v[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
std::string describe() const override {
|
||||
return "Equals: " + ::Catch::Detail::stringify( m_comparator );
|
||||
}
|
||||
std::vector<T> const& m_comparator;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct ApproxMatcher final : MatcherBase<std::vector<T>> {
|
||||
|
||||
ApproxMatcher(std::vector<T> const& comparator) : m_comparator( comparator ) {}
|
||||
|
||||
bool match(std::vector<T> const &v) const override {
|
||||
if (m_comparator.size() != v.size())
|
||||
return false;
|
||||
for (std::size_t i = 0; i < v.size(); ++i)
|
||||
if (m_comparator[i] != approx(v[i]))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
std::string describe() const override {
|
||||
return "is approx: " + ::Catch::Detail::stringify( m_comparator );
|
||||
}
|
||||
template <typename = std::enable_if_t<std::is_constructible<double, T>::value>>
|
||||
ApproxMatcher& epsilon( T const& newEpsilon ) {
|
||||
approx.epsilon(newEpsilon);
|
||||
return *this;
|
||||
}
|
||||
template <typename = std::enable_if_t<std::is_constructible<double, T>::value>>
|
||||
ApproxMatcher& margin( T const& newMargin ) {
|
||||
approx.margin(newMargin);
|
||||
return *this;
|
||||
}
|
||||
template <typename = std::enable_if_t<std::is_constructible<double, T>::value>>
|
||||
ApproxMatcher& scale( T const& newScale ) {
|
||||
approx.scale(newScale);
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::vector<T> const& m_comparator;
|
||||
mutable Catch::Approx approx = Catch::Approx::custom();
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct UnorderedEqualsMatcher final : MatcherBase<std::vector<T>> {
|
||||
UnorderedEqualsMatcher(std::vector<T> const& target) : m_target(target) {}
|
||||
bool match(std::vector<T> const& vec) const override {
|
||||
// Note: This is a reimplementation of std::is_permutation,
|
||||
// because I don't want to include <algorithm> inside the common path
|
||||
if (m_target.size() != vec.size()) {
|
||||
return false;
|
||||
}
|
||||
return std::is_permutation(m_target.begin(), m_target.end(), vec.begin());
|
||||
}
|
||||
|
||||
std::string describe() const override {
|
||||
return "UnorderedEquals: " + ::Catch::Detail::stringify(m_target);
|
||||
}
|
||||
private:
|
||||
std::vector<T> const& m_target;
|
||||
};
|
||||
|
||||
} // namespace Vector
|
||||
|
||||
// The following functions create the actual matcher objects.
|
||||
// This allows the types to be inferred
|
||||
|
||||
|
||||
//! Creates a matcher that matches vectors that contain all elements in `comparator`
|
||||
template<typename T>
|
||||
Vector::ContainsMatcher<T> Contains( std::vector<T> const& comparator ) {
|
||||
return Vector::ContainsMatcher<T>( comparator );
|
||||
ContainsMatcher<T> Contains( std::vector<T> const& comparator ) {
|
||||
return ContainsMatcher<T>( comparator );
|
||||
}
|
||||
|
||||
//! Creates a matcher that matches vectors that contain `comparator` as an element
|
||||
template<typename T>
|
||||
Vector::ContainsElementMatcher<T> VectorContains( T const& comparator ) {
|
||||
return Vector::ContainsElementMatcher<T>( comparator );
|
||||
ContainsElementMatcher<T> VectorContains( T const& comparator ) {
|
||||
return ContainsElementMatcher<T>( comparator );
|
||||
}
|
||||
|
||||
//! Creates a matcher that matches vectors that are exactly equal to `comparator`
|
||||
template<typename T>
|
||||
Vector::EqualsMatcher<T> Equals( std::vector<T> const& comparator ) {
|
||||
return Vector::EqualsMatcher<T>( comparator );
|
||||
EqualsMatcher<T> Equals( std::vector<T> const& comparator ) {
|
||||
return EqualsMatcher<T>( comparator );
|
||||
}
|
||||
|
||||
//! Creates a matcher that matches vectors that `comparator` as an element
|
||||
template<typename T>
|
||||
Vector::ApproxMatcher<T> Approx( std::vector<T> const& comparator ) {
|
||||
return Vector::ApproxMatcher<T>( comparator );
|
||||
ApproxMatcher<T> Approx( std::vector<T> const& comparator ) {
|
||||
return ApproxMatcher<T>( comparator );
|
||||
}
|
||||
|
||||
//! Creates a matcher that matches vectors that is equal to `target` modulo permutation
|
||||
template<typename T>
|
||||
Vector::UnorderedEqualsMatcher<T> UnorderedEquals(std::vector<T> const& target) {
|
||||
return Vector::UnorderedEqualsMatcher<T>(target);
|
||||
UnorderedEqualsMatcher<T> UnorderedEquals(std::vector<T> const& target) {
|
||||
return UnorderedEqualsMatcher<T>(target);
|
||||
}
|
||||
|
||||
} // namespace Matchers
|
||||
|
@ -283,14 +283,18 @@ ToStringGeneral.tests.cpp:<line number>: passed: c == i for: 2 == 2
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: c == i for: 3 == 3
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: c == i for: 4 == 4
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: c == i for: 5 == 5
|
||||
Matchers.tests.cpp:<line number>: passed: with 1 message: 'std::is_same< decltype(MatcherA() && MatcherB() && MatcherC()), Catch::Matchers::Detail::MatchAllOfGeneric<MatcherA, MatcherB, MatcherC> >::value'
|
||||
Matchers.tests.cpp:<line number>: passed: 1, MatcherA() && MatcherB() && MatcherC() for: 1 ( equals: (int) 1 or (float) 1.0f and equals: (long long) 1 and equals: (T) 1 )
|
||||
Matchers.tests.cpp:<line number>: passed: with 1 message: 'std::is_same< decltype(MatcherA() && MatcherB() && MatcherC() && MatcherD()), Catch::Matchers::Detail::MatchAllOfGeneric<MatcherA, MatcherB, MatcherC, MatcherD> >::value'
|
||||
Matchers.tests.cpp:<line number>: passed: 1, MatcherA() && MatcherB() && MatcherC() && MatcherD() for: 1 ( equals: (int) 1 or (float) 1.0f and equals: (long long) 1 and equals: (T) 1 and equals: true )
|
||||
Matchers.tests.cpp:<line number>: passed: with 1 message: 'std::is_same< decltype(MatcherA() || MatcherB() || MatcherC()), Catch::Matchers::Detail::MatchAnyOfGeneric<MatcherA, MatcherB, MatcherC> >::value'
|
||||
Matchers.tests.cpp:<line number>: passed: 1, MatcherA() || MatcherB() || MatcherC() for: 1 ( equals: (int) 1 or (float) 1.0f or equals: (long long) 1 or equals: (T) 1 )
|
||||
Matchers.tests.cpp:<line number>: passed: with 1 message: 'std::is_same< decltype(MatcherA() || MatcherB() || MatcherC() || MatcherD()), Catch::Matchers::Detail::MatchAnyOfGeneric<MatcherA, MatcherB, MatcherC, MatcherD> >::value'
|
||||
Matchers.tests.cpp:<line number>: passed: 1, MatcherA() || MatcherB() || MatcherC() || MatcherD() for: 1 ( equals: (int) 1 or (float) 1.0f or equals: (long long) 1 or equals: (T) 1 or equals: true )
|
||||
Matchers.tests.cpp:<line number>: passed: with 1 message: 'std::is_same< decltype((MatcherA() && MatcherB()) && MatcherC()), Catch::Matchers::Detail::MatchAllOfGeneric<MatcherA, MatcherB, MatcherC> >::value'
|
||||
Matchers.tests.cpp:<line number>: passed: 1, (MatcherA() && MatcherB()) && MatcherC() for: 1 ( equals: (int) 1 or (float) 1.0f and equals: (long long) 1 and equals: (T) 1 )
|
||||
Matchers.tests.cpp:<line number>: passed: with 1 message: 'std::is_same< decltype(MatcherA() && (MatcherB() && MatcherC())), Catch::Matchers::Detail::MatchAllOfGeneric<MatcherA, MatcherB, MatcherC> >::value'
|
||||
Matchers.tests.cpp:<line number>: passed: 1, MatcherA() && (MatcherB() && MatcherC()) for: 1 ( equals: (int) 1 or (float) 1.0f and equals: (long long) 1 and equals: (T) 1 )
|
||||
Matchers.tests.cpp:<line number>: passed: with 1 message: 'std::is_same< decltype((MatcherA() && MatcherB()) && (MatcherC() && MatcherD())), Catch::Matchers::Detail::MatchAllOfGeneric<MatcherA, MatcherB, MatcherC, MatcherD> >::value'
|
||||
Matchers.tests.cpp:<line number>: passed: 1, (MatcherA() && MatcherB()) && (MatcherC() && MatcherD()) for: 1 ( equals: (int) 1 or (float) 1.0f and equals: (long long) 1 and equals: (T) 1 and equals: true )
|
||||
Matchers.tests.cpp:<line number>: passed: with 1 message: 'std::is_same< decltype((MatcherA() || MatcherB()) || MatcherC()), Catch::Matchers::Detail::MatchAnyOfGeneric<MatcherA, MatcherB, MatcherC> >::value'
|
||||
Matchers.tests.cpp:<line number>: passed: 1, (MatcherA() || MatcherB()) || MatcherC() for: 1 ( equals: (int) 1 or (float) 1.0f or equals: (long long) 1 or equals: (T) 1 )
|
||||
Matchers.tests.cpp:<line number>: passed: with 1 message: 'std::is_same< decltype(MatcherA() || (MatcherB() || MatcherC())), Catch::Matchers::Detail::MatchAnyOfGeneric<MatcherA, MatcherB, MatcherC> >::value'
|
||||
Matchers.tests.cpp:<line number>: passed: 1, MatcherA() || (MatcherB() || MatcherC()) for: 1 ( equals: (int) 1 or (float) 1.0f or equals: (long long) 1 or equals: (T) 1 )
|
||||
Matchers.tests.cpp:<line number>: passed: with 1 message: 'std::is_same< decltype((MatcherA() || MatcherB()) || (MatcherC() || MatcherD())), Catch::Matchers::Detail::MatchAnyOfGeneric<MatcherA, MatcherB, MatcherC, MatcherD> >::value'
|
||||
Matchers.tests.cpp:<line number>: passed: 1, (MatcherA() || MatcherB()) || (MatcherC() || MatcherD()) for: 1 ( equals: (int) 1 or (float) 1.0f or equals: (long long) 1 or equals: (T) 1 or equals: true )
|
||||
Matchers.tests.cpp:<line number>: passed: with 1 message: 'std::is_same< decltype(!MatcherA()), Catch::Matchers::Detail::MatchNotOfGeneric<MatcherA> >::value'
|
||||
Matchers.tests.cpp:<line number>: passed: 0, !MatcherA() for: 0 not equals: (int) 1 or (float) 1.0f
|
||||
Matchers.tests.cpp:<line number>: passed: with 1 message: 'std::is_same< decltype(!!MatcherA()), MatcherA const& >::value'
|
||||
|
@ -1381,5 +1381,5 @@ due to unexpected exception with message:
|
||||
|
||||
===============================================================================
|
||||
test cases: 331 | 257 passed | 70 failed | 4 failed as expected
|
||||
assertions: 1868 | 1716 passed | 131 failed | 21 failed as expected
|
||||
assertions: 1872 | 1720 passed | 131 failed | 21 failed as expected
|
||||
|
||||
|
@ -2287,23 +2287,34 @@ Matchers.tests.cpp:<line number>
|
||||
|
||||
Matchers.tests.cpp:<line number>: PASSED:
|
||||
with message:
|
||||
std::is_same< decltype(MatcherA() && MatcherB() && MatcherC()), Catch::
|
||||
std::is_same< decltype((MatcherA() && MatcherB()) && MatcherC()), Catch::
|
||||
Matchers::Detail::MatchAllOfGeneric<MatcherA, MatcherB, MatcherC> >::value
|
||||
|
||||
Matchers.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE_THAT( 1, MatcherA() && MatcherB() && MatcherC() )
|
||||
REQUIRE_THAT( 1, (MatcherA() && MatcherB()) && MatcherC() )
|
||||
with expansion:
|
||||
1 ( equals: (int) 1 or (float) 1.0f and equals: (long long) 1 and equals: (T)
|
||||
1 )
|
||||
|
||||
Matchers.tests.cpp:<line number>: PASSED:
|
||||
with message:
|
||||
std::is_same< decltype(MatcherA() && MatcherB() && MatcherC() && MatcherD()),
|
||||
Catch::Matchers::Detail::MatchAllOfGeneric<MatcherA, MatcherB, MatcherC,
|
||||
MatcherD> >::value
|
||||
std::is_same< decltype(MatcherA() && (MatcherB() && MatcherC())), Catch::
|
||||
Matchers::Detail::MatchAllOfGeneric<MatcherA, MatcherB, MatcherC> >::value
|
||||
|
||||
Matchers.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE_THAT( 1, MatcherA() && MatcherB() && MatcherC() && MatcherD() )
|
||||
REQUIRE_THAT( 1, MatcherA() && (MatcherB() && MatcherC()) )
|
||||
with expansion:
|
||||
1 ( equals: (int) 1 or (float) 1.0f and equals: (long long) 1 and equals: (T)
|
||||
1 )
|
||||
|
||||
Matchers.tests.cpp:<line number>: PASSED:
|
||||
with message:
|
||||
std::is_same< decltype((MatcherA() && MatcherB()) && (MatcherC() && MatcherD
|
||||
())), Catch::Matchers::Detail::MatchAllOfGeneric<MatcherA, MatcherB,
|
||||
MatcherC, MatcherD> >::value
|
||||
|
||||
Matchers.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE_THAT( 1, (MatcherA() && MatcherB()) && (MatcherC() && MatcherD()) )
|
||||
with expansion:
|
||||
1 ( equals: (int) 1 or (float) 1.0f and equals: (long long) 1 and equals: (T)
|
||||
1 and equals: true )
|
||||
@ -2316,23 +2327,34 @@ Matchers.tests.cpp:<line number>
|
||||
|
||||
Matchers.tests.cpp:<line number>: PASSED:
|
||||
with message:
|
||||
std::is_same< decltype(MatcherA() || MatcherB() || MatcherC()), Catch::
|
||||
std::is_same< decltype((MatcherA() || MatcherB()) || MatcherC()), Catch::
|
||||
Matchers::Detail::MatchAnyOfGeneric<MatcherA, MatcherB, MatcherC> >::value
|
||||
|
||||
Matchers.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE_THAT( 1, MatcherA() || MatcherB() || MatcherC() )
|
||||
REQUIRE_THAT( 1, (MatcherA() || MatcherB()) || MatcherC() )
|
||||
with expansion:
|
||||
1 ( equals: (int) 1 or (float) 1.0f or equals: (long long) 1 or equals: (T) 1
|
||||
)
|
||||
|
||||
Matchers.tests.cpp:<line number>: PASSED:
|
||||
with message:
|
||||
std::is_same< decltype(MatcherA() || MatcherB() || MatcherC() || MatcherD()),
|
||||
Catch::Matchers::Detail::MatchAnyOfGeneric<MatcherA, MatcherB, MatcherC,
|
||||
MatcherD> >::value
|
||||
std::is_same< decltype(MatcherA() || (MatcherB() || MatcherC())), Catch::
|
||||
Matchers::Detail::MatchAnyOfGeneric<MatcherA, MatcherB, MatcherC> >::value
|
||||
|
||||
Matchers.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE_THAT( 1, MatcherA() || MatcherB() || MatcherC() || MatcherD() )
|
||||
REQUIRE_THAT( 1, MatcherA() || (MatcherB() || MatcherC()) )
|
||||
with expansion:
|
||||
1 ( equals: (int) 1 or (float) 1.0f or equals: (long long) 1 or equals: (T) 1
|
||||
)
|
||||
|
||||
Matchers.tests.cpp:<line number>: PASSED:
|
||||
with message:
|
||||
std::is_same< decltype((MatcherA() || MatcherB()) || (MatcherC() || MatcherD
|
||||
())), Catch::Matchers::Detail::MatchAnyOfGeneric<MatcherA, MatcherB,
|
||||
MatcherC, MatcherD> >::value
|
||||
|
||||
Matchers.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE_THAT( 1, (MatcherA() || MatcherB()) || (MatcherC() || MatcherD()) )
|
||||
with expansion:
|
||||
1 ( equals: (int) 1 or (float) 1.0f or equals: (long long) 1 or equals: (T) 1
|
||||
or equals: true )
|
||||
@ -14626,5 +14648,5 @@ Misc.tests.cpp:<line number>: PASSED:
|
||||
|
||||
===============================================================================
|
||||
test cases: 331 | 241 passed | 86 failed | 4 failed as expected
|
||||
assertions: 1885 | 1716 passed | 148 failed | 21 failed as expected
|
||||
assertions: 1889 | 1720 passed | 148 failed | 21 failed as expected
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<testsuitesloose text artifact
|
||||
>
|
||||
<testsuite name="<exe-name>" errors="17" failures="132" tests="1886" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
|
||||
<testsuite name="<exe-name>" errors="17" failures="132" tests="1890" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
|
||||
<properties>
|
||||
<property name="filters" value="~[!nonportable]~[!benchmark]~[approvals] *"/>
|
||||
<property name="random-seed" value="1"/>
|
||||
|
@ -565,21 +565,29 @@ ok {test-number} - c == i for: 4 == 4
|
||||
# Character pretty printing
|
||||
ok {test-number} - c == i for: 5 == 5
|
||||
# Combining MatchAllOfGeneric does not nest
|
||||
ok {test-number} - with 1 message: 'std::is_same< decltype(MatcherA() && MatcherB() && MatcherC()), Catch::Matchers::Detail::MatchAllOfGeneric<MatcherA, MatcherB, MatcherC> >::value'
|
||||
ok {test-number} - with 1 message: 'std::is_same< decltype((MatcherA() && MatcherB()) && MatcherC()), Catch::Matchers::Detail::MatchAllOfGeneric<MatcherA, MatcherB, MatcherC> >::value'
|
||||
# Combining MatchAllOfGeneric does not nest
|
||||
ok {test-number} - 1, MatcherA() && MatcherB() && MatcherC() for: 1 ( equals: (int) 1 or (float) 1.0f and equals: (long long) 1 and equals: (T) 1 )
|
||||
ok {test-number} - 1, (MatcherA() && MatcherB()) && MatcherC() for: 1 ( equals: (int) 1 or (float) 1.0f and equals: (long long) 1 and equals: (T) 1 )
|
||||
# Combining MatchAllOfGeneric does not nest
|
||||
ok {test-number} - with 1 message: 'std::is_same< decltype(MatcherA() && MatcherB() && MatcherC() && MatcherD()), Catch::Matchers::Detail::MatchAllOfGeneric<MatcherA, MatcherB, MatcherC, MatcherD> >::value'
|
||||
ok {test-number} - with 1 message: 'std::is_same< decltype(MatcherA() && (MatcherB() && MatcherC())), Catch::Matchers::Detail::MatchAllOfGeneric<MatcherA, MatcherB, MatcherC> >::value'
|
||||
# Combining MatchAllOfGeneric does not nest
|
||||
ok {test-number} - 1, MatcherA() && MatcherB() && MatcherC() && MatcherD() for: 1 ( equals: (int) 1 or (float) 1.0f and equals: (long long) 1 and equals: (T) 1 and equals: true )
|
||||
ok {test-number} - 1, MatcherA() && (MatcherB() && MatcherC()) for: 1 ( equals: (int) 1 or (float) 1.0f and equals: (long long) 1 and equals: (T) 1 )
|
||||
# Combining MatchAllOfGeneric does not nest
|
||||
ok {test-number} - with 1 message: 'std::is_same< decltype((MatcherA() && MatcherB()) && (MatcherC() && MatcherD())), Catch::Matchers::Detail::MatchAllOfGeneric<MatcherA, MatcherB, MatcherC, MatcherD> >::value'
|
||||
# Combining MatchAllOfGeneric does not nest
|
||||
ok {test-number} - 1, (MatcherA() && MatcherB()) && (MatcherC() && MatcherD()) for: 1 ( equals: (int) 1 or (float) 1.0f and equals: (long long) 1 and equals: (T) 1 and equals: true )
|
||||
# Combining MatchAnyOfGeneric does not nest
|
||||
ok {test-number} - with 1 message: 'std::is_same< decltype(MatcherA() || MatcherB() || MatcherC()), Catch::Matchers::Detail::MatchAnyOfGeneric<MatcherA, MatcherB, MatcherC> >::value'
|
||||
ok {test-number} - with 1 message: 'std::is_same< decltype((MatcherA() || MatcherB()) || MatcherC()), Catch::Matchers::Detail::MatchAnyOfGeneric<MatcherA, MatcherB, MatcherC> >::value'
|
||||
# Combining MatchAnyOfGeneric does not nest
|
||||
ok {test-number} - 1, MatcherA() || MatcherB() || MatcherC() for: 1 ( equals: (int) 1 or (float) 1.0f or equals: (long long) 1 or equals: (T) 1 )
|
||||
ok {test-number} - 1, (MatcherA() || MatcherB()) || MatcherC() for: 1 ( equals: (int) 1 or (float) 1.0f or equals: (long long) 1 or equals: (T) 1 )
|
||||
# Combining MatchAnyOfGeneric does not nest
|
||||
ok {test-number} - with 1 message: 'std::is_same< decltype(MatcherA() || MatcherB() || MatcherC() || MatcherD()), Catch::Matchers::Detail::MatchAnyOfGeneric<MatcherA, MatcherB, MatcherC, MatcherD> >::value'
|
||||
ok {test-number} - with 1 message: 'std::is_same< decltype(MatcherA() || (MatcherB() || MatcherC())), Catch::Matchers::Detail::MatchAnyOfGeneric<MatcherA, MatcherB, MatcherC> >::value'
|
||||
# Combining MatchAnyOfGeneric does not nest
|
||||
ok {test-number} - 1, MatcherA() || MatcherB() || MatcherC() || MatcherD() for: 1 ( equals: (int) 1 or (float) 1.0f or equals: (long long) 1 or equals: (T) 1 or equals: true )
|
||||
ok {test-number} - 1, MatcherA() || (MatcherB() || MatcherC()) for: 1 ( equals: (int) 1 or (float) 1.0f or equals: (long long) 1 or equals: (T) 1 )
|
||||
# Combining MatchAnyOfGeneric does not nest
|
||||
ok {test-number} - with 1 message: 'std::is_same< decltype((MatcherA() || MatcherB()) || (MatcherC() || MatcherD())), Catch::Matchers::Detail::MatchAnyOfGeneric<MatcherA, MatcherB, MatcherC, MatcherD> >::value'
|
||||
# Combining MatchAnyOfGeneric does not nest
|
||||
ok {test-number} - 1, (MatcherA() || MatcherB()) || (MatcherC() || MatcherD()) for: 1 ( equals: (int) 1 or (float) 1.0f or equals: (long long) 1 or equals: (T) 1 or equals: true )
|
||||
# Combining MatchNotOfGeneric does not nest
|
||||
ok {test-number} - with 1 message: 'std::is_same< decltype(!MatcherA()), Catch::Matchers::Detail::MatchNotOfGeneric<MatcherA> >::value'
|
||||
# Combining MatchNotOfGeneric does not nest
|
||||
@ -3762,5 +3770,5 @@ ok {test-number} - q3 == 23. for: 23.0 == 23.0
|
||||
ok {test-number} -
|
||||
# xmlentitycheck
|
||||
ok {test-number} -
|
||||
1..1877
|
||||
1..1881
|
||||
|
||||
|
@ -2613,7 +2613,7 @@ Nor would this
|
||||
<TestCase name="Combining MatchAllOfGeneric does not nest" tags="[matchers][templated]" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||
<Original>
|
||||
1, MatcherA() && MatcherB() && MatcherC()
|
||||
1, (MatcherA() && MatcherB()) && MatcherC()
|
||||
</Original>
|
||||
<Expanded>
|
||||
1 ( equals: (int) 1 or (float) 1.0f and equals: (long long) 1 and equals: (T) 1 )
|
||||
@ -2621,7 +2621,15 @@ Nor would this
|
||||
</Expression>
|
||||
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||
<Original>
|
||||
1, MatcherA() && MatcherB() && MatcherC() && MatcherD()
|
||||
1, MatcherA() && (MatcherB() && MatcherC())
|
||||
</Original>
|
||||
<Expanded>
|
||||
1 ( equals: (int) 1 or (float) 1.0f and equals: (long long) 1 and equals: (T) 1 )
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||
<Original>
|
||||
1, (MatcherA() && MatcherB()) && (MatcherC() && MatcherD())
|
||||
</Original>
|
||||
<Expanded>
|
||||
1 ( equals: (int) 1 or (float) 1.0f and equals: (long long) 1 and equals: (T) 1 and equals: true )
|
||||
@ -2632,7 +2640,7 @@ Nor would this
|
||||
<TestCase name="Combining MatchAnyOfGeneric does not nest" tags="[matchers][templated]" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||
<Original>
|
||||
1, MatcherA() || MatcherB() || MatcherC()
|
||||
1, (MatcherA() || MatcherB()) || MatcherC()
|
||||
</Original>
|
||||
<Expanded>
|
||||
1 ( equals: (int) 1 or (float) 1.0f or equals: (long long) 1 or equals: (T) 1 )
|
||||
@ -2640,7 +2648,15 @@ Nor would this
|
||||
</Expression>
|
||||
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||
<Original>
|
||||
1, MatcherA() || MatcherB() || MatcherC() || MatcherD()
|
||||
1, MatcherA() || (MatcherB() || MatcherC())
|
||||
</Original>
|
||||
<Expanded>
|
||||
1 ( equals: (int) 1 or (float) 1.0f or equals: (long long) 1 or equals: (T) 1 )
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||
<Original>
|
||||
1, (MatcherA() || MatcherB()) || (MatcherC() || MatcherD())
|
||||
</Original>
|
||||
<Expanded>
|
||||
1 ( equals: (int) 1 or (float) 1.0f or equals: (long long) 1 or equals: (T) 1 or equals: true )
|
||||
@ -17541,7 +17557,7 @@ loose text artifact
|
||||
</Section>
|
||||
<OverallResult success="true"/>
|
||||
</TestCase>
|
||||
<OverallResults successes="1716" failures="149" expectedFailures="21"/>
|
||||
<OverallResults successes="1720" failures="149" expectedFailures="21"/>
|
||||
</Group>
|
||||
<OverallResults successes="1716" failures="148" expectedFailures="21"/>
|
||||
<OverallResults successes="1720" failures="148" expectedFailures="21"/>
|
||||
</Catch>
|
||||
|
@ -678,35 +678,57 @@ namespace { namespace MatchersTests {
|
||||
}
|
||||
|
||||
TEST_CASE("Combining MatchAnyOfGeneric does not nest", "[matchers][templated]") {
|
||||
// MatchAnyOfGeneric LHS + some matcher RHS
|
||||
STATIC_REQUIRE(std::is_same<
|
||||
decltype(MatcherA() || MatcherB() || MatcherC()),
|
||||
decltype((MatcherA() || MatcherB()) || MatcherC()),
|
||||
Catch::Matchers::Detail::MatchAnyOfGeneric<MatcherA, MatcherB, MatcherC>
|
||||
>::value);
|
||||
|
||||
REQUIRE_THAT(1, MatcherA() || MatcherB() || MatcherC());
|
||||
REQUIRE_THAT(1, (MatcherA() || MatcherB()) || MatcherC());
|
||||
|
||||
// some matcher LHS + MatchAnyOfGeneric RHS
|
||||
STATIC_REQUIRE(std::is_same<
|
||||
decltype(MatcherA() || MatcherB() || MatcherC() || MatcherD()),
|
||||
decltype(MatcherA() || (MatcherB() || MatcherC())),
|
||||
Catch::Matchers::Detail::MatchAnyOfGeneric<MatcherA, MatcherB, MatcherC>
|
||||
>::value);
|
||||
|
||||
REQUIRE_THAT(1, MatcherA() || (MatcherB() || MatcherC()));
|
||||
|
||||
|
||||
// MatchAnyOfGeneric LHS + MatchAnyOfGeneric RHS
|
||||
STATIC_REQUIRE(std::is_same<
|
||||
decltype((MatcherA() || MatcherB()) || (MatcherC() || MatcherD())),
|
||||
Catch::Matchers::Detail::MatchAnyOfGeneric<MatcherA, MatcherB, MatcherC, MatcherD>
|
||||
>::value);
|
||||
|
||||
REQUIRE_THAT(1, MatcherA() || MatcherB() || MatcherC() || MatcherD());
|
||||
REQUIRE_THAT(1, (MatcherA() || MatcherB()) || (MatcherC() || MatcherD()));
|
||||
}
|
||||
|
||||
TEST_CASE("Combining MatchAllOfGeneric does not nest", "[matchers][templated]") {
|
||||
// MatchAllOfGeneric lhs + some matcher RHS
|
||||
STATIC_REQUIRE(std::is_same<
|
||||
decltype(MatcherA() && MatcherB() && MatcherC()),
|
||||
decltype((MatcherA() && MatcherB()) && MatcherC()),
|
||||
Catch::Matchers::Detail::MatchAllOfGeneric<MatcherA, MatcherB, MatcherC>
|
||||
>::value);
|
||||
|
||||
REQUIRE_THAT(1, MatcherA() && MatcherB() && MatcherC());
|
||||
REQUIRE_THAT(1, (MatcherA() && MatcherB()) && MatcherC());
|
||||
|
||||
// some matcher LHS + MatchAllOfGeneric RSH
|
||||
STATIC_REQUIRE(std::is_same<
|
||||
decltype(MatcherA() && MatcherB() && MatcherC() && MatcherD()),
|
||||
decltype(MatcherA() && (MatcherB() && MatcherC())),
|
||||
Catch::Matchers::Detail::MatchAllOfGeneric<MatcherA, MatcherB, MatcherC>
|
||||
>::value);
|
||||
|
||||
REQUIRE_THAT(1, MatcherA() && (MatcherB() && MatcherC()));
|
||||
|
||||
|
||||
// MatchAllOfGeneric LHS + MatchAllOfGeneric RHS
|
||||
STATIC_REQUIRE(std::is_same<
|
||||
decltype((MatcherA() && MatcherB()) && (MatcherC() && MatcherD())),
|
||||
Catch::Matchers::Detail::MatchAllOfGeneric<MatcherA, MatcherB, MatcherC, MatcherD>
|
||||
>::value);
|
||||
|
||||
REQUIRE_THAT(1, MatcherA() && MatcherB() && MatcherC() && MatcherD());
|
||||
REQUIRE_THAT(1, (MatcherA() && MatcherB()) && (MatcherC() && MatcherD()));
|
||||
}
|
||||
|
||||
TEST_CASE("Combining MatchNotOfGeneric does not nest", "[matchers][templated]") {
|
||||
|
Loading…
Reference in New Issue
Block a user