commit
78579756a8
@ -179,6 +179,35 @@ class MatcherInterface : public MatcherDescriberInterface {
|
|||||||
// virtual void DescribeNegationTo(::std::ostream* os) const;
|
// 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.
|
// A match result listener that stores the explanation in a string.
|
||||||
class StringMatchResultListener : public MatchResultListener {
|
class StringMatchResultListener : public MatchResultListener {
|
||||||
public:
|
public:
|
||||||
@ -252,7 +281,8 @@ class MatcherBase {
|
|||||||
public:
|
public:
|
||||||
// Returns true iff the matcher matches x; also explains the match
|
// Returns true iff the matcher matches x; also explains the match
|
||||||
// result to 'listener'.
|
// result to 'listener'.
|
||||||
bool MatchAndExplain(T x, MatchResultListener* listener) const {
|
bool MatchAndExplain(GTEST_REFERENCE_TO_CONST_(T) x,
|
||||||
|
MatchResultListener* listener) const {
|
||||||
return impl_->MatchAndExplain(x, listener);
|
return impl_->MatchAndExplain(x, listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -290,6 +320,14 @@ class MatcherBase {
|
|||||||
explicit MatcherBase(const MatcherInterface<T>* impl)
|
explicit MatcherBase(const MatcherInterface<T>* impl)
|
||||||
: impl_(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() {}
|
virtual ~MatcherBase() {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -323,7 +361,13 @@ class Matcher : public internal::MatcherBase<T> {
|
|||||||
explicit Matcher() {} // NOLINT
|
explicit Matcher() {} // NOLINT
|
||||||
|
|
||||||
// Constructs a matcher from its implementation.
|
// Constructs a matcher from its implementation.
|
||||||
explicit Matcher(const MatcherInterface<T>* impl)
|
explicit Matcher(const MatcherInterface<GTEST_REFERENCE_TO_CONST_(T)>* impl)
|
||||||
|
: internal::MatcherBase<T>(impl) {}
|
||||||
|
|
||||||
|
template <typename U>
|
||||||
|
explicit Matcher(const MatcherInterface<U>* impl,
|
||||||
|
typename internal::EnableIf<!internal::IsSame<
|
||||||
|
U, GTEST_REFERENCE_TO_CONST_(U)>::value>::type* = NULL)
|
||||||
: internal::MatcherBase<T>(impl) {}
|
: internal::MatcherBase<T>(impl) {}
|
||||||
|
|
||||||
// Implicit constructor here allows people to write
|
// Implicit constructor here allows people to write
|
||||||
@ -332,64 +376,79 @@ class Matcher : public internal::MatcherBase<T> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// The following two specializations allow the user to write str
|
// The following two specializations allow the user to write str
|
||||||
// instead of Eq(str) and "foo" instead of Eq("foo") when a string
|
// instead of Eq(str) and "foo" instead of Eq("foo") when a std::string
|
||||||
// matcher is expected.
|
// matcher is expected.
|
||||||
template <>
|
template <>
|
||||||
class GTEST_API_ Matcher<const internal::string&>
|
class GTEST_API_ Matcher<const std::string&>
|
||||||
: public internal::MatcherBase<const internal::string&> {
|
: public internal::MatcherBase<const std::string&> {
|
||||||
public:
|
public:
|
||||||
Matcher() {}
|
Matcher() {}
|
||||||
|
|
||||||
explicit Matcher(const MatcherInterface<const internal::string&>* impl)
|
explicit Matcher(const MatcherInterface<const std::string&>* impl)
|
||||||
: internal::MatcherBase<const internal::string&>(impl) {}
|
: internal::MatcherBase<const std::string&>(impl) {}
|
||||||
|
|
||||||
// Allows the user to write str instead of Eq(str) sometimes, where
|
// Allows the user to write str instead of Eq(str) sometimes, where
|
||||||
// str is a string object.
|
// str is a std::string object.
|
||||||
Matcher(const internal::string& s); // NOLINT
|
Matcher(const std::string& s); // NOLINT
|
||||||
|
|
||||||
|
#if GTEST_HAS_GLOBAL_STRING
|
||||||
|
// Allows the user to write str instead of Eq(str) sometimes, where
|
||||||
|
// str is a ::string object.
|
||||||
|
Matcher(const ::string& s); // NOLINT
|
||||||
|
#endif // GTEST_HAS_GLOBAL_STRING
|
||||||
|
|
||||||
// Allows the user to write "foo" instead of Eq("foo") sometimes.
|
// Allows the user to write "foo" instead of Eq("foo") sometimes.
|
||||||
Matcher(const char* s); // NOLINT
|
Matcher(const char* s); // NOLINT
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
class GTEST_API_ Matcher<internal::string>
|
class GTEST_API_ Matcher<std::string>
|
||||||
: public internal::MatcherBase<internal::string> {
|
: public internal::MatcherBase<std::string> {
|
||||||
public:
|
public:
|
||||||
Matcher() {}
|
Matcher() {}
|
||||||
|
|
||||||
explicit Matcher(const MatcherInterface<internal::string>* impl)
|
explicit Matcher(const MatcherInterface<std::string>* impl)
|
||||||
: internal::MatcherBase<internal::string>(impl) {}
|
: internal::MatcherBase<std::string>(impl) {}
|
||||||
|
|
||||||
// Allows the user to write str instead of Eq(str) sometimes, where
|
// Allows the user to write str instead of Eq(str) sometimes, where
|
||||||
// str is a string object.
|
// str is a string object.
|
||||||
Matcher(const internal::string& s); // NOLINT
|
Matcher(const std::string& s); // NOLINT
|
||||||
|
|
||||||
|
#if GTEST_HAS_GLOBAL_STRING
|
||||||
|
// Allows the user to write str instead of Eq(str) sometimes, where
|
||||||
|
// str is a ::string object.
|
||||||
|
Matcher(const ::string& s); // NOLINT
|
||||||
|
#endif // GTEST_HAS_GLOBAL_STRING
|
||||||
|
|
||||||
// Allows the user to write "foo" instead of Eq("foo") sometimes.
|
// Allows the user to write "foo" instead of Eq("foo") sometimes.
|
||||||
Matcher(const char* s); // NOLINT
|
Matcher(const char* s); // NOLINT
|
||||||
};
|
};
|
||||||
|
|
||||||
#if GTEST_HAS_STRING_PIECE_
|
#if GTEST_HAS_GLOBAL_STRING
|
||||||
// The following two specializations allow the user to write str
|
// The following two specializations allow the user to write str
|
||||||
// instead of Eq(str) and "foo" instead of Eq("foo") when a StringPiece
|
// instead of Eq(str) and "foo" instead of Eq("foo") when a ::string
|
||||||
// matcher is expected.
|
// matcher is expected.
|
||||||
template <>
|
template <>
|
||||||
class GTEST_API_ Matcher<const StringPiece&>
|
class GTEST_API_ Matcher<const ::string&>
|
||||||
: public internal::MatcherBase<const StringPiece&> {
|
: public internal::MatcherBase<const ::string&> {
|
||||||
public:
|
public:
|
||||||
Matcher() {}
|
Matcher() {}
|
||||||
|
|
||||||
explicit Matcher(const MatcherInterface<const StringPiece&>* impl)
|
explicit Matcher(const MatcherInterface<const ::string&>* impl)
|
||||||
: internal::MatcherBase<const StringPiece&>(impl) {}
|
: internal::MatcherBase<const ::string&>(impl) {}
|
||||||
|
|
||||||
// Allows the user to write str instead of Eq(str) sometimes, where
|
// Allows the user to write str instead of Eq(str) sometimes, where
|
||||||
// str is a string object.
|
// str is a std::string object.
|
||||||
Matcher(const internal::string& s); // NOLINT
|
Matcher(const std::string& s); // NOLINT
|
||||||
|
|
||||||
|
// Allows the user to write str instead of Eq(str) sometimes, where
|
||||||
|
// str is a ::string object.
|
||||||
|
Matcher(const ::string& s); // NOLINT
|
||||||
|
|
||||||
// Allows the user to write "foo" instead of Eq("foo") sometimes.
|
// Allows the user to write "foo" instead of Eq("foo") sometimes.
|
||||||
Matcher(const char* s); // NOLINT
|
Matcher(const char* s); // NOLINT
|
||||||
|
};
|
||||||
|
|
||||||
// Allows the user to pass StringPieces directly.
|
|
||||||
Matcher(StringPiece s); // NOLINT
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
@ -530,21 +589,18 @@ class MatcherCastImpl {
|
|||||||
return CastImpl(
|
return CastImpl(
|
||||||
polymorphic_matcher_or_value,
|
polymorphic_matcher_or_value,
|
||||||
BooleanConstant<
|
BooleanConstant<
|
||||||
internal::ImplicitlyConvertible<M, Matcher<T> >::value>());
|
internal::ImplicitlyConvertible<M, Matcher<T> >::value>(),
|
||||||
|
BooleanConstant<
|
||||||
|
internal::ImplicitlyConvertible<M, T>::value>());
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static Matcher<T> CastImpl(const M& value, BooleanConstant<false>) {
|
template <bool Ignore>
|
||||||
// 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));
|
|
||||||
}
|
|
||||||
|
|
||||||
static Matcher<T> CastImpl(const M& polymorphic_matcher_or_value,
|
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 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
|
// from M. In both cases using the implicit conversion will produce a
|
||||||
// matcher.
|
// matcher.
|
||||||
//
|
//
|
||||||
@ -553,6 +609,29 @@ class MatcherCastImpl {
|
|||||||
// (first to create T from M and then to create Matcher<T> from T).
|
// (first to create T from M and then to create Matcher<T> from T).
|
||||||
return polymorphic_matcher_or_value;
|
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
|
// This more specialized version is used when MatcherCast()'s argument
|
||||||
@ -573,6 +652,22 @@ class MatcherCastImpl<T, Matcher<U> > {
|
|||||||
|
|
||||||
// We delegate the matching logic to the source matcher.
|
// We delegate the matching logic to the source matcher.
|
||||||
virtual bool MatchAndExplain(T x, MatchResultListener* listener) const {
|
virtual bool MatchAndExplain(T x, MatchResultListener* listener) const {
|
||||||
|
#if GTEST_LANG_CXX11
|
||||||
|
using FromType = typename std::remove_cv<typename std::remove_pointer<
|
||||||
|
typename std::remove_reference<T>::type>::type>::type;
|
||||||
|
using ToType = typename std::remove_cv<typename std::remove_pointer<
|
||||||
|
typename std::remove_reference<U>::type>::type>::type;
|
||||||
|
// Do not allow implicitly converting base*/& to derived*/&.
|
||||||
|
static_assert(
|
||||||
|
// Do not trigger if only one of them is a pointer. That implies a
|
||||||
|
// regular conversion and not a down_cast.
|
||||||
|
(std::is_pointer<typename std::remove_reference<T>::type>::value !=
|
||||||
|
std::is_pointer<typename std::remove_reference<U>::type>::value) ||
|
||||||
|
std::is_same<FromType, ToType>::value ||
|
||||||
|
!std::is_base_of<FromType, ToType>::value,
|
||||||
|
"Can't implicitly convert from <base> to <derived>");
|
||||||
|
#endif // GTEST_LANG_CXX11
|
||||||
|
|
||||||
return source_matcher_.MatchAndExplain(static_cast<U>(x), listener);
|
return source_matcher_.MatchAndExplain(static_cast<U>(x), listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1340,7 +1435,7 @@ class MatchesRegexMatcher {
|
|||||||
// Matches anything that can convert to std::string.
|
// Matches anything that can convert to std::string.
|
||||||
//
|
//
|
||||||
// This is a template, not just a plain function with const std::string&,
|
// This is a template, not just a plain function with const std::string&,
|
||||||
// because StringPiece has some interfering non-explicit constructors.
|
// because absl::string_view has some interfering non-explicit constructors.
|
||||||
template <class MatcheeStringType>
|
template <class MatcheeStringType>
|
||||||
bool MatchAndExplain(const MatcheeStringType& s,
|
bool MatchAndExplain(const MatcheeStringType& s,
|
||||||
MatchResultListener* /* listener */) const {
|
MatchResultListener* /* listener */) const {
|
||||||
@ -2036,6 +2131,82 @@ class FloatingEqMatcher {
|
|||||||
GTEST_DISALLOW_ASSIGN_(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() { Init(-1, false); }
|
||||||
|
|
||||||
|
explicit FloatingEq2Matcher(bool nan_eq_nan) { Init(-1, nan_eq_nan); }
|
||||||
|
|
||||||
|
explicit FloatingEq2Matcher(FloatType max_abs_error) {
|
||||||
|
Init(max_abs_error, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
FloatingEq2Matcher(FloatType max_abs_error, bool nan_eq_nan) {
|
||||||
|
Init(max_abs_error, 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_;
|
||||||
|
};
|
||||||
|
|
||||||
|
void Init(FloatType max_abs_error_val, bool nan_eq_nan_val) {
|
||||||
|
max_abs_error_ = max_abs_error_val;
|
||||||
|
nan_eq_nan_ = nan_eq_nan_val;
|
||||||
|
}
|
||||||
|
FloatType max_abs_error_;
|
||||||
|
bool nan_eq_nan_;
|
||||||
|
};
|
||||||
|
|
||||||
// Implements the Pointee(m) matcher for matching a pointer whose
|
// Implements the Pointee(m) matcher for matching a pointer whose
|
||||||
// pointee matches matcher m. The pointer can be either raw or smart.
|
// pointee matches matcher m. The pointer can be either raw or smart.
|
||||||
template <typename InnerMatcher>
|
template <typename InnerMatcher>
|
||||||
@ -2181,15 +2352,21 @@ class FieldMatcher {
|
|||||||
public:
|
public:
|
||||||
FieldMatcher(FieldType Class::*field,
|
FieldMatcher(FieldType Class::*field,
|
||||||
const Matcher<const FieldType&>& matcher)
|
const Matcher<const FieldType&>& matcher)
|
||||||
: field_(field), matcher_(matcher) {}
|
: field_(field), matcher_(matcher), whose_field_("whose given field ") {}
|
||||||
|
|
||||||
|
FieldMatcher(const std::string& field_name, FieldType Class::*field,
|
||||||
|
const Matcher<const FieldType&>& matcher)
|
||||||
|
: field_(field),
|
||||||
|
matcher_(matcher),
|
||||||
|
whose_field_("whose field `" + field_name + "` ") {}
|
||||||
|
|
||||||
void DescribeTo(::std::ostream* os) const {
|
void DescribeTo(::std::ostream* os) const {
|
||||||
*os << "is an object whose given field ";
|
*os << "is an object " << whose_field_;
|
||||||
matcher_.DescribeTo(os);
|
matcher_.DescribeTo(os);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DescribeNegationTo(::std::ostream* os) const {
|
void DescribeNegationTo(::std::ostream* os) const {
|
||||||
*os << "is an object whose given field ";
|
*os << "is an object " << whose_field_;
|
||||||
matcher_.DescribeNegationTo(os);
|
matcher_.DescribeNegationTo(os);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2207,7 +2384,7 @@ class FieldMatcher {
|
|||||||
// true_type iff the Field() matcher is used to match a pointer.
|
// true_type iff the Field() matcher is used to match a pointer.
|
||||||
bool MatchAndExplainImpl(false_type /* is_not_pointer */, const Class& obj,
|
bool MatchAndExplainImpl(false_type /* is_not_pointer */, const Class& obj,
|
||||||
MatchResultListener* listener) const {
|
MatchResultListener* listener) const {
|
||||||
*listener << "whose given field is ";
|
*listener << whose_field_ << "is ";
|
||||||
return MatchPrintAndExplain(obj.*field_, matcher_, listener);
|
return MatchPrintAndExplain(obj.*field_, matcher_, listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2226,6 +2403,10 @@ class FieldMatcher {
|
|||||||
const FieldType Class::*field_;
|
const FieldType Class::*field_;
|
||||||
const Matcher<const FieldType&> matcher_;
|
const Matcher<const FieldType&> matcher_;
|
||||||
|
|
||||||
|
// Contains either "whose given field " if the name of the field is unknown
|
||||||
|
// or "whose field `name_of_field` " if the name is known.
|
||||||
|
const std::string whose_field_;
|
||||||
|
|
||||||
GTEST_DISALLOW_ASSIGN_(FieldMatcher);
|
GTEST_DISALLOW_ASSIGN_(FieldMatcher);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2244,15 +2425,23 @@ class PropertyMatcher {
|
|||||||
typedef GTEST_REFERENCE_TO_CONST_(PropertyType) RefToConstProperty;
|
typedef GTEST_REFERENCE_TO_CONST_(PropertyType) RefToConstProperty;
|
||||||
|
|
||||||
PropertyMatcher(Property property, const Matcher<RefToConstProperty>& matcher)
|
PropertyMatcher(Property property, const Matcher<RefToConstProperty>& matcher)
|
||||||
: property_(property), matcher_(matcher) {}
|
: property_(property),
|
||||||
|
matcher_(matcher),
|
||||||
|
whose_property_("whose given property ") {}
|
||||||
|
|
||||||
|
PropertyMatcher(const std::string& property_name, Property property,
|
||||||
|
const Matcher<RefToConstProperty>& matcher)
|
||||||
|
: property_(property),
|
||||||
|
matcher_(matcher),
|
||||||
|
whose_property_("whose property `" + property_name + "` ") {}
|
||||||
|
|
||||||
void DescribeTo(::std::ostream* os) const {
|
void DescribeTo(::std::ostream* os) const {
|
||||||
*os << "is an object whose given property ";
|
*os << "is an object " << whose_property_;
|
||||||
matcher_.DescribeTo(os);
|
matcher_.DescribeTo(os);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DescribeNegationTo(::std::ostream* os) const {
|
void DescribeNegationTo(::std::ostream* os) const {
|
||||||
*os << "is an object whose given property ";
|
*os << "is an object " << whose_property_;
|
||||||
matcher_.DescribeNegationTo(os);
|
matcher_.DescribeNegationTo(os);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2270,7 +2459,7 @@ class PropertyMatcher {
|
|||||||
// true_type iff the Property() matcher is used to match a pointer.
|
// true_type iff the Property() matcher is used to match a pointer.
|
||||||
bool MatchAndExplainImpl(false_type /* is_not_pointer */, const Class& obj,
|
bool MatchAndExplainImpl(false_type /* is_not_pointer */, const Class& obj,
|
||||||
MatchResultListener* listener) const {
|
MatchResultListener* listener) const {
|
||||||
*listener << "whose given property is ";
|
*listener << whose_property_ << "is ";
|
||||||
// Cannot pass the return value (for example, int) to MatchPrintAndExplain,
|
// Cannot pass the return value (for example, int) to MatchPrintAndExplain,
|
||||||
// which takes a non-const reference as argument.
|
// which takes a non-const reference as argument.
|
||||||
#if defined(_PREFAST_ ) && _MSC_VER == 1800
|
#if defined(_PREFAST_ ) && _MSC_VER == 1800
|
||||||
@ -2299,6 +2488,10 @@ class PropertyMatcher {
|
|||||||
Property property_;
|
Property property_;
|
||||||
const Matcher<RefToConstProperty> matcher_;
|
const Matcher<RefToConstProperty> matcher_;
|
||||||
|
|
||||||
|
// Contains either "whose given property " if the name of the property is
|
||||||
|
// unknown or "whose property `name_of_property` " if the name is known.
|
||||||
|
const std::string whose_property_;
|
||||||
|
|
||||||
GTEST_DISALLOW_ASSIGN_(PropertyMatcher);
|
GTEST_DISALLOW_ASSIGN_(PropertyMatcher);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2692,6 +2885,10 @@ class WhenSortedByMatcher {
|
|||||||
// container and the RHS container respectively.
|
// container and the RHS container respectively.
|
||||||
template <typename TupleMatcher, typename RhsContainer>
|
template <typename TupleMatcher, typename RhsContainer>
|
||||||
class PointwiseMatcher {
|
class PointwiseMatcher {
|
||||||
|
GTEST_COMPILE_ASSERT_(
|
||||||
|
!IsHashTable<GTEST_REMOVE_REFERENCE_AND_CONST_(RhsContainer)>::value,
|
||||||
|
use_UnorderedPointwise_with_hash_tables);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef internal::StlContainerView<RhsContainer> RhsView;
|
typedef internal::StlContainerView<RhsContainer> RhsView;
|
||||||
typedef typename RhsView::type RhsStlContainer;
|
typedef typename RhsView::type RhsStlContainer;
|
||||||
@ -2709,6 +2906,10 @@ class PointwiseMatcher {
|
|||||||
|
|
||||||
template <typename LhsContainer>
|
template <typename LhsContainer>
|
||||||
operator Matcher<LhsContainer>() const {
|
operator Matcher<LhsContainer>() const {
|
||||||
|
GTEST_COMPILE_ASSERT_(
|
||||||
|
!IsHashTable<GTEST_REMOVE_REFERENCE_AND_CONST_(LhsContainer)>::value,
|
||||||
|
use_UnorderedPointwise_with_hash_tables);
|
||||||
|
|
||||||
return MakeMatcher(new Impl<LhsContainer>(tuple_matcher_, rhs_));
|
return MakeMatcher(new Impl<LhsContainer>(tuple_matcher_, rhs_));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2759,12 +2960,15 @@ class PointwiseMatcher {
|
|||||||
typename LhsStlContainer::const_iterator left = lhs_stl_container.begin();
|
typename LhsStlContainer::const_iterator left = lhs_stl_container.begin();
|
||||||
typename RhsStlContainer::const_iterator right = rhs_.begin();
|
typename RhsStlContainer::const_iterator right = rhs_.begin();
|
||||||
for (size_t i = 0; i != actual_size; ++i, ++left, ++right) {
|
for (size_t i = 0; i != actual_size; ++i, ++left, ++right) {
|
||||||
const InnerMatcherArg value_pair(*left, *right);
|
|
||||||
|
|
||||||
if (listener->IsInterested()) {
|
if (listener->IsInterested()) {
|
||||||
StringMatchResultListener inner_listener;
|
StringMatchResultListener inner_listener;
|
||||||
|
// Create InnerMatcherArg as a temporarily object to avoid it outlives
|
||||||
|
// *left and *right. Dereference or the conversion to `const T&` may
|
||||||
|
// return temp objects, e.g for vector<bool>.
|
||||||
if (!mono_tuple_matcher_.MatchAndExplain(
|
if (!mono_tuple_matcher_.MatchAndExplain(
|
||||||
value_pair, &inner_listener)) {
|
InnerMatcherArg(ImplicitCast_<const LhsValue&>(*left),
|
||||||
|
ImplicitCast_<const RhsValue&>(*right)),
|
||||||
|
&inner_listener)) {
|
||||||
*listener << "where the value pair (";
|
*listener << "where the value pair (";
|
||||||
UniversalPrint(*left, listener->stream());
|
UniversalPrint(*left, listener->stream());
|
||||||
*listener << ", ";
|
*listener << ", ";
|
||||||
@ -2774,7 +2978,9 @@ class PointwiseMatcher {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!mono_tuple_matcher_.Matches(value_pair))
|
if (!mono_tuple_matcher_.Matches(
|
||||||
|
InnerMatcherArg(ImplicitCast_<const LhsValue&>(*left),
|
||||||
|
ImplicitCast_<const RhsValue&>(*right))))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2932,6 +3138,50 @@ class EachMatcher {
|
|||||||
GTEST_DISALLOW_ASSIGN_(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.
|
// Implements Key(inner_matcher) for the given argument pair type.
|
||||||
// Key(inner_matcher) matches an std::pair whose 'first' field matches
|
// 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
|
// inner_matcher. For example, Contains(Key(Ge(5))) can be used to match an
|
||||||
@ -2952,8 +3202,8 @@ class KeyMatcherImpl : public MatcherInterface<PairType> {
|
|||||||
virtual bool MatchAndExplain(PairType key_value,
|
virtual bool MatchAndExplain(PairType key_value,
|
||||||
MatchResultListener* listener) const {
|
MatchResultListener* listener) const {
|
||||||
StringMatchResultListener inner_listener;
|
StringMatchResultListener inner_listener;
|
||||||
const bool match = inner_matcher_.MatchAndExplain(key_value.first,
|
const bool match = inner_matcher_.MatchAndExplain(
|
||||||
&inner_listener);
|
pair_getters::First(key_value, Rank0()), &inner_listener);
|
||||||
const std::string explanation = inner_listener.str();
|
const std::string explanation = inner_listener.str();
|
||||||
if (explanation != "") {
|
if (explanation != "") {
|
||||||
*listener << "whose first field is a value " << explanation;
|
*listener << "whose first field is a value " << explanation;
|
||||||
@ -3036,18 +3286,18 @@ class PairMatcherImpl : public MatcherInterface<PairType> {
|
|||||||
if (!listener->IsInterested()) {
|
if (!listener->IsInterested()) {
|
||||||
// If the listener is not interested, we don't need to construct the
|
// If the listener is not interested, we don't need to construct the
|
||||||
// explanation.
|
// explanation.
|
||||||
return first_matcher_.Matches(a_pair.first) &&
|
return first_matcher_.Matches(pair_getters::First(a_pair, Rank0())) &&
|
||||||
second_matcher_.Matches(a_pair.second);
|
second_matcher_.Matches(pair_getters::Second(a_pair, Rank0()));
|
||||||
}
|
}
|
||||||
StringMatchResultListener first_inner_listener;
|
StringMatchResultListener first_inner_listener;
|
||||||
if (!first_matcher_.MatchAndExplain(a_pair.first,
|
if (!first_matcher_.MatchAndExplain(pair_getters::First(a_pair, Rank0()),
|
||||||
&first_inner_listener)) {
|
&first_inner_listener)) {
|
||||||
*listener << "whose first field does not match";
|
*listener << "whose first field does not match";
|
||||||
PrintIfNotEmpty(first_inner_listener.str(), listener->stream());
|
PrintIfNotEmpty(first_inner_listener.str(), listener->stream());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
StringMatchResultListener second_inner_listener;
|
StringMatchResultListener second_inner_listener;
|
||||||
if (!second_matcher_.MatchAndExplain(a_pair.second,
|
if (!second_matcher_.MatchAndExplain(pair_getters::Second(a_pair, Rank0()),
|
||||||
&second_inner_listener)) {
|
&second_inner_listener)) {
|
||||||
*listener << "whose second field does not match";
|
*listener << "whose second field does not match";
|
||||||
PrintIfNotEmpty(second_inner_listener.str(), listener->stream());
|
PrintIfNotEmpty(second_inner_listener.str(), listener->stream());
|
||||||
@ -3494,6 +3744,11 @@ class ElementsAreMatcher {
|
|||||||
|
|
||||||
template <typename Container>
|
template <typename Container>
|
||||||
operator Matcher<Container>() const {
|
operator Matcher<Container>() const {
|
||||||
|
GTEST_COMPILE_ASSERT_(
|
||||||
|
!IsHashTable<GTEST_REMOVE_REFERENCE_AND_CONST_(Container)>::value ||
|
||||||
|
::testing::tuple_size<MatcherTuple>::value < 2,
|
||||||
|
use_UnorderedElementsAre_with_hash_tables);
|
||||||
|
|
||||||
typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer;
|
typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer;
|
||||||
typedef typename internal::StlContainerView<RawContainer>::type View;
|
typedef typename internal::StlContainerView<RawContainer>::type View;
|
||||||
typedef typename View::value_type Element;
|
typedef typename View::value_type Element;
|
||||||
@ -3542,6 +3797,10 @@ class ElementsAreArrayMatcher {
|
|||||||
|
|
||||||
template <typename Container>
|
template <typename Container>
|
||||||
operator Matcher<Container>() const {
|
operator Matcher<Container>() const {
|
||||||
|
GTEST_COMPILE_ASSERT_(
|
||||||
|
!IsHashTable<GTEST_REMOVE_REFERENCE_AND_CONST_(Container)>::value,
|
||||||
|
use_UnorderedElementsAreArray_with_hash_tables);
|
||||||
|
|
||||||
return MakeMatcher(new ElementsAreMatcherImpl<Container>(
|
return MakeMatcher(new ElementsAreMatcherImpl<Container>(
|
||||||
matchers_.begin(), matchers_.end()));
|
matchers_.begin(), matchers_.end()));
|
||||||
}
|
}
|
||||||
@ -3636,6 +3895,61 @@ GTEST_API_ std::string FormatMatcherDescription(bool negation,
|
|||||||
const char* matcher_name,
|
const char* matcher_name,
|
||||||
const Strings& param_values);
|
const Strings& param_values);
|
||||||
|
|
||||||
|
// Implements a matcher that checks the value of a optional<> type variable.
|
||||||
|
template <typename ValueMatcher>
|
||||||
|
class OptionalMatcher {
|
||||||
|
public:
|
||||||
|
explicit OptionalMatcher(const ValueMatcher& value_matcher)
|
||||||
|
: value_matcher_(value_matcher) {}
|
||||||
|
|
||||||
|
template <typename Optional>
|
||||||
|
operator Matcher<Optional>() const {
|
||||||
|
return MakeMatcher(new Impl<Optional>(value_matcher_));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Optional>
|
||||||
|
class Impl : public MatcherInterface<Optional> {
|
||||||
|
public:
|
||||||
|
typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Optional) OptionalView;
|
||||||
|
typedef typename OptionalView::value_type ValueType;
|
||||||
|
explicit Impl(const ValueMatcher& value_matcher)
|
||||||
|
: value_matcher_(MatcherCast<ValueType>(value_matcher)) {}
|
||||||
|
|
||||||
|
virtual void DescribeTo(::std::ostream* os) const {
|
||||||
|
*os << "value ";
|
||||||
|
value_matcher_.DescribeTo(os);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void DescribeNegationTo(::std::ostream* os) const {
|
||||||
|
*os << "value ";
|
||||||
|
value_matcher_.DescribeNegationTo(os);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool MatchAndExplain(Optional optional,
|
||||||
|
MatchResultListener* listener) const {
|
||||||
|
if (!optional) {
|
||||||
|
*listener << "which is not engaged";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const ValueType& value = *optional;
|
||||||
|
StringMatchResultListener value_listener;
|
||||||
|
const bool match = value_matcher_.MatchAndExplain(value, &value_listener);
|
||||||
|
*listener << "whose value " << PrintToString(value)
|
||||||
|
<< (match ? " matches" : " doesn't match");
|
||||||
|
PrintIfNotEmpty(value_listener.str(), listener->stream());
|
||||||
|
return match;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const Matcher<ValueType> value_matcher_;
|
||||||
|
GTEST_DISALLOW_ASSIGN_(Impl);
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
const ValueMatcher value_matcher_;
|
||||||
|
GTEST_DISALLOW_ASSIGN_(OptionalMatcher);
|
||||||
|
};
|
||||||
|
|
||||||
namespace variant_matcher {
|
namespace variant_matcher {
|
||||||
// Overloads to allow VariantMatcher to do proper ADL lookup.
|
// Overloads to allow VariantMatcher to do proper ADL lookup.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -3684,7 +3998,7 @@ class VariantMatcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static string GetTypeName() {
|
static std::string GetTypeName() {
|
||||||
#if GTEST_HAS_RTTI
|
#if GTEST_HAS_RTTI
|
||||||
return internal::GetTypeName<T>();
|
return internal::GetTypeName<T>();
|
||||||
#endif
|
#endif
|
||||||
@ -3696,6 +4010,65 @@ class VariantMatcher {
|
|||||||
|
|
||||||
} // namespace variant_matcher
|
} // 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
|
} // namespace internal
|
||||||
|
|
||||||
// ElementsAreArray(iterator_first, iterator_last)
|
// ElementsAreArray(iterator_first, iterator_last)
|
||||||
@ -3827,6 +4200,14 @@ inline internal::EqMatcher<T> Eq(T x) { return internal::EqMatcher<T>(x); }
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
Matcher<T>::Matcher(T value) { *this = Eq(value); }
|
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
|
// Creates a monomorphic matcher that matches anything with type Lhs
|
||||||
// and equal to rhs. A user may need to use this instead of Eq(...)
|
// and equal to rhs. A user may need to use this instead of Eq(...)
|
||||||
// in order to resolve an overloading ambiguity.
|
// in order to resolve an overloading ambiguity.
|
||||||
@ -3985,6 +4366,16 @@ inline PolymorphicMatcher<
|
|||||||
// to compile where bar is an int32 and m is a matcher for int64.
|
// to compile where bar is an int32 and m is a matcher for int64.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Same as Field() but also takes the name of the field to provide better error
|
||||||
|
// messages.
|
||||||
|
template <typename Class, typename FieldType, typename FieldMatcher>
|
||||||
|
inline PolymorphicMatcher<internal::FieldMatcher<Class, FieldType> > Field(
|
||||||
|
const std::string& field_name, FieldType Class::*field,
|
||||||
|
const FieldMatcher& matcher) {
|
||||||
|
return MakePolymorphicMatcher(internal::FieldMatcher<Class, FieldType>(
|
||||||
|
field_name, field, MatcherCast<const FieldType&>(matcher)));
|
||||||
|
}
|
||||||
|
|
||||||
// Creates a matcher that matches an object whose given property
|
// Creates a matcher that matches an object whose given property
|
||||||
// matches 'matcher'. For example,
|
// matches 'matcher'. For example,
|
||||||
// Property(&Foo::str, StartsWith("hi"))
|
// Property(&Foo::str, StartsWith("hi"))
|
||||||
@ -4005,6 +4396,21 @@ Property(PropertyType (Class::*property)() const,
|
|||||||
// to compile where bar() returns an int32 and m is a matcher for int64.
|
// to compile where bar() returns an int32 and m is a matcher for int64.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Same as Property() above, but also takes the name of the property to provide
|
||||||
|
// better error messages.
|
||||||
|
template <typename Class, typename PropertyType, typename PropertyMatcher>
|
||||||
|
inline PolymorphicMatcher<internal::PropertyMatcher<
|
||||||
|
Class, PropertyType, PropertyType (Class::*)() const> >
|
||||||
|
Property(const std::string& property_name,
|
||||||
|
PropertyType (Class::*property)() const,
|
||||||
|
const PropertyMatcher& matcher) {
|
||||||
|
return MakePolymorphicMatcher(
|
||||||
|
internal::PropertyMatcher<Class, PropertyType,
|
||||||
|
PropertyType (Class::*)() const>(
|
||||||
|
property_name, property,
|
||||||
|
MatcherCast<GTEST_REFERENCE_TO_CONST_(PropertyType)>(matcher)));
|
||||||
|
}
|
||||||
|
|
||||||
#if GTEST_LANG_CXX11
|
#if GTEST_LANG_CXX11
|
||||||
// The same as above but for reference-qualified member functions.
|
// The same as above but for reference-qualified member functions.
|
||||||
template <typename Class, typename PropertyType, typename PropertyMatcher>
|
template <typename Class, typename PropertyType, typename PropertyMatcher>
|
||||||
@ -4033,6 +4439,7 @@ Property(PropertyType (Class::*property)() const &,
|
|||||||
// concurrent access.
|
// concurrent access.
|
||||||
// * If it is a function object, it has to define type result_type.
|
// * If it is a function object, it has to define type result_type.
|
||||||
// We recommend deriving your functor classes from std::unary_function.
|
// We recommend deriving your functor classes from std::unary_function.
|
||||||
|
//
|
||||||
template <typename Callable, typename ResultOfMatcher>
|
template <typename Callable, typename ResultOfMatcher>
|
||||||
internal::ResultOfMatcher<Callable> ResultOf(
|
internal::ResultOfMatcher<Callable> ResultOf(
|
||||||
Callable callable, const ResultOfMatcher& matcher) {
|
Callable callable, const ResultOfMatcher& matcher) {
|
||||||
@ -4123,53 +4530,53 @@ inline PolymorphicMatcher<internal::MatchesRegexMatcher> ContainsRegex(
|
|||||||
// Wide string matchers.
|
// Wide string matchers.
|
||||||
|
|
||||||
// Matches a string equal to str.
|
// Matches a string equal to str.
|
||||||
inline PolymorphicMatcher<internal::StrEqualityMatcher<internal::wstring> >
|
inline PolymorphicMatcher<internal::StrEqualityMatcher<std::wstring> > StrEq(
|
||||||
StrEq(const internal::wstring& str) {
|
const std::wstring& str) {
|
||||||
return MakePolymorphicMatcher(internal::StrEqualityMatcher<internal::wstring>(
|
return MakePolymorphicMatcher(
|
||||||
str, true, true));
|
internal::StrEqualityMatcher<std::wstring>(str, true, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Matches a string not equal to str.
|
// Matches a string not equal to str.
|
||||||
inline PolymorphicMatcher<internal::StrEqualityMatcher<internal::wstring> >
|
inline PolymorphicMatcher<internal::StrEqualityMatcher<std::wstring> > StrNe(
|
||||||
StrNe(const internal::wstring& str) {
|
const std::wstring& str) {
|
||||||
return MakePolymorphicMatcher(internal::StrEqualityMatcher<internal::wstring>(
|
return MakePolymorphicMatcher(
|
||||||
str, false, true));
|
internal::StrEqualityMatcher<std::wstring>(str, false, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Matches a string equal to str, ignoring case.
|
// Matches a string equal to str, ignoring case.
|
||||||
inline PolymorphicMatcher<internal::StrEqualityMatcher<internal::wstring> >
|
inline PolymorphicMatcher<internal::StrEqualityMatcher<std::wstring> >
|
||||||
StrCaseEq(const internal::wstring& str) {
|
StrCaseEq(const std::wstring& str) {
|
||||||
return MakePolymorphicMatcher(internal::StrEqualityMatcher<internal::wstring>(
|
return MakePolymorphicMatcher(
|
||||||
str, true, false));
|
internal::StrEqualityMatcher<std::wstring>(str, true, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Matches a string not equal to str, ignoring case.
|
// Matches a string not equal to str, ignoring case.
|
||||||
inline PolymorphicMatcher<internal::StrEqualityMatcher<internal::wstring> >
|
inline PolymorphicMatcher<internal::StrEqualityMatcher<std::wstring> >
|
||||||
StrCaseNe(const internal::wstring& str) {
|
StrCaseNe(const std::wstring& str) {
|
||||||
return MakePolymorphicMatcher(internal::StrEqualityMatcher<internal::wstring>(
|
return MakePolymorphicMatcher(
|
||||||
str, false, false));
|
internal::StrEqualityMatcher<std::wstring>(str, false, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a matcher that matches any wstring, std::wstring, or C wide string
|
// Creates a matcher that matches any ::wstring, std::wstring, or C wide string
|
||||||
// that contains the given substring.
|
// that contains the given substring.
|
||||||
inline PolymorphicMatcher<internal::HasSubstrMatcher<internal::wstring> >
|
inline PolymorphicMatcher<internal::HasSubstrMatcher<std::wstring> > HasSubstr(
|
||||||
HasSubstr(const internal::wstring& substring) {
|
const std::wstring& substring) {
|
||||||
return MakePolymorphicMatcher(internal::HasSubstrMatcher<internal::wstring>(
|
return MakePolymorphicMatcher(
|
||||||
substring));
|
internal::HasSubstrMatcher<std::wstring>(substring));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Matches a string that starts with 'prefix' (case-sensitive).
|
// Matches a string that starts with 'prefix' (case-sensitive).
|
||||||
inline PolymorphicMatcher<internal::StartsWithMatcher<internal::wstring> >
|
inline PolymorphicMatcher<internal::StartsWithMatcher<std::wstring> >
|
||||||
StartsWith(const internal::wstring& prefix) {
|
StartsWith(const std::wstring& prefix) {
|
||||||
return MakePolymorphicMatcher(internal::StartsWithMatcher<internal::wstring>(
|
return MakePolymorphicMatcher(
|
||||||
prefix));
|
internal::StartsWithMatcher<std::wstring>(prefix));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Matches a string that ends with 'suffix' (case-sensitive).
|
// Matches a string that ends with 'suffix' (case-sensitive).
|
||||||
inline PolymorphicMatcher<internal::EndsWithMatcher<internal::wstring> >
|
inline PolymorphicMatcher<internal::EndsWithMatcher<std::wstring> > EndsWith(
|
||||||
EndsWith(const internal::wstring& suffix) {
|
const std::wstring& suffix) {
|
||||||
return MakePolymorphicMatcher(internal::EndsWithMatcher<internal::wstring>(
|
return MakePolymorphicMatcher(
|
||||||
suffix));
|
internal::EndsWithMatcher<std::wstring>(suffix));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // GTEST_HAS_GLOBAL_WSTRING || GTEST_HAS_STD_WSTRING
|
#endif // GTEST_HAS_GLOBAL_WSTRING || GTEST_HAS_STD_WSTRING
|
||||||
@ -4198,6 +4605,58 @@ inline internal::Lt2Matcher Lt() { return internal::Lt2Matcher(); }
|
|||||||
// first field != the second field.
|
// first field != the second field.
|
||||||
inline internal::Ne2Matcher Ne() { return internal::Ne2Matcher(); }
|
inline internal::Ne2Matcher Ne() { return internal::Ne2Matcher(); }
|
||||||
|
|
||||||
|
// Creates a polymorphic matcher that matches a 2-tuple where
|
||||||
|
// FloatEq(first field) matches the second field.
|
||||||
|
inline internal::FloatingEq2Matcher<float> FloatEq() {
|
||||||
|
return internal::FloatingEq2Matcher<float>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a polymorphic matcher that matches a 2-tuple where
|
||||||
|
// DoubleEq(first field) matches the second field.
|
||||||
|
inline internal::FloatingEq2Matcher<double> DoubleEq() {
|
||||||
|
return internal::FloatingEq2Matcher<double>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a polymorphic matcher that matches a 2-tuple where
|
||||||
|
// FloatEq(first field) matches the second field with NaN equality.
|
||||||
|
inline internal::FloatingEq2Matcher<float> NanSensitiveFloatEq() {
|
||||||
|
return internal::FloatingEq2Matcher<float>(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a polymorphic matcher that matches a 2-tuple where
|
||||||
|
// DoubleEq(first field) matches the second field with NaN equality.
|
||||||
|
inline internal::FloatingEq2Matcher<double> NanSensitiveDoubleEq() {
|
||||||
|
return internal::FloatingEq2Matcher<double>(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a polymorphic matcher that matches a 2-tuple where
|
||||||
|
// FloatNear(first field, max_abs_error) matches the second field.
|
||||||
|
inline internal::FloatingEq2Matcher<float> FloatNear(float max_abs_error) {
|
||||||
|
return internal::FloatingEq2Matcher<float>(max_abs_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a polymorphic matcher that matches a 2-tuple where
|
||||||
|
// DoubleNear(first field, max_abs_error) matches the second field.
|
||||||
|
inline internal::FloatingEq2Matcher<double> DoubleNear(double max_abs_error) {
|
||||||
|
return internal::FloatingEq2Matcher<double>(max_abs_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a polymorphic matcher that matches a 2-tuple where
|
||||||
|
// FloatNear(first field, max_abs_error) matches the second field with NaN
|
||||||
|
// equality.
|
||||||
|
inline internal::FloatingEq2Matcher<float> NanSensitiveFloatNear(
|
||||||
|
float max_abs_error) {
|
||||||
|
return internal::FloatingEq2Matcher<float>(max_abs_error, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a polymorphic matcher that matches a 2-tuple where
|
||||||
|
// DoubleNear(first field, max_abs_error) matches the second field with NaN
|
||||||
|
// equality.
|
||||||
|
inline internal::FloatingEq2Matcher<double> NanSensitiveDoubleNear(
|
||||||
|
double max_abs_error) {
|
||||||
|
return internal::FloatingEq2Matcher<double>(max_abs_error, true);
|
||||||
|
}
|
||||||
|
|
||||||
// Creates a matcher that matches any value of type T that m doesn't
|
// Creates a matcher that matches any value of type T that m doesn't
|
||||||
// match.
|
// match.
|
||||||
template <typename InnerMatcher>
|
template <typename InnerMatcher>
|
||||||
@ -4575,6 +5034,28 @@ inline bool ExplainMatchResult(
|
|||||||
return SafeMatcherCast<const T&>(matcher).MatchAndExplain(value, listener);
|
return SafeMatcherCast<const T&>(matcher).MatchAndExplain(value, listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns a string representation of the given matcher. Useful for description
|
||||||
|
// strings of matchers defined using MATCHER_P* macros that accept matchers as
|
||||||
|
// their arguments. For example:
|
||||||
|
//
|
||||||
|
// MATCHER_P(XAndYThat, matcher,
|
||||||
|
// "X that " + DescribeMatcher<int>(matcher, negation) +
|
||||||
|
// " and Y that " + DescribeMatcher<double>(matcher, negation)) {
|
||||||
|
// return ExplainMatchResult(matcher, arg.x(), result_listener) &&
|
||||||
|
// ExplainMatchResult(matcher, arg.y(), result_listener);
|
||||||
|
// }
|
||||||
|
template <typename T, typename M>
|
||||||
|
std::string DescribeMatcher(const M& matcher, bool negation = false) {
|
||||||
|
::std::stringstream ss;
|
||||||
|
Matcher<T> monomorphic_matcher = SafeMatcherCast<T>(matcher);
|
||||||
|
if (negation) {
|
||||||
|
monomorphic_matcher.DescribeNegationTo(&ss);
|
||||||
|
} else {
|
||||||
|
monomorphic_matcher.DescribeTo(&ss);
|
||||||
|
}
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
#if GTEST_LANG_CXX11
|
#if GTEST_LANG_CXX11
|
||||||
// Define variadic matcher versions. They are overloaded in
|
// Define variadic matcher versions. They are overloaded in
|
||||||
// gmock-generated-matchers.h for the cases supported by pre C++11 compilers.
|
// gmock-generated-matchers.h for the cases supported by pre C++11 compilers.
|
||||||
@ -4600,6 +5081,28 @@ inline internal::AnyOfMatcher<Args...> AnyOf(const Args&... matchers) {
|
|||||||
template <typename InnerMatcher>
|
template <typename InnerMatcher>
|
||||||
inline InnerMatcher AllArgs(const InnerMatcher& matcher) { return matcher; }
|
inline InnerMatcher AllArgs(const InnerMatcher& matcher) { return matcher; }
|
||||||
|
|
||||||
|
// Returns a matcher that matches the value of an optional<> type variable.
|
||||||
|
// The matcher implementation only uses '!arg' and requires that the optional<>
|
||||||
|
// type has a 'value_type' member type and that '*arg' is of type 'value_type'
|
||||||
|
// and is printable using 'PrintToString'. It is compatible with
|
||||||
|
// std::optional/std::experimental::optional.
|
||||||
|
// Note that to compare an optional type variable against nullopt you should
|
||||||
|
// use Eq(nullopt) and not Optional(Eq(nullopt)). The latter implies that the
|
||||||
|
// optional value contains an optional itself.
|
||||||
|
template <typename ValueMatcher>
|
||||||
|
inline internal::OptionalMatcher<ValueMatcher> Optional(
|
||||||
|
const ValueMatcher& value_matcher) {
|
||||||
|
return internal::OptionalMatcher<ValueMatcher>(value_matcher);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a matcher that matches the value of a absl::any type variable.
|
||||||
|
template <typename T>
|
||||||
|
PolymorphicMatcher<internal::any_cast_matcher::AnyCastMatcher<T> > AnyWith(
|
||||||
|
const Matcher<const T&>& matcher) {
|
||||||
|
return MakePolymorphicMatcher(
|
||||||
|
internal::any_cast_matcher::AnyCastMatcher<T>(matcher));
|
||||||
|
}
|
||||||
|
|
||||||
// Returns a matcher that matches the value of a variant<> type variable.
|
// Returns a matcher that matches the value of a variant<> type variable.
|
||||||
// The matcher implementation uses ADL to find the holds_alternative and get
|
// The matcher implementation uses ADL to find the holds_alternative and get
|
||||||
// functions.
|
// functions.
|
||||||
@ -4626,4 +5129,5 @@ PolymorphicMatcher<internal::variant_matcher::VariantMatcher<T> > VariantWith(
|
|||||||
// We must include this header at the end to make sure it can use the
|
// We must include this header at the end to make sure it can use the
|
||||||
// declarations from this file.
|
// declarations from this file.
|
||||||
#include "gmock/internal/custom/gmock-matchers.h"
|
#include "gmock/internal/custom/gmock-matchers.h"
|
||||||
|
|
||||||
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_MATCHERS_H_
|
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_MATCHERS_H_
|
||||||
|
@ -44,60 +44,67 @@
|
|||||||
|
|
||||||
namespace testing {
|
namespace testing {
|
||||||
|
|
||||||
// Constructs a matcher that matches a const string& whose value is
|
// Constructs a matcher that matches a const std::string& whose value is
|
||||||
// equal to s.
|
// equal to s.
|
||||||
Matcher<const internal::string&>::Matcher(const internal::string& s) {
|
Matcher<const std::string&>::Matcher(const std::string& s) { *this = Eq(s); }
|
||||||
*this = Eq(s);
|
|
||||||
|
#if GTEST_HAS_GLOBAL_STRING
|
||||||
|
// Constructs a matcher that matches a const std::string& whose value is
|
||||||
|
// equal to s.
|
||||||
|
Matcher<const std::string&>::Matcher(const ::string& s) {
|
||||||
|
*this = Eq(static_cast<std::string>(s));
|
||||||
|
}
|
||||||
|
#endif // GTEST_HAS_GLOBAL_STRING
|
||||||
|
|
||||||
|
// Constructs a matcher that matches a const std::string& whose value is
|
||||||
|
// equal to s.
|
||||||
|
Matcher<const std::string&>::Matcher(const char* s) {
|
||||||
|
*this = Eq(std::string(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Constructs a matcher that matches a const string& whose value is
|
// Constructs a matcher that matches a std::string whose value is equal to
|
||||||
// equal to s.
|
// s.
|
||||||
Matcher<const internal::string&>::Matcher(const char* s) {
|
Matcher<std::string>::Matcher(const std::string& s) { *this = Eq(s); }
|
||||||
*this = Eq(internal::string(s));
|
|
||||||
|
#if GTEST_HAS_GLOBAL_STRING
|
||||||
|
// Constructs a matcher that matches a std::string whose value is equal to
|
||||||
|
// s.
|
||||||
|
Matcher<std::string>::Matcher(const ::string& s) {
|
||||||
|
*this = Eq(static_cast<std::string>(s));
|
||||||
}
|
}
|
||||||
|
#endif // GTEST_HAS_GLOBAL_STRING
|
||||||
|
|
||||||
|
// Constructs a matcher that matches a std::string whose value is equal to
|
||||||
|
// s.
|
||||||
|
Matcher<std::string>::Matcher(const char* s) { *this = Eq(std::string(s)); }
|
||||||
|
|
||||||
|
#if GTEST_HAS_GLOBAL_STRING
|
||||||
|
// Constructs a matcher that matches a const ::string& whose value is
|
||||||
|
// equal to s.
|
||||||
|
Matcher<const ::string&>::Matcher(const std::string& s) {
|
||||||
|
*this = Eq(static_cast<::string>(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructs a matcher that matches a const ::string& whose value is
|
||||||
|
// equal to s.
|
||||||
|
Matcher<const ::string&>::Matcher(const ::string& s) { *this = Eq(s); }
|
||||||
|
|
||||||
|
// Constructs a matcher that matches a const ::string& whose value is
|
||||||
|
// equal to s.
|
||||||
|
Matcher<const ::string&>::Matcher(const char* s) { *this = Eq(::string(s)); }
|
||||||
|
|
||||||
|
// Constructs a matcher that matches a ::string whose value is equal to s.
|
||||||
|
Matcher<::string>::Matcher(const std::string& s) {
|
||||||
|
*this = Eq(static_cast<::string>(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructs a matcher that matches a ::string whose value is equal to s.
|
||||||
|
Matcher<::string>::Matcher(const ::string& s) { *this = Eq(s); }
|
||||||
|
|
||||||
// Constructs a matcher that matches a string whose value is equal to s.
|
// Constructs a matcher that matches a string whose value is equal to s.
|
||||||
Matcher<internal::string>::Matcher(const internal::string& s) { *this = Eq(s); }
|
Matcher<::string>::Matcher(const char* s) { *this = Eq(::string(s)); }
|
||||||
|
#endif // GTEST_HAS_GLOBAL_STRING
|
||||||
|
|
||||||
// Constructs a matcher that matches a string whose value is equal to s.
|
|
||||||
Matcher<internal::string>::Matcher(const char* s) {
|
|
||||||
*this = Eq(internal::string(s));
|
|
||||||
}
|
|
||||||
|
|
||||||
#if GTEST_HAS_STRING_PIECE_
|
|
||||||
// Constructs a matcher that matches a const StringPiece& whose value is
|
|
||||||
// equal to s.
|
|
||||||
Matcher<const StringPiece&>::Matcher(const internal::string& s) {
|
|
||||||
*this = Eq(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Constructs a matcher that matches a const StringPiece& whose value is
|
|
||||||
// equal to s.
|
|
||||||
Matcher<const StringPiece&>::Matcher(const char* s) {
|
|
||||||
*this = Eq(internal::string(s));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Constructs a matcher that matches a const StringPiece& whose value is
|
|
||||||
// equal to s.
|
|
||||||
Matcher<const StringPiece&>::Matcher(StringPiece s) {
|
|
||||||
*this = Eq(s.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Constructs a matcher that matches a StringPiece whose value is equal to s.
|
|
||||||
Matcher<StringPiece>::Matcher(const internal::string& s) {
|
|
||||||
*this = Eq(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Constructs a matcher that matches a StringPiece whose value is equal to s.
|
|
||||||
Matcher<StringPiece>::Matcher(const char* s) {
|
|
||||||
*this = Eq(internal::string(s));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Constructs a matcher that matches a StringPiece whose value is equal to s.
|
|
||||||
Matcher<StringPiece>::Matcher(StringPiece s) {
|
|
||||||
*this = Eq(s.ToString());
|
|
||||||
}
|
|
||||||
#endif // GTEST_HAS_STRING_PIECE_
|
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
|
@ -44,7 +44,15 @@
|
|||||||
#include "gmock/internal/gmock-port.h"
|
#include "gmock/internal/gmock-port.h"
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
#include "gtest/gtest-spi.h"
|
#include "gtest/gtest-spi.h"
|
||||||
|
|
||||||
|
// Indicates that this translation unit is part of Google Test's
|
||||||
|
// implementation. It must come before gtest-internal-inl.h is
|
||||||
|
// included, or there will be a compiler error. This trick is to
|
||||||
|
// prevent a user from accidentally including gtest-internal-inl.h in
|
||||||
|
// their code.
|
||||||
|
#define GTEST_IMPLEMENTATION_ 1
|
||||||
#include "src/gtest-internal-inl.h"
|
#include "src/gtest-internal-inl.h"
|
||||||
|
#undef GTEST_IMPLEMENTATION_
|
||||||
|
|
||||||
#if GTEST_OS_CYGWIN
|
#if GTEST_OS_CYGWIN
|
||||||
# include <sys/types.h> // For ssize_t. NOLINT
|
# include <sys/types.h> // For ssize_t. NOLINT
|
||||||
@ -61,6 +69,26 @@ namespace internal {
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
TEST(JoinAsTupleTest, JoinsEmptyTuple) {
|
||||||
|
EXPECT_EQ("", JoinAsTuple(Strings()));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(JoinAsTupleTest, JoinsOneTuple) {
|
||||||
|
const char* fields[] = {"1"};
|
||||||
|
EXPECT_EQ("1", JoinAsTuple(Strings(fields, fields + 1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(JoinAsTupleTest, JoinsTwoTuple) {
|
||||||
|
const char* fields[] = {"1", "a"};
|
||||||
|
EXPECT_EQ("(1, a)", JoinAsTuple(Strings(fields, fields + 2)));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(JoinAsTupleTest, JoinsTenTuple) {
|
||||||
|
const char* fields[] = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10"};
|
||||||
|
EXPECT_EQ("(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)",
|
||||||
|
JoinAsTuple(Strings(fields, fields + 10)));
|
||||||
|
}
|
||||||
|
|
||||||
TEST(ConvertIdentifierNameToWordsTest, WorksWhenNameContainsNoWord) {
|
TEST(ConvertIdentifierNameToWordsTest, WorksWhenNameContainsNoWord) {
|
||||||
EXPECT_EQ("", ConvertIdentifierNameToWords(""));
|
EXPECT_EQ("", ConvertIdentifierNameToWords(""));
|
||||||
EXPECT_EQ("", ConvertIdentifierNameToWords("_"));
|
EXPECT_EQ("", ConvertIdentifierNameToWords("_"));
|
||||||
|
@ -47,6 +47,7 @@ using testing::NaggyMock;
|
|||||||
using testing::Ref;
|
using testing::Ref;
|
||||||
using testing::Return;
|
using testing::Return;
|
||||||
using testing::Sequence;
|
using testing::Sequence;
|
||||||
|
using testing::Value;
|
||||||
|
|
||||||
class MockFoo {
|
class MockFoo {
|
||||||
public:
|
public:
|
||||||
@ -268,6 +269,10 @@ TEST_F(GMockOutputTest, CatchesLeakedMocks) {
|
|||||||
// Both foo1 and foo2 are deliberately leaked.
|
// Both foo1 and foo2 are deliberately leaked.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MATCHER_P2(IsPair, first, second, "") {
|
||||||
|
return Value(arg.first, first) && Value(arg.second, second);
|
||||||
|
}
|
||||||
|
|
||||||
void TestCatchesLeakedMocksInAdHocTests() {
|
void TestCatchesLeakedMocksInAdHocTests() {
|
||||||
MockFoo* foo = new MockFoo;
|
MockFoo* foo = new MockFoo;
|
||||||
|
|
||||||
@ -280,7 +285,6 @@ void TestCatchesLeakedMocksInAdHocTests() {
|
|||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
testing::InitGoogleMock(&argc, argv);
|
testing::InitGoogleMock(&argc, argv);
|
||||||
|
|
||||||
// Ensures that the tests pass no matter what value of
|
// Ensures that the tests pass no matter what value of
|
||||||
// --gmock_catch_leaked_mocks and --gmock_verbose the user specifies.
|
// --gmock_catch_leaked_mocks and --gmock_verbose the user specifies.
|
||||||
testing::GMOCK_FLAG(catch_leaked_mocks) = true;
|
testing::GMOCK_FLAG(catch_leaked_mocks) = true;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user