mirror of
https://github.com/google/googletest.git
synced 2024-12-27 10:11:03 +08:00
gmock-matchers merging -2
This commit is contained in:
parent
a28a7eb5e9
commit
466a49ae30
@ -179,6 +179,35 @@ class MatcherInterface : public MatcherDescriberInterface {
|
||||
// virtual void DescribeNegationTo(::std::ostream* os) const;
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
|
||||
// Converts a MatcherInterface<T> to a MatcherInterface<const T&>.
|
||||
template <typename T>
|
||||
class MatcherInterfaceAdapter : public MatcherInterface<const T&> {
|
||||
public:
|
||||
explicit MatcherInterfaceAdapter(const MatcherInterface<T>* impl)
|
||||
: impl_(impl) {}
|
||||
virtual ~MatcherInterfaceAdapter() { delete impl_; }
|
||||
|
||||
virtual void DescribeTo(::std::ostream* os) const { impl_->DescribeTo(os); }
|
||||
|
||||
virtual void DescribeNegationTo(::std::ostream* os) const {
|
||||
impl_->DescribeNegationTo(os);
|
||||
}
|
||||
|
||||
virtual bool MatchAndExplain(const T& x,
|
||||
MatchResultListener* listener) const {
|
||||
return impl_->MatchAndExplain(x, listener);
|
||||
}
|
||||
|
||||
private:
|
||||
const MatcherInterface<T>* const impl_;
|
||||
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(MatcherInterfaceAdapter);
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// A match result listener that stores the explanation in a string.
|
||||
class StringMatchResultListener : public MatchResultListener {
|
||||
public:
|
||||
@ -290,6 +319,14 @@ class MatcherBase {
|
||||
explicit MatcherBase(const MatcherInterface<T>* impl)
|
||||
: impl_(impl) {}
|
||||
|
||||
template <typename U>
|
||||
explicit MatcherBase(
|
||||
const MatcherInterface<U>* impl,
|
||||
typename internal::EnableIf<
|
||||
!internal::IsSame<U, GTEST_REFERENCE_TO_CONST_(U)>::value>::type* =
|
||||
NULL)
|
||||
: impl_(new internal::MatcherInterfaceAdapter<U>(impl)) {}
|
||||
|
||||
virtual ~MatcherBase() {}
|
||||
|
||||
private:
|
||||
@ -551,21 +588,18 @@ class MatcherCastImpl {
|
||||
return CastImpl(
|
||||
polymorphic_matcher_or_value,
|
||||
BooleanConstant<
|
||||
internal::ImplicitlyConvertible<M, Matcher<T> >::value>());
|
||||
internal::ImplicitlyConvertible<M, Matcher<T> >::value>(),
|
||||
BooleanConstant<
|
||||
internal::ImplicitlyConvertible<M, T>::value>());
|
||||
}
|
||||
|
||||
private:
|
||||
static Matcher<T> CastImpl(const M& value, BooleanConstant<false>) {
|
||||
// M can't be implicitly converted to Matcher<T>, so M isn't a polymorphic
|
||||
// matcher. It must be a value then. Use direct initialization to create
|
||||
// a matcher.
|
||||
return Matcher<T>(ImplicitCast_<T>(value));
|
||||
}
|
||||
|
||||
template <bool Ignore>
|
||||
static Matcher<T> CastImpl(const M& polymorphic_matcher_or_value,
|
||||
BooleanConstant<true>) {
|
||||
BooleanConstant<true> /* convertible_to_matcher */,
|
||||
BooleanConstant<Ignore>) {
|
||||
// M is implicitly convertible to Matcher<T>, which means that either
|
||||
// M is a polymorhpic matcher or Matcher<T> has an implicit constructor
|
||||
// M is a polymorphic matcher or Matcher<T> has an implicit constructor
|
||||
// from M. In both cases using the implicit conversion will produce a
|
||||
// matcher.
|
||||
//
|
||||
@ -574,6 +608,29 @@ class MatcherCastImpl {
|
||||
// (first to create T from M and then to create Matcher<T> from T).
|
||||
return polymorphic_matcher_or_value;
|
||||
}
|
||||
|
||||
// M can't be implicitly converted to Matcher<T>, so M isn't a polymorphic
|
||||
// matcher. It's a value of a type implicitly convertible to T. Use direct
|
||||
// initialization to create a matcher.
|
||||
static Matcher<T> CastImpl(
|
||||
const M& value, BooleanConstant<false> /* convertible_to_matcher */,
|
||||
BooleanConstant<true> /* convertible_to_T */) {
|
||||
return Matcher<T>(ImplicitCast_<T>(value));
|
||||
}
|
||||
|
||||
// M can't be implicitly converted to either Matcher<T> or T. Attempt to use
|
||||
// polymorphic matcher Eq(value) in this case.
|
||||
//
|
||||
// Note that we first attempt to perform an implicit cast on the value and
|
||||
// only fall back to the polymorphic Eq() matcher afterwards because the
|
||||
// latter calls bool operator==(const Lhs& lhs, const Rhs& rhs) in the end
|
||||
// which might be undefined even when Rhs is implicitly convertible to Lhs
|
||||
// (e.g. std::pair<const int, int> vs. std::pair<int, int>).
|
||||
//
|
||||
// We don't define this method inline as we need the declaration of Eq().
|
||||
static Matcher<T> CastImpl(
|
||||
const M& value, BooleanConstant<false> /* convertible_to_matcher */,
|
||||
BooleanConstant<false> /* convertible_to_T */);
|
||||
};
|
||||
|
||||
// This more specialized version is used when MatcherCast()'s argument
|
||||
@ -2057,6 +2114,78 @@ class FloatingEqMatcher {
|
||||
GTEST_DISALLOW_ASSIGN_(FloatingEqMatcher);
|
||||
};
|
||||
|
||||
// A 2-tuple ("binary") wrapper around FloatingEqMatcher:
|
||||
// FloatingEq2Matcher() matches (x, y) by matching FloatingEqMatcher(x, false)
|
||||
// against y, and FloatingEq2Matcher(e) matches FloatingEqMatcher(x, false, e)
|
||||
// against y. The former implements "Eq", the latter "Near". At present, there
|
||||
// is no version that compares NaNs as equal.
|
||||
template <typename FloatType>
|
||||
class FloatingEq2Matcher {
|
||||
public:
|
||||
FloatingEq2Matcher() : FloatingEq2Matcher(-1, false) {}
|
||||
|
||||
explicit FloatingEq2Matcher(bool nan_eq_nan)
|
||||
: FloatingEq2Matcher(-1, nan_eq_nan) {}
|
||||
|
||||
explicit FloatingEq2Matcher(FloatType max_abs_error)
|
||||
: FloatingEq2Matcher(max_abs_error, false) {}
|
||||
|
||||
FloatingEq2Matcher(FloatType max_abs_error, bool nan_eq_nan)
|
||||
: max_abs_error_(max_abs_error),
|
||||
nan_eq_nan_(nan_eq_nan) {}
|
||||
|
||||
template <typename T1, typename T2>
|
||||
operator Matcher< ::testing::tuple<T1, T2> >() const {
|
||||
return MakeMatcher(
|
||||
new Impl< ::testing::tuple<T1, T2> >(max_abs_error_, nan_eq_nan_));
|
||||
}
|
||||
template <typename T1, typename T2>
|
||||
operator Matcher<const ::testing::tuple<T1, T2>&>() const {
|
||||
return MakeMatcher(
|
||||
new Impl<const ::testing::tuple<T1, T2>&>(max_abs_error_, nan_eq_nan_));
|
||||
}
|
||||
|
||||
private:
|
||||
static ::std::ostream& GetDesc(::std::ostream& os) { // NOLINT
|
||||
return os << "an almost-equal pair";
|
||||
}
|
||||
|
||||
template <typename Tuple>
|
||||
class Impl : public MatcherInterface<Tuple> {
|
||||
public:
|
||||
Impl(FloatType max_abs_error, bool nan_eq_nan) :
|
||||
max_abs_error_(max_abs_error),
|
||||
nan_eq_nan_(nan_eq_nan) {}
|
||||
|
||||
virtual bool MatchAndExplain(Tuple args,
|
||||
MatchResultListener* listener) const {
|
||||
if (max_abs_error_ == -1) {
|
||||
FloatingEqMatcher<FloatType> fm(::testing::get<0>(args), nan_eq_nan_);
|
||||
return static_cast<Matcher<FloatType> >(fm).MatchAndExplain(
|
||||
::testing::get<1>(args), listener);
|
||||
} else {
|
||||
FloatingEqMatcher<FloatType> fm(::testing::get<0>(args), nan_eq_nan_,
|
||||
max_abs_error_);
|
||||
return static_cast<Matcher<FloatType> >(fm).MatchAndExplain(
|
||||
::testing::get<1>(args), listener);
|
||||
}
|
||||
}
|
||||
virtual void DescribeTo(::std::ostream* os) const {
|
||||
*os << "are " << GetDesc;
|
||||
}
|
||||
virtual void DescribeNegationTo(::std::ostream* os) const {
|
||||
*os << "aren't " << GetDesc;
|
||||
}
|
||||
|
||||
private:
|
||||
FloatType max_abs_error_;
|
||||
const bool nan_eq_nan_;
|
||||
};
|
||||
|
||||
FloatType max_abs_error_;
|
||||
const bool nan_eq_nan_;
|
||||
};
|
||||
|
||||
// Implements the Pointee(m) matcher for matching a pointer whose
|
||||
// pointee matches matcher m. The pointer can be either raw or smart.
|
||||
template <typename InnerMatcher>
|
||||
@ -2953,6 +3082,50 @@ class EachMatcher {
|
||||
GTEST_DISALLOW_ASSIGN_(EachMatcher);
|
||||
};
|
||||
|
||||
struct Rank1 {};
|
||||
struct Rank0 : Rank1 {};
|
||||
|
||||
namespace pair_getters {
|
||||
#if GTEST_LANG_CXX11
|
||||
using std::get;
|
||||
template <typename T>
|
||||
auto First(T& x, Rank1) -> decltype(get<0>(x)) { // NOLINT
|
||||
return get<0>(x);
|
||||
}
|
||||
template <typename T>
|
||||
auto First(T& x, Rank0) -> decltype((x.first)) { // NOLINT
|
||||
return x.first;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
auto Second(T& x, Rank1) -> decltype(get<1>(x)) { // NOLINT
|
||||
return get<1>(x);
|
||||
}
|
||||
template <typename T>
|
||||
auto Second(T& x, Rank0) -> decltype((x.second)) { // NOLINT
|
||||
return x.second;
|
||||
}
|
||||
#else
|
||||
template <typename T>
|
||||
typename T::first_type& First(T& x, Rank0) { // NOLINT
|
||||
return x.first;
|
||||
}
|
||||
template <typename T>
|
||||
const typename T::first_type& First(const T& x, Rank0) {
|
||||
return x.first;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename T::second_type& Second(T& x, Rank0) { // NOLINT
|
||||
return x.second;
|
||||
}
|
||||
template <typename T>
|
||||
const typename T::second_type& Second(const T& x, Rank0) {
|
||||
return x.second;
|
||||
}
|
||||
#endif // GTEST_LANG_CXX11
|
||||
} // namespace pair_getters
|
||||
|
||||
// Implements Key(inner_matcher) for the given argument pair type.
|
||||
// Key(inner_matcher) matches an std::pair whose 'first' field matches
|
||||
// inner_matcher. For example, Contains(Key(Ge(5))) can be used to match an
|
||||
@ -3717,6 +3890,65 @@ class VariantMatcher {
|
||||
|
||||
} // namespace variant_matcher
|
||||
|
||||
namespace any_cast_matcher {
|
||||
|
||||
// Overloads to allow AnyCastMatcher to do proper ADL lookup.
|
||||
template <typename T>
|
||||
void any_cast() {}
|
||||
|
||||
// Implements a matcher that any_casts the value.
|
||||
template <typename T>
|
||||
class AnyCastMatcher {
|
||||
public:
|
||||
explicit AnyCastMatcher(const ::testing::Matcher<const T&>& matcher)
|
||||
: matcher_(matcher) {}
|
||||
|
||||
template <typename AnyType>
|
||||
bool MatchAndExplain(const AnyType& value,
|
||||
::testing::MatchResultListener* listener) const {
|
||||
if (!listener->IsInterested()) {
|
||||
const T* ptr = any_cast<T>(&value);
|
||||
return ptr != NULL && matcher_.Matches(*ptr);
|
||||
}
|
||||
|
||||
const T* elem = any_cast<T>(&value);
|
||||
if (elem == NULL) {
|
||||
*listener << "whose value is not of type '" << GetTypeName() << "'";
|
||||
return false;
|
||||
}
|
||||
|
||||
StringMatchResultListener elem_listener;
|
||||
const bool match = matcher_.MatchAndExplain(*elem, &elem_listener);
|
||||
*listener << "whose value " << PrintToString(*elem)
|
||||
<< (match ? " matches" : " doesn't match");
|
||||
PrintIfNotEmpty(elem_listener.str(), listener->stream());
|
||||
return match;
|
||||
}
|
||||
|
||||
void DescribeTo(std::ostream* os) const {
|
||||
*os << "is an 'any' type with value of type '" << GetTypeName()
|
||||
<< "' and the value ";
|
||||
matcher_.DescribeTo(os);
|
||||
}
|
||||
|
||||
void DescribeNegationTo(std::ostream* os) const {
|
||||
*os << "is an 'any' type with value of type other than '" << GetTypeName()
|
||||
<< "' or the value ";
|
||||
matcher_.DescribeNegationTo(os);
|
||||
}
|
||||
|
||||
private:
|
||||
static std::string GetTypeName() {
|
||||
#if GTEST_HAS_RTTI
|
||||
return internal::GetTypeName<T>();
|
||||
#endif
|
||||
return "the element type";
|
||||
}
|
||||
|
||||
const ::testing::Matcher<const T&> matcher_;
|
||||
};
|
||||
|
||||
} // namespace any_cast_matcher
|
||||
} // namespace internal
|
||||
|
||||
// ElementsAreArray(iterator_first, iterator_last)
|
||||
@ -3848,6 +4080,14 @@ inline internal::EqMatcher<T> Eq(T x) { return internal::EqMatcher<T>(x); }
|
||||
template <typename T>
|
||||
Matcher<T>::Matcher(T value) { *this = Eq(value); }
|
||||
|
||||
template <typename T, typename M>
|
||||
Matcher<T> internal::MatcherCastImpl<T, M>::CastImpl(
|
||||
const M& value,
|
||||
internal::BooleanConstant<false> /* convertible_to_matcher */,
|
||||
internal::BooleanConstant<false> /* convertible_to_T */) {
|
||||
return Eq(value);
|
||||
}
|
||||
|
||||
// Creates a monomorphic matcher that matches anything with type Lhs
|
||||
// and equal to rhs. A user may need to use this instead of Eq(...)
|
||||
// in order to resolve an overloading ambiguity.
|
||||
|
Loading…
x
Reference in New Issue
Block a user