"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "googlemock/include/gmock/gmock-matchers.h" between
googletest-release-1.11.0.tar.gz and googletest-release-1.12.0.tar.gz

About: GoogleTest is Google's (unit) testing and mocking framework for C++ tests.

gmock-matchers.h  (googletest-release-1.11.0):gmock-matchers.h  (googletest-release-1.12.0)
skipping to change at line 252 skipping to change at line 252
// on // on
// https://github.com/google/googletest/blob/master/docs/gmock_cook_book.md // https://github.com/google/googletest/blob/master/docs/gmock_cook_book.md
// //
// This file also implements some commonly used argument matchers. More // This file also implements some commonly used argument matchers. More
// matchers can be defined by the user implementing the // matchers can be defined by the user implementing the
// MatcherInterface<T> interface if necessary. // MatcherInterface<T> interface if necessary.
// //
// See googletest/include/gtest/gtest-matchers.h for the definition of class // See googletest/include/gtest/gtest-matchers.h for the definition of class
// Matcher, class MatcherInterface, and others. // Matcher, class MatcherInterface, and others.
// GOOGLETEST_CM0002 DO NOT DELETE // IWYU pragma: private, include "gmock/gmock.h"
// IWYU pragma: friend gmock/.*
#ifndef GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_MATCHERS_H_ #ifndef GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_MATCHERS_H_
#define GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_MATCHERS_H_ #define GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_MATCHERS_H_
#include <algorithm> #include <algorithm>
#include <cmath> #include <cmath>
#include <initializer_list> #include <initializer_list>
#include <iterator> #include <iterator>
#include <limits> #include <limits>
#include <memory> #include <memory>
skipping to change at line 315 skipping to change at line 316
// Returns the explanation accumulated so far. // Returns the explanation accumulated so far.
std::string str() const { return ss_.str(); } std::string str() const { return ss_.str(); }
// Clears the explanation accumulated so far. // Clears the explanation accumulated so far.
void Clear() { ss_.str(""); } void Clear() { ss_.str(""); }
private: private:
::std::stringstream ss_; ::std::stringstream ss_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(StringMatchResultListener); StringMatchResultListener(const StringMatchResultListener&) = delete;
StringMatchResultListener& operator=(const StringMatchResultListener&) =
delete;
}; };
// Anything inside the 'internal' namespace IS INTERNAL IMPLEMENTATION // Anything inside the 'internal' namespace IS INTERNAL IMPLEMENTATION
// and MUST NOT BE USED IN USER CODE!!! // and MUST NOT BE USED IN USER CODE!!!
namespace internal { namespace internal {
// The MatcherCastImpl class template is a helper for implementing // The MatcherCastImpl class template is a helper for implementing
// MatcherCast(). We need this helper in order to partially // MatcherCast(). We need this helper in order to partially
// specialize the implementation of MatcherCast() (C++ allows // specialize the implementation of MatcherCast() (C++ allows
// class/struct templates to be partially specialized, but not // class/struct templates to be partially specialized, but not
skipping to change at line 398 skipping to change at line 401
// We don't define this method inline as we need the declaration of Eq(). // We don't define this method inline as we need the declaration of Eq().
static Matcher<T> CastImpl(const M& value, static Matcher<T> CastImpl(const M& value,
std::false_type /* convertible_to_matcher */, std::false_type /* convertible_to_matcher */,
std::false_type /* convertible_to_T */); std::false_type /* convertible_to_T */);
}; };
// This more specialized version is used when MatcherCast()'s argument // This more specialized version is used when MatcherCast()'s argument
// is already a Matcher. This only compiles when type T can be // is already a Matcher. This only compiles when type T can be
// statically converted to type U. // statically converted to type U.
template <typename T, typename U> template <typename T, typename U>
class MatcherCastImpl<T, Matcher<U> > { class MatcherCastImpl<T, Matcher<U>> {
public: public:
static Matcher<T> Cast(const Matcher<U>& source_matcher) { static Matcher<T> Cast(const Matcher<U>& source_matcher) {
return Matcher<T>(new Impl(source_matcher)); return Matcher<T>(new Impl(source_matcher));
} }
private: private:
class Impl : public MatcherInterface<T> { class Impl : public MatcherInterface<T> {
public: public:
explicit Impl(const Matcher<U>& source_matcher) explicit Impl(const Matcher<U>& source_matcher)
: source_matcher_(source_matcher) {} : source_matcher_(source_matcher) {}
skipping to change at line 452 skipping to change at line 455
} }
private: private:
const Matcher<U> source_matcher_; const Matcher<U> source_matcher_;
}; };
}; };
// This even more specialized version is used for efficiently casting // This even more specialized version is used for efficiently casting
// a matcher to its own type. // a matcher to its own type.
template <typename T> template <typename T>
class MatcherCastImpl<T, Matcher<T> > { class MatcherCastImpl<T, Matcher<T>> {
public: public:
static Matcher<T> Cast(const Matcher<T>& matcher) { return matcher; } static Matcher<T> Cast(const Matcher<T>& matcher) { return matcher; }
}; };
// Template specialization for parameterless Matcher. // Template specialization for parameterless Matcher.
template <typename Derived> template <typename Derived>
class MatcherBaseImpl { class MatcherBaseImpl {
public: public:
MatcherBaseImpl() = default; MatcherBaseImpl() = default;
skipping to change at line 535 skipping to change at line 538
// The only exception is when U is a reference and T is not, as the // The only exception is when U is a reference and T is not, as the
// underlying Matcher<U> may be interested in the argument's address, which // underlying Matcher<U> may be interested in the argument's address, which
// is not preserved in the conversion from T to U. // is not preserved in the conversion from T to U.
template <typename T, typename U> template <typename T, typename U>
inline Matcher<T> SafeMatcherCast(const Matcher<U>& matcher) { inline Matcher<T> SafeMatcherCast(const Matcher<U>& matcher) {
// Enforce that T can be implicitly converted to U. // Enforce that T can be implicitly converted to U.
static_assert(std::is_convertible<const T&, const U&>::value, static_assert(std::is_convertible<const T&, const U&>::value,
"T must be implicitly convertible to U"); "T must be implicitly convertible to U");
// Enforce that we are not converting a non-reference type T to a reference // Enforce that we are not converting a non-reference type T to a reference
// type U. // type U.
GTEST_COMPILE_ASSERT_( static_assert(std::is_reference<T>::value || !std::is_reference<U>::value,
std::is_reference<T>::value || !std::is_reference<U>::value, "cannot convert non reference arg to reference");
cannot_convert_non_reference_arg_to_reference);
// In case both T and U are arithmetic types, enforce that the // In case both T and U are arithmetic types, enforce that the
// conversion is not lossy. // conversion is not lossy.
typedef GTEST_REMOVE_REFERENCE_AND_CONST_(T) RawT; typedef GTEST_REMOVE_REFERENCE_AND_CONST_(T) RawT;
typedef GTEST_REMOVE_REFERENCE_AND_CONST_(U) RawU; typedef GTEST_REMOVE_REFERENCE_AND_CONST_(U) RawU;
constexpr bool kTIsOther = GMOCK_KIND_OF_(RawT) == internal::kOther; constexpr bool kTIsOther = GMOCK_KIND_OF_(RawT) == internal::kOther;
constexpr bool kUIsOther = GMOCK_KIND_OF_(RawU) == internal::kOther; constexpr bool kUIsOther = GMOCK_KIND_OF_(RawU) == internal::kOther;
GTEST_COMPILE_ASSERT_( static_assert(
kTIsOther || kUIsOther || kTIsOther || kUIsOther ||
(internal::LosslessArithmeticConvertible<RawT, RawU>::value), (internal::LosslessArithmeticConvertible<RawT, RawU>::value),
conversion_of_arithmetic_types_must_be_lossless); "conversion of arithmetic types must be lossless");
return MatcherCast<T>(matcher); return MatcherCast<T>(matcher);
} }
// A<T>() returns a matcher that matches any value of type T. // A<T>() returns a matcher that matches any value of type T.
template <typename T> template <typename T>
Matcher<T> A(); Matcher<T> A();
// Anything inside the 'internal' namespace IS INTERNAL IMPLEMENTATION // Anything inside the 'internal' namespace IS INTERNAL IMPLEMENTATION
// and MUST NOT BE USED IN USER CODE!!! // and MUST NOT BE USED IN USER CODE!!!
namespace internal { namespace internal {
skipping to change at line 680 skipping to change at line 682
// TupleMatches(matcher_tuple, value_tuple) returns true if and only if // TupleMatches(matcher_tuple, value_tuple) returns true if and only if
// all matchers in matcher_tuple match the corresponding fields in // all matchers in matcher_tuple match the corresponding fields in
// value_tuple. It is a compiler error if matcher_tuple and // value_tuple. It is a compiler error if matcher_tuple and
// value_tuple have different number of fields or incompatible field // value_tuple have different number of fields or incompatible field
// types. // types.
template <typename MatcherTuple, typename ValueTuple> template <typename MatcherTuple, typename ValueTuple>
bool TupleMatches(const MatcherTuple& matcher_tuple, bool TupleMatches(const MatcherTuple& matcher_tuple,
const ValueTuple& value_tuple) { const ValueTuple& value_tuple) {
// Makes sure that matcher_tuple and value_tuple have the same // Makes sure that matcher_tuple and value_tuple have the same
// number of fields. // number of fields.
GTEST_COMPILE_ASSERT_(std::tuple_size<MatcherTuple>::value == static_assert(std::tuple_size<MatcherTuple>::value ==
std::tuple_size<ValueTuple>::value, std::tuple_size<ValueTuple>::value,
matcher_and_value_have_different_numbers_of_fields); "matcher and value have different numbers of fields");
return TuplePrefix<std::tuple_size<ValueTuple>::value>::Matches(matcher_tuple, return TuplePrefix<std::tuple_size<ValueTuple>::value>::Matches(matcher_tuple,
value_tuple); value_tuple);
} }
// Describes failures in matching matchers against values. If there // Describes failures in matching matchers against values. If there
// is no failure, nothing will be streamed to os. // is no failure, nothing will be streamed to os.
template <typename MatcherTuple, typename ValueTuple> template <typename MatcherTuple, typename ValueTuple>
void ExplainMatchFailureTupleTo(const MatcherTuple& matchers, void ExplainMatchFailureTupleTo(const MatcherTuple& matchers,
const ValueTuple& values, const ValueTuple& values, ::std::ostream* os) {
::std::ostream* os) {
TuplePrefix<std::tuple_size<MatcherTuple>::value>::ExplainMatchFailuresTo( TuplePrefix<std::tuple_size<MatcherTuple>::value>::ExplainMatchFailuresTo(
matchers, values, os); matchers, values, os);
} }
// TransformTupleValues and its helper. // TransformTupleValues and its helper.
// //
// TransformTupleValuesHelper hides the internal machinery that // TransformTupleValuesHelper hides the internal machinery that
// TransformTupleValues uses to implement a tuple traversal. // TransformTupleValues uses to implement a tuple traversal.
template <typename Tuple, typename Func, typename OutIter> template <typename Tuple, typename Func, typename OutIter>
class TransformTupleValuesHelper { class TransformTupleValuesHelper {
skipping to change at line 716 skipping to change at line 717
public: public:
// For each member of tuple 't', taken in order, evaluates '*out++ = f(t)'. // For each member of tuple 't', taken in order, evaluates '*out++ = f(t)'.
// Returns the final value of 'out' in case the caller needs it. // Returns the final value of 'out' in case the caller needs it.
static OutIter Run(Func f, const Tuple& t, OutIter out) { static OutIter Run(Func f, const Tuple& t, OutIter out) {
return IterateOverTuple<Tuple, TupleSize::value>()(f, t, out); return IterateOverTuple<Tuple, TupleSize::value>()(f, t, out);
} }
private: private:
template <typename Tup, size_t kRemainingSize> template <typename Tup, size_t kRemainingSize>
struct IterateOverTuple { struct IterateOverTuple {
OutIter operator() (Func f, const Tup& t, OutIter out) const { OutIter operator()(Func f, const Tup& t, OutIter out) const {
*out++ = f(::std::get<TupleSize::value - kRemainingSize>(t)); *out++ = f(::std::get<TupleSize::value - kRemainingSize>(t));
return IterateOverTuple<Tup, kRemainingSize - 1>()(f, t, out); return IterateOverTuple<Tup, kRemainingSize - 1>()(f, t, out);
} }
}; };
template <typename Tup> template <typename Tup>
struct IterateOverTuple<Tup, 0> { struct IterateOverTuple<Tup, 0> {
OutIter operator() (Func /* f */, const Tup& /* t */, OutIter out) const { OutIter operator()(Func /* f */, const Tup& /* t */, OutIter out) const {
return out; return out;
} }
}; };
}; };
// Successively invokes 'f(element)' on each element of the tuple 't', // Successively invokes 'f(element)' on each element of the tuple 't',
// appending each result to the 'out' iterator. Returns the final value // appending each result to the 'out' iterator. Returns the final value
// of 'out'. // of 'out'.
template <typename Tuple, typename Func, typename OutIter> template <typename Tuple, typename Func, typename OutIter>
OutIter TransformTupleValues(Func f, const Tuple& t, OutIter out) { OutIter TransformTupleValues(Func f, const Tuple& t, OutIter out) {
skipping to change at line 769 skipping to change at line 770
// pointer that is NULL. // pointer that is NULL.
class IsNullMatcher { class IsNullMatcher {
public: public:
template <typename Pointer> template <typename Pointer>
bool MatchAndExplain(const Pointer& p, bool MatchAndExplain(const Pointer& p,
MatchResultListener* /* listener */) const { MatchResultListener* /* listener */) const {
return p == nullptr; return p == nullptr;
} }
void DescribeTo(::std::ostream* os) const { *os << "is NULL"; } void DescribeTo(::std::ostream* os) const { *os << "is NULL"; }
void DescribeNegationTo(::std::ostream* os) const { void DescribeNegationTo(::std::ostream* os) const { *os << "isn't NULL"; }
*os << "isn't NULL";
}
}; };
// Implements the polymorphic NotNull() matcher, which matches any raw or smart // Implements the polymorphic NotNull() matcher, which matches any raw or smart
// pointer that is not NULL. // pointer that is not NULL.
class NotNullMatcher { class NotNullMatcher {
public: public:
template <typename Pointer> template <typename Pointer>
bool MatchAndExplain(const Pointer& p, bool MatchAndExplain(const Pointer& p,
MatchResultListener* /* listener */) const { MatchResultListener* /* listener */) const {
return p != nullptr; return p != nullptr;
} }
void DescribeTo(::std::ostream* os) const { *os << "isn't NULL"; } void DescribeTo(::std::ostream* os) const { *os << "isn't NULL"; }
void DescribeNegationTo(::std::ostream* os) const { void DescribeNegationTo(::std::ostream* os) const { *os << "is NULL"; }
*os << "is NULL";
}
}; };
// Ref(variable) matches any argument that is a reference to // Ref(variable) matches any argument that is a reference to
// 'variable'. This matcher is polymorphic as it can match any // 'variable'. This matcher is polymorphic as it can match any
// super type of the type of 'variable'. // super type of the type of 'variable'.
// //
// The RefMatcher template class implements Ref(variable). It can // The RefMatcher template class implements Ref(variable). It can
// only be instantiated with a reference type. This prevents a user // only be instantiated with a reference type. This prevents a user
// from mistakenly using Ref(x) to match a non-reference function // from mistakenly using Ref(x) to match a non-reference function
// argument. For example, the following will righteously cause a // argument. For example, the following will righteously cause a
skipping to change at line 873 skipping to change at line 870
} }
inline bool CaseInsensitiveCStringEquals(const wchar_t* lhs, inline bool CaseInsensitiveCStringEquals(const wchar_t* lhs,
const wchar_t* rhs) { const wchar_t* rhs) {
return String::CaseInsensitiveWideCStringEquals(lhs, rhs); return String::CaseInsensitiveWideCStringEquals(lhs, rhs);
} }
// String comparison for narrow or wide strings that can have embedded NUL // String comparison for narrow or wide strings that can have embedded NUL
// characters. // characters.
template <typename StringType> template <typename StringType>
bool CaseInsensitiveStringEquals(const StringType& s1, bool CaseInsensitiveStringEquals(const StringType& s1, const StringType& s2) {
const StringType& s2) {
// Are the heads equal? // Are the heads equal?
if (!CaseInsensitiveCStringEquals(s1.c_str(), s2.c_str())) { if (!CaseInsensitiveCStringEquals(s1.c_str(), s2.c_str())) {
return false; return false;
} }
// Skip the equal heads. // Skip the equal heads.
const typename StringType::value_type nul = 0; const typename StringType::value_type nul = 0;
const size_t i1 = s1.find(nul), i2 = s2.find(nul); const size_t i1 = s1.find(nul), i2 = s2.find(nul);
// Are we at the end of either s1 or s2? // Are we at the end of either s1 or s2?
skipping to change at line 935 skipping to change at line 931
} }
// Matches anything that can convert to StringType. // Matches anything that can convert to StringType.
// //
// This is a template, not just a plain function with const StringType&, // This is a template, not just a plain function with const StringType&,
// because StringView has some interfering non-explicit constructors. // because StringView has some interfering non-explicit constructors.
template <typename MatcheeStringType> template <typename MatcheeStringType>
bool MatchAndExplain(const MatcheeStringType& s, bool MatchAndExplain(const MatcheeStringType& s,
MatchResultListener* /* listener */) const { MatchResultListener* /* listener */) const {
const StringType s2(s); const StringType s2(s);
const bool eq = case_sensitive_ ? s2 == string_ : const bool eq = case_sensitive_ ? s2 == string_
CaseInsensitiveStringEquals(s2, string_); : CaseInsensitiveStringEquals(s2, string_);
return expect_eq_ == eq; return expect_eq_ == eq;
} }
void DescribeTo(::std::ostream* os) const { void DescribeTo(::std::ostream* os) const {
DescribeToHelper(expect_eq_, os); DescribeToHelper(expect_eq_, os);
} }
void DescribeNegationTo(::std::ostream* os) const { void DescribeNegationTo(::std::ostream* os) const {
DescribeToHelper(!expect_eq_, os); DescribeToHelper(!expect_eq_, os);
} }
skipping to change at line 1023 skipping to change at line 1019
private: private:
const StringType substring_; const StringType substring_;
}; };
// Implements the polymorphic StartsWith(substring) matcher, which // Implements the polymorphic StartsWith(substring) matcher, which
// can be used as a Matcher<T> as long as T can be converted to a // can be used as a Matcher<T> as long as T can be converted to a
// string. // string.
template <typename StringType> template <typename StringType>
class StartsWithMatcher { class StartsWithMatcher {
public: public:
explicit StartsWithMatcher(const StringType& prefix) : prefix_(prefix) { explicit StartsWithMatcher(const StringType& prefix) : prefix_(prefix) {}
}
#if GTEST_INTERNAL_HAS_STRING_VIEW #if GTEST_INTERNAL_HAS_STRING_VIEW
bool MatchAndExplain(const internal::StringView& s, bool MatchAndExplain(const internal::StringView& s,
MatchResultListener* listener) const { MatchResultListener* listener) const {
// This should fail to compile if StringView is used with wide // This should fail to compile if StringView is used with wide
// strings. // strings.
const StringType& str = std::string(s); const StringType& str = std::string(s);
return MatchAndExplain(str, listener); return MatchAndExplain(str, listener);
} }
#endif // GTEST_INTERNAL_HAS_STRING_VIEW #endif // GTEST_INTERNAL_HAS_STRING_VIEW
skipping to change at line 1055 skipping to change at line 1050
// Matches anything that can convert to StringType. // Matches anything that can convert to StringType.
// //
// This is a template, not just a plain function with const StringType&, // This is a template, not just a plain function with const StringType&,
// because StringView has some interfering non-explicit constructors. // because StringView has some interfering non-explicit constructors.
template <typename MatcheeStringType> template <typename MatcheeStringType>
bool MatchAndExplain(const MatcheeStringType& s, bool MatchAndExplain(const MatcheeStringType& s,
MatchResultListener* /* listener */) const { MatchResultListener* /* listener */) const {
const StringType& s2(s); const StringType& s2(s);
return s2.length() >= prefix_.length() && return s2.length() >= prefix_.length() &&
s2.substr(0, prefix_.length()) == prefix_; s2.substr(0, prefix_.length()) == prefix_;
} }
void DescribeTo(::std::ostream* os) const { void DescribeTo(::std::ostream* os) const {
*os << "starts with "; *os << "starts with ";
UniversalPrint(prefix_, os); UniversalPrint(prefix_, os);
} }
void DescribeNegationTo(::std::ostream* os) const { void DescribeNegationTo(::std::ostream* os) const {
*os << "doesn't start with "; *os << "doesn't start with ";
UniversalPrint(prefix_, os); UniversalPrint(prefix_, os);
skipping to change at line 1109 skipping to change at line 1104
// Matches anything that can convert to StringType. // Matches anything that can convert to StringType.
// //
// This is a template, not just a plain function with const StringType&, // This is a template, not just a plain function with const StringType&,
// because StringView has some interfering non-explicit constructors. // because StringView has some interfering non-explicit constructors.
template <typename MatcheeStringType> template <typename MatcheeStringType>
bool MatchAndExplain(const MatcheeStringType& s, bool MatchAndExplain(const MatcheeStringType& s,
MatchResultListener* /* listener */) const { MatchResultListener* /* listener */) const {
const StringType& s2(s); const StringType& s2(s);
return s2.length() >= suffix_.length() && return s2.length() >= suffix_.length() &&
s2.substr(s2.length() - suffix_.length()) == suffix_; s2.substr(s2.length() - suffix_.length()) == suffix_;
} }
void DescribeTo(::std::ostream* os) const { void DescribeTo(::std::ostream* os) const {
*os << "ends with "; *os << "ends with ";
UniversalPrint(suffix_, os); UniversalPrint(suffix_, os);
} }
void DescribeNegationTo(::std::ostream* os) const { void DescribeNegationTo(::std::ostream* os) const {
*os << "doesn't end with "; *os << "doesn't end with ";
UniversalPrint(suffix_, os); UniversalPrint(suffix_, os);
} }
private: private:
const StringType suffix_; const StringType suffix_;
}; };
// Implements the polymorphic WhenBase64Unescaped(matcher) matcher, which can be
// used as a Matcher<T> as long as T can be converted to a string.
class WhenBase64UnescapedMatcher {
public:
using is_gtest_matcher = void;
explicit WhenBase64UnescapedMatcher(
const Matcher<const std::string&>& internal_matcher)
: internal_matcher_(internal_matcher) {}
// Matches anything that can convert to std::string.
template <typename MatcheeStringType>
bool MatchAndExplain(const MatcheeStringType& s,
MatchResultListener* listener) const {
const std::string s2(s); // NOLINT (needed for working with string_view).
std::string unescaped;
if (!internal::Base64Unescape(s2, &unescaped)) {
if (listener != nullptr) {
*listener << "is not a valid base64 escaped string";
}
return false;
}
return MatchPrintAndExplain(unescaped, internal_matcher_, listener);
}
void DescribeTo(::std::ostream* os) const {
*os << "matches after Base64Unescape ";
internal_matcher_.DescribeTo(os);
}
void DescribeNegationTo(::std::ostream* os) const {
*os << "does not match after Base64Unescape ";
internal_matcher_.DescribeTo(os);
}
private:
const Matcher<const std::string&> internal_matcher_;
};
// Implements a matcher that compares the two fields of a 2-tuple // Implements a matcher that compares the two fields of a 2-tuple
// using one of the ==, <=, <, etc, operators. The two fields being // using one of the ==, <=, <, etc, operators. The two fields being
// compared don't have to have the same type. // compared don't have to have the same type.
// //
// The matcher defined here is polymorphic (for example, Eq() can be // The matcher defined here is polymorphic (for example, Eq() can be
// used to match a std::tuple<int, short>, a std::tuple<const long&, double>, // used to match a std::tuple<int, short>, a std::tuple<const long&, double>,
// etc). Therefore we use a template type conversion operator in the // etc). Therefore we use a template type conversion operator in the
// implementation. // implementation.
template <typename D, typename Op> template <typename D, typename Op>
class PairMatchBase { class PairMatchBase {
skipping to change at line 1199 skipping to change at line 1233
static const char* Desc() { return "a pair where the first >= the second"; } static const char* Desc() { return "a pair where the first >= the second"; }
}; };
// Implements the Not(...) matcher for a particular argument type T. // Implements the Not(...) matcher for a particular argument type T.
// We do not nest it inside the NotMatcher class template, as that // We do not nest it inside the NotMatcher class template, as that
// will prevent different instantiations of NotMatcher from sharing // will prevent different instantiations of NotMatcher from sharing
// the same NotMatcherImpl<T> class. // the same NotMatcherImpl<T> class.
template <typename T> template <typename T>
class NotMatcherImpl : public MatcherInterface<const T&> { class NotMatcherImpl : public MatcherInterface<const T&> {
public: public:
explicit NotMatcherImpl(const Matcher<T>& matcher) explicit NotMatcherImpl(const Matcher<T>& matcher) : matcher_(matcher) {}
: matcher_(matcher) {}
bool MatchAndExplain(const T& x, bool MatchAndExplain(const T& x,
MatchResultListener* listener) const override { MatchResultListener* listener) const override {
return !matcher_.MatchAndExplain(x, listener); return !matcher_.MatchAndExplain(x, listener);
} }
void DescribeTo(::std::ostream* os) const override { void DescribeTo(::std::ostream* os) const override {
matcher_.DescribeNegationTo(os); matcher_.DescribeNegationTo(os);
} }
skipping to change at line 1244 skipping to change at line 1277
InnerMatcher matcher_; InnerMatcher matcher_;
}; };
// Implements the AllOf(m1, m2) matcher for a particular argument type // Implements the AllOf(m1, m2) matcher for a particular argument type
// T. We do not nest it inside the BothOfMatcher class template, as // T. We do not nest it inside the BothOfMatcher class template, as
// that will prevent different instantiations of BothOfMatcher from // that will prevent different instantiations of BothOfMatcher from
// sharing the same BothOfMatcherImpl<T> class. // sharing the same BothOfMatcherImpl<T> class.
template <typename T> template <typename T>
class AllOfMatcherImpl : public MatcherInterface<const T&> { class AllOfMatcherImpl : public MatcherInterface<const T&> {
public: public:
explicit AllOfMatcherImpl(std::vector<Matcher<T> > matchers) explicit AllOfMatcherImpl(std::vector<Matcher<T>> matchers)
: matchers_(std::move(matchers)) {} : matchers_(std::move(matchers)) {}
void DescribeTo(::std::ostream* os) const override { void DescribeTo(::std::ostream* os) const override {
*os << "("; *os << "(";
for (size_t i = 0; i < matchers_.size(); ++i) { for (size_t i = 0; i < matchers_.size(); ++i) {
if (i != 0) *os << ") and ("; if (i != 0) *os << ") and (";
matchers_[i].DescribeTo(os); matchers_[i].DescribeTo(os);
} }
*os << ")"; *os << ")";
} }
skipping to change at line 1295 skipping to change at line 1328
return false; return false;
} }
} }
// Otherwise we need to explain why *both* of them match. // Otherwise we need to explain why *both* of them match.
*listener << all_match_result; *listener << all_match_result;
return true; return true;
} }
private: private:
const std::vector<Matcher<T> > matchers_; const std::vector<Matcher<T>> matchers_;
}; };
// VariadicMatcher is used for the variadic implementation of // VariadicMatcher is used for the variadic implementation of
// AllOf(m_1, m_2, ...) and AnyOf(m_1, m_2, ...). // AllOf(m_1, m_2, ...) and AnyOf(m_1, m_2, ...).
// CombiningMatcher<T> is used to recursively combine the provided matchers // CombiningMatcher<T> is used to recursively combine the provided matchers
// (of type Args...). // (of type Args...).
template <template <typename T> class CombiningMatcher, typename... Args> template <template <typename T> class CombiningMatcher, typename... Args>
class VariadicMatcher { class VariadicMatcher {
public: public:
VariadicMatcher(const Args&... matchers) // NOLINT VariadicMatcher(const Args&... matchers) // NOLINT
skipping to change at line 1318 skipping to change at line 1351
} }
VariadicMatcher(const VariadicMatcher&) = default; VariadicMatcher(const VariadicMatcher&) = default;
VariadicMatcher& operator=(const VariadicMatcher&) = delete; VariadicMatcher& operator=(const VariadicMatcher&) = delete;
// This template type conversion operator allows an // This template type conversion operator allows an
// VariadicMatcher<Matcher1, Matcher2...> object to match any type that // VariadicMatcher<Matcher1, Matcher2...> object to match any type that
// all of the provided matchers (Matcher1, Matcher2, ...) can match. // all of the provided matchers (Matcher1, Matcher2, ...) can match.
template <typename T> template <typename T>
operator Matcher<T>() const { operator Matcher<T>() const {
std::vector<Matcher<T> > values; std::vector<Matcher<T>> values;
CreateVariadicMatcher<T>(&values, std::integral_constant<size_t, 0>()); CreateVariadicMatcher<T>(&values, std::integral_constant<size_t, 0>());
return Matcher<T>(new CombiningMatcher<T>(std::move(values))); return Matcher<T>(new CombiningMatcher<T>(std::move(values)));
} }
private: private:
template <typename T, size_t I> template <typename T, size_t I>
void CreateVariadicMatcher(std::vector<Matcher<T> >* values, void CreateVariadicMatcher(std::vector<Matcher<T>>* values,
std::integral_constant<size_t, I>) const { std::integral_constant<size_t, I>) const {
values->push_back(SafeMatcherCast<T>(std::get<I>(matchers_))); values->push_back(SafeMatcherCast<T>(std::get<I>(matchers_)));
CreateVariadicMatcher<T>(values, std::integral_constant<size_t, I + 1>()); CreateVariadicMatcher<T>(values, std::integral_constant<size_t, I + 1>());
} }
template <typename T> template <typename T>
void CreateVariadicMatcher( void CreateVariadicMatcher(
std::vector<Matcher<T> >*, std::vector<Matcher<T>>*,
std::integral_constant<size_t, sizeof...(Args)>) const {} std::integral_constant<size_t, sizeof...(Args)>) const {}
std::tuple<Args...> matchers_; std::tuple<Args...> matchers_;
}; };
template <typename... Args> template <typename... Args>
using AllOfMatcher = VariadicMatcher<AllOfMatcherImpl, Args...>; using AllOfMatcher = VariadicMatcher<AllOfMatcherImpl, Args...>;
// Implements the AnyOf(m1, m2) matcher for a particular argument type // Implements the AnyOf(m1, m2) matcher for a particular argument type
// T. We do not nest it inside the AnyOfMatcher class template, as // T. We do not nest it inside the AnyOfMatcher class template, as
// that will prevent different instantiations of AnyOfMatcher from // that will prevent different instantiations of AnyOfMatcher from
// sharing the same EitherOfMatcherImpl<T> class. // sharing the same EitherOfMatcherImpl<T> class.
template <typename T> template <typename T>
class AnyOfMatcherImpl : public MatcherInterface<const T&> { class AnyOfMatcherImpl : public MatcherInterface<const T&> {
public: public:
explicit AnyOfMatcherImpl(std::vector<Matcher<T> > matchers) explicit AnyOfMatcherImpl(std::vector<Matcher<T>> matchers)
: matchers_(std::move(matchers)) {} : matchers_(std::move(matchers)) {}
void DescribeTo(::std::ostream* os) const override { void DescribeTo(::std::ostream* os) const override {
*os << "("; *os << "(";
for (size_t i = 0; i < matchers_.size(); ++i) { for (size_t i = 0; i < matchers_.size(); ++i) {
if (i != 0) *os << ") or ("; if (i != 0) *os << ") or (";
matchers_[i].DescribeTo(os); matchers_[i].DescribeTo(os);
} }
*os << ")"; *os << ")";
} }
skipping to change at line 1400 skipping to change at line 1433
} }
} }
} }
// Otherwise we need to explain why *both* of them fail. // Otherwise we need to explain why *both* of them fail.
*listener << no_match_result; *listener << no_match_result;
return false; return false;
} }
private: private:
const std::vector<Matcher<T> > matchers_; const std::vector<Matcher<T>> matchers_;
}; };
// AnyOfMatcher is used for the variadic implementation of AnyOf(m_1, m_2, ...). // AnyOfMatcher is used for the variadic implementation of AnyOf(m_1, m_2, ...).
template <typename... Args> template <typename... Args>
using AnyOfMatcher = VariadicMatcher<AnyOfMatcherImpl, Args...>; using AnyOfMatcher = VariadicMatcher<AnyOfMatcherImpl, Args...>;
// ConditionalMatcher is the implementation of Conditional(cond, m1, m2)
template <typename MatcherTrue, typename MatcherFalse>
class ConditionalMatcher {
public:
ConditionalMatcher(bool condition, MatcherTrue matcher_true,
MatcherFalse matcher_false)
: condition_(condition),
matcher_true_(std::move(matcher_true)),
matcher_false_(std::move(matcher_false)) {}
template <typename T>
operator Matcher<T>() const { // NOLINT(runtime/explicit)
return condition_ ? SafeMatcherCast<T>(matcher_true_)
: SafeMatcherCast<T>(matcher_false_);
}
private:
bool condition_;
MatcherTrue matcher_true_;
MatcherFalse matcher_false_;
};
// Wrapper for implementation of Any/AllOfArray(). // Wrapper for implementation of Any/AllOfArray().
template <template <class> class MatcherImpl, typename T> template <template <class> class MatcherImpl, typename T>
class SomeOfArrayMatcher { class SomeOfArrayMatcher {
public: public:
// Constructs the matcher from a sequence of element values or // Constructs the matcher from a sequence of element values or
// element matchers. // element matchers.
template <typename Iter> template <typename Iter>
SomeOfArrayMatcher(Iter first, Iter last) : matchers_(first, last) {} SomeOfArrayMatcher(Iter first, Iter last) : matchers_(first, last) {}
template <typename U> template <typename U>
skipping to change at line 1456 skipping to change at line 1511
// interested in the address of the argument. // interested in the address of the argument.
template <typename T> template <typename T>
bool MatchAndExplain(T& x, // NOLINT bool MatchAndExplain(T& x, // NOLINT
MatchResultListener* listener) const { MatchResultListener* listener) const {
// Without the if-statement, MSVC sometimes warns about converting // Without the if-statement, MSVC sometimes warns about converting
// a value to bool (warning 4800). // a value to bool (warning 4800).
// //
// We cannot write 'return !!predicate_(x);' as that doesn't work // We cannot write 'return !!predicate_(x);' as that doesn't work
// when predicate_(x) returns a class convertible to bool but // when predicate_(x) returns a class convertible to bool but
// having no operator!(). // having no operator!().
if (predicate_(x)) if (predicate_(x)) return true;
return true;
*listener << "didn't satisfy the given predicate"; *listener << "didn't satisfy the given predicate";
return false; return false;
} }
void DescribeTo(::std::ostream* os) const { void DescribeTo(::std::ostream* os) const {
*os << "satisfies the given predicate"; *os << "satisfies the given predicate";
} }
void DescribeNegationTo(::std::ostream* os) const { void DescribeNegationTo(::std::ostream* os) const {
*os << "doesn't satisfy the given predicate"; *os << "doesn't satisfy the given predicate";
skipping to change at line 1565 skipping to change at line 1619
private: private:
const M matcher_; const M matcher_;
}; };
// A helper function for converting a matcher to a predicate-formatter // A helper function for converting a matcher to a predicate-formatter
// without the user needing to explicitly write the type. This is // without the user needing to explicitly write the type. This is
// used for implementing ASSERT_THAT() and EXPECT_THAT(). // used for implementing ASSERT_THAT() and EXPECT_THAT().
// Implementation detail: 'matcher' is received by-value to force decaying. // Implementation detail: 'matcher' is received by-value to force decaying.
template <typename M> template <typename M>
inline PredicateFormatterFromMatcher<M> inline PredicateFormatterFromMatcher<M> MakePredicateFormatterFromMatcher(
MakePredicateFormatterFromMatcher(M matcher) { M matcher) {
return PredicateFormatterFromMatcher<M>(std::move(matcher)); return PredicateFormatterFromMatcher<M>(std::move(matcher));
} }
// Implements the polymorphic IsNan() matcher, which matches any floating type // Implements the polymorphic IsNan() matcher, which matches any floating type
// value that is Nan. // value that is Nan.
class IsNanMatcher { class IsNanMatcher {
public: public:
template <typename FloatType> template <typename FloatType>
bool MatchAndExplain(const FloatType& f, bool MatchAndExplain(const FloatType& f,
MatchResultListener* /* listener */) const { MatchResultListener* /* listener */) const {
return (::std::isnan)(f); return (::std::isnan)(f);
} }
void DescribeTo(::std::ostream* os) const { *os << "is NaN"; } void DescribeTo(::std::ostream* os) const { *os << "is NaN"; }
void DescribeNegationTo(::std::ostream* os) const { void DescribeNegationTo(::std::ostream* os) const { *os << "isn't NaN"; }
*os << "isn't NaN";
}
}; };
// Implements the polymorphic floating point equality matcher, which matches // Implements the polymorphic floating point equality matcher, which matches
// two float values using ULP-based approximation or, optionally, a // two float values using ULP-based approximation or, optionally, a
// user-specified epsilon. The template is meant to be instantiated with // user-specified epsilon. The template is meant to be instantiated with
// FloatType being either float or double. // FloatType being either float or double.
template <typename FloatType> template <typename FloatType>
class FloatingEqMatcher { class FloatingEqMatcher {
public: public:
// Constructor for FloatingEqMatcher. // Constructor for FloatingEqMatcher.
// The matcher's input will be compared with expected. The matcher treats two // The matcher's input will be compared with expected. The matcher treats two
// NANs as equal if nan_eq_nan is true. Otherwise, under IEEE standards, // NANs as equal if nan_eq_nan is true. Otherwise, under IEEE standards,
// equality comparisons between NANs will always return false. We specify a // equality comparisons between NANs will always return false. We specify a
// negative max_abs_error_ term to indicate that ULP-based approximation will // negative max_abs_error_ term to indicate that ULP-based approximation will
// be used for comparison. // be used for comparison.
FloatingEqMatcher(FloatType expected, bool nan_eq_nan) : FloatingEqMatcher(FloatType expected, bool nan_eq_nan)
expected_(expected), nan_eq_nan_(nan_eq_nan), max_abs_error_(-1) { : expected_(expected), nan_eq_nan_(nan_eq_nan), max_abs_error_(-1) {}
}
// Constructor that supports a user-specified max_abs_error that will be used // Constructor that supports a user-specified max_abs_error that will be used
// for comparison instead of ULP-based approximation. The max absolute // for comparison instead of ULP-based approximation. The max absolute
// should be non-negative. // should be non-negative.
FloatingEqMatcher(FloatType expected, bool nan_eq_nan, FloatingEqMatcher(FloatType expected, bool nan_eq_nan,
FloatType max_abs_error) FloatType max_abs_error)
: expected_(expected), : expected_(expected),
nan_eq_nan_(nan_eq_nan), nan_eq_nan_(nan_eq_nan),
max_abs_error_(max_abs_error) { max_abs_error_(max_abs_error) {
GTEST_CHECK_(max_abs_error >= 0) GTEST_CHECK_(max_abs_error >= 0)
skipping to change at line 1663 skipping to change at line 1714
return false; return false;
} else { } else {
return actual.AlmostEquals(expected); return actual.AlmostEquals(expected);
} }
} }
void DescribeTo(::std::ostream* os) const override { void DescribeTo(::std::ostream* os) const override {
// os->precision() returns the previously set precision, which we // os->precision() returns the previously set precision, which we
// store to restore the ostream to its original configuration // store to restore the ostream to its original configuration
// after outputting. // after outputting.
const ::std::streamsize old_precision = os->precision( const ::std::streamsize old_precision =
::std::numeric_limits<FloatType>::digits10 + 2); os->precision(::std::numeric_limits<FloatType>::digits10 + 2);
if (FloatingPoint<FloatType>(expected_).is_nan()) { if (FloatingPoint<FloatType>(expected_).is_nan()) {
if (nan_eq_nan_) { if (nan_eq_nan_) {
*os << "is NaN"; *os << "is NaN";
} else { } else {
*os << "never matches"; *os << "never matches";
} }
} else { } else {
*os << "is approximately " << expected_; *os << "is approximately " << expected_;
if (HasMaxAbsError()) { if (HasMaxAbsError()) {
*os << " (absolute error <= " << max_abs_error_ << ")"; *os << " (absolute error <= " << max_abs_error_ << ")";
} }
} }
os->precision(old_precision); os->precision(old_precision);
} }
void DescribeNegationTo(::std::ostream* os) const override { void DescribeNegationTo(::std::ostream* os) const override {
// As before, get original precision. // As before, get original precision.
const ::std::streamsize old_precision = os->precision( const ::std::streamsize old_precision =
::std::numeric_limits<FloatType>::digits10 + 2); os->precision(::std::numeric_limits<FloatType>::digits10 + 2);
if (FloatingPoint<FloatType>(expected_).is_nan()) { if (FloatingPoint<FloatType>(expected_).is_nan()) {
if (nan_eq_nan_) { if (nan_eq_nan_) {
*os << "isn't NaN"; *os << "isn't NaN";
} else { } else {
*os << "is anything"; *os << "is anything";
} }
} else { } else {
*os << "isn't approximately " << expected_; *os << "isn't approximately " << expected_;
if (HasMaxAbsError()) { if (HasMaxAbsError()) {
*os << " (absolute error > " << max_abs_error_ << ")"; *os << " (absolute error > " << max_abs_error_ << ")";
} }
} }
// Restore original precision. // Restore original precision.
os->precision(old_precision); os->precision(old_precision);
} }
private: private:
bool HasMaxAbsError() const { bool HasMaxAbsError() const { return max_abs_error_ >= 0; }
return max_abs_error_ >= 0;
}
const FloatType expected_; const FloatType expected_;
const bool nan_eq_nan_; const bool nan_eq_nan_;
// max_abs_error will be used for value comparison when >= 0. // max_abs_error will be used for value comparison when >= 0.
const FloatType max_abs_error_; const FloatType max_abs_error_;
}; };
// The following 3 type conversion operators allow FloatEq(expected) and // The following 3 type conversion operators allow FloatEq(expected) and
// NanSensitiveFloatEq(expected) to be used as a Matcher<float>, a // NanSensitiveFloatEq(expected) to be used as a Matcher<float>, a
// Matcher<const float&>, or a Matcher<float&>, but nothing else. // Matcher<const float&>, or a Matcher<float&>, but nothing else.
skipping to change at line 1775 skipping to change at line 1824
} }
private: private:
static ::std::ostream& GetDesc(::std::ostream& os) { // NOLINT static ::std::ostream& GetDesc(::std::ostream& os) { // NOLINT
return os << "an almost-equal pair"; return os << "an almost-equal pair";
} }
template <typename Tuple> template <typename Tuple>
class Impl : public MatcherInterface<Tuple> { class Impl : public MatcherInterface<Tuple> {
public: public:
Impl(FloatType max_abs_error, bool nan_eq_nan) : Impl(FloatType max_abs_error, bool nan_eq_nan)
max_abs_error_(max_abs_error), : max_abs_error_(max_abs_error), nan_eq_nan_(nan_eq_nan) {}
nan_eq_nan_(nan_eq_nan) {}
bool MatchAndExplain(Tuple args, bool MatchAndExplain(Tuple args,
MatchResultListener* listener) const override { MatchResultListener* listener) const override {
if (max_abs_error_ == -1) { if (max_abs_error_ == -1) {
FloatingEqMatcher<FloatType> fm(::std::get<0>(args), nan_eq_nan_); FloatingEqMatcher<FloatType> fm(::std::get<0>(args), nan_eq_nan_);
return static_cast<Matcher<FloatType>>(fm).MatchAndExplain( return static_cast<Matcher<FloatType>>(fm).MatchAndExplain(
::std::get<1>(args), listener); ::std::get<1>(args), listener);
} else { } else {
FloatingEqMatcher<FloatType> fm(::std::get<0>(args), nan_eq_nan_, FloatingEqMatcher<FloatType> fm(::std::get<0>(args), nan_eq_nan_,
max_abs_error_); max_abs_error_);
skipping to change at line 1953 skipping to change at line 2001
} }
void DescribeNegationTo(::std::ostream* os) const { void DescribeNegationTo(::std::ostream* os) const {
GetCastTypeDescription(os); GetCastTypeDescription(os);
matcher_.DescribeNegationTo(os); matcher_.DescribeNegationTo(os);
} }
protected: protected:
const Matcher<To> matcher_; const Matcher<To> matcher_;
static std::string GetToName() { static std::string GetToName() { return GetTypeName<To>(); }
return GetTypeName<To>();
}
private: private:
static void GetCastTypeDescription(::std::ostream* os) { static void GetCastTypeDescription(::std::ostream* os) {
*os << "when dynamic_cast to " << GetToName() << ", "; *os << "when dynamic_cast to " << GetToName() << ", ";
} }
}; };
// Primary template. // Primary template.
// To is a pointer. Cast and forward the result. // To is a pointer. Cast and forward the result.
template <typename To> template <typename To>
skipping to change at line 2092 skipping to change at line 2138
*os << "is an object " << whose_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_property_; *os << "is an object " << whose_property_;
matcher_.DescribeNegationTo(os); matcher_.DescribeNegationTo(os);
} }
template <typename T> template <typename T>
bool MatchAndExplain(const T&value, MatchResultListener* listener) const { bool MatchAndExplain(const T& value, MatchResultListener* listener) const {
return MatchAndExplainImpl( return MatchAndExplainImpl(
typename std::is_pointer<typename std::remove_const<T>::type>::type(), typename std::is_pointer<typename std::remove_const<T>::type>::type(),
value, listener); value, listener);
} }
private: private:
bool MatchAndExplainImpl(std::false_type /* is_not_pointer */, bool MatchAndExplainImpl(std::false_type /* is_not_pointer */,
const Class& obj, const Class& obj,
MatchResultListener* listener) const { MatchResultListener* listener) const {
*listener << whose_property_ << "is "; *listener << whose_property_ << "is ";
skipping to change at line 2144 skipping to change at line 2190
static void CheckIsValid(Functor /* functor */) {} static void CheckIsValid(Functor /* functor */) {}
template <typename T> template <typename T>
static auto Invoke(Functor f, const T& arg) -> decltype(f(arg)) { static auto Invoke(Functor f, const T& arg) -> decltype(f(arg)) {
return f(arg); return f(arg);
} }
}; };
// Specialization for function pointers. // Specialization for function pointers.
template <typename ArgType, typename ResType> template <typename ArgType, typename ResType>
struct CallableTraits<ResType(*)(ArgType)> { struct CallableTraits<ResType (*)(ArgType)> {
typedef ResType ResultType; typedef ResType ResultType;
typedef ResType(*StorageType)(ArgType); typedef ResType (*StorageType)(ArgType);
static void CheckIsValid(ResType(*f)(ArgType)) { static void CheckIsValid(ResType (*f)(ArgType)) {
GTEST_CHECK_(f != nullptr) GTEST_CHECK_(f != nullptr)
<< "NULL function pointer is passed into ResultOf()."; << "NULL function pointer is passed into ResultOf().";
} }
template <typename T> template <typename T>
static ResType Invoke(ResType(*f)(ArgType), T arg) { static ResType Invoke(ResType (*f)(ArgType), T arg) {
return (*f)(arg); return (*f)(arg);
} }
}; };
// Implements the ResultOf() matcher for matching a return value of a // Implements the ResultOf() matcher for matching a return value of a
// unary function of an object. // unary function of an object.
template <typename Callable, typename InnerMatcher> template <typename Callable, typename InnerMatcher>
class ResultOfMatcher { class ResultOfMatcher {
public: public:
ResultOfMatcher(Callable callable, InnerMatcher matcher) ResultOfMatcher(Callable callable, InnerMatcher matcher)
: callable_(std::move(callable)), matcher_(std::move(matcher)) { : ResultOfMatcher(/*result_description=*/"", std::move(callable),
std::move(matcher)) {}
ResultOfMatcher(const std::string& result_description, Callable callable,
InnerMatcher matcher)
: result_description_(result_description),
callable_(std::move(callable)),
matcher_(std::move(matcher)) {
CallableTraits<Callable>::CheckIsValid(callable_); CallableTraits<Callable>::CheckIsValid(callable_);
} }
template <typename T> template <typename T>
operator Matcher<T>() const { operator Matcher<T>() const {
return Matcher<T>(new Impl<const T&>(callable_, matcher_)); return Matcher<T>(
new Impl<const T&>(result_description_, callable_, matcher_));
} }
private: private:
typedef typename CallableTraits<Callable>::StorageType CallableStorageType; typedef typename CallableTraits<Callable>::StorageType CallableStorageType;
template <typename T> template <typename T>
class Impl : public MatcherInterface<T> { class Impl : public MatcherInterface<T> {
using ResultType = decltype(CallableTraits<Callable>::template Invoke<T>( using ResultType = decltype(CallableTraits<Callable>::template Invoke<T>(
std::declval<CallableStorageType>(), std::declval<T>())); std::declval<CallableStorageType>(), std::declval<T>()));
public: public:
template <typename M> template <typename M>
Impl(const CallableStorageType& callable, const M& matcher) Impl(const std::string& result_description,
: callable_(callable), matcher_(MatcherCast<ResultType>(matcher)) {} const CallableStorageType& callable, const M& matcher)
: result_description_(result_description),
callable_(callable),
matcher_(MatcherCast<ResultType>(matcher)) {}
void DescribeTo(::std::ostream* os) const override { void DescribeTo(::std::ostream* os) const override {
*os << "is mapped by the given callable to a value that "; if (result_description_.empty()) {
*os << "is mapped by the given callable to a value that ";
} else {
*os << "whose " << result_description_ << " ";
}
matcher_.DescribeTo(os); matcher_.DescribeTo(os);
} }
void DescribeNegationTo(::std::ostream* os) const override { void DescribeNegationTo(::std::ostream* os) const override {
*os << "is mapped by the given callable to a value that "; if (result_description_.empty()) {
*os << "is mapped by the given callable to a value that ";
} else {
*os << "whose " << result_description_ << " ";
}
matcher_.DescribeNegationTo(os); matcher_.DescribeNegationTo(os);
} }
bool MatchAndExplain(T obj, MatchResultListener* listener) const override { bool MatchAndExplain(T obj, MatchResultListener* listener) const override {
*listener << "which is mapped by the given callable to "; if (result_description_.empty()) {
*listener << "which is mapped by the given callable to ";
} else {
*listener << "whose " << result_description_ << " is ";
}
// Cannot pass the return value directly to MatchPrintAndExplain, which // Cannot pass the return value directly to MatchPrintAndExplain, which
// takes a non-const reference as argument. // takes a non-const reference as argument.
// Also, specifying template argument explicitly is needed because T could // Also, specifying template argument explicitly is needed because T could
// be a non-const reference (e.g. Matcher<Uncopyable&>). // be a non-const reference (e.g. Matcher<Uncopyable&>).
ResultType result = ResultType result =
CallableTraits<Callable>::template Invoke<T>(callable_, obj); CallableTraits<Callable>::template Invoke<T>(callable_, obj);
return MatchPrintAndExplain(result, matcher_, listener); return MatchPrintAndExplain(result, matcher_, listener);
} }
private: private:
const std::string result_description_;
// Functors often define operator() as non-const method even though // Functors often define operator() as non-const method even though
// they are actually stateless. But we need to use them even when // they are actually stateless. But we need to use them even when
// 'this' is a const pointer. It's the user's responsibility not to // 'this' is a const pointer. It's the user's responsibility not to
// use stateful callables with ResultOf(), which doesn't guarantee // use stateful callables with ResultOf(), which doesn't guarantee
// how many times the callable will be invoked. // how many times the callable will be invoked.
mutable CallableStorageType callable_; mutable CallableStorageType callable_;
const Matcher<ResultType> matcher_; const Matcher<ResultType> matcher_;
}; // class Impl }; // class Impl
const std::string result_description_;
const CallableStorageType callable_; const CallableStorageType callable_;
const InnerMatcher matcher_; const InnerMatcher matcher_;
}; };
// Implements a matcher that checks the size of an STL-style container. // Implements a matcher that checks the size of an STL-style container.
template <typename SizeMatcher> template <typename SizeMatcher>
class SizeIsMatcher { class SizeIsMatcher {
public: public:
explicit SizeIsMatcher(const SizeMatcher& size_matcher) explicit SizeIsMatcher(const SizeMatcher& size_matcher)
: size_matcher_(size_matcher) { : size_matcher_(size_matcher) {}
}
template <typename Container> template <typename Container>
operator Matcher<Container>() const { operator Matcher<Container>() const {
return Matcher<Container>(new Impl<const Container&>(size_matcher_)); return Matcher<Container>(new Impl<const Container&>(size_matcher_));
} }
template <typename Container> template <typename Container>
class Impl : public MatcherInterface<Container> { class Impl : public MatcherInterface<Container> {
public: public:
using SizeType = decltype(std::declval<Container>().size()); using SizeType = decltype(std::declval<Container>().size());
skipping to change at line 2255 skipping to change at line 2325
void DescribeNegationTo(::std::ostream* os) const override { void DescribeNegationTo(::std::ostream* os) const override {
*os << "size "; *os << "size ";
size_matcher_.DescribeNegationTo(os); size_matcher_.DescribeNegationTo(os);
} }
bool MatchAndExplain(Container container, bool MatchAndExplain(Container container,
MatchResultListener* listener) const override { MatchResultListener* listener) const override {
SizeType size = container.size(); SizeType size = container.size();
StringMatchResultListener size_listener; StringMatchResultListener size_listener;
const bool result = size_matcher_.MatchAndExplain(size, &size_listener); const bool result = size_matcher_.MatchAndExplain(size, &size_listener);
*listener *listener << "whose size " << size
<< "whose size " << size << (result ? " matches" : " doesn't match"); << (result ? " matches" : " doesn't match");
PrintIfNotEmpty(size_listener.str(), listener->stream()); PrintIfNotEmpty(size_listener.str(), listener->stream());
return result; return result;
} }
private: private:
const Matcher<SizeType> size_matcher_; const Matcher<SizeType> size_matcher_;
}; };
private: private:
const SizeMatcher size_matcher_; const SizeMatcher size_matcher_;
skipping to change at line 2285 skipping to change at line 2355
: distance_matcher_(distance_matcher) {} : distance_matcher_(distance_matcher) {}
template <typename Container> template <typename Container>
operator Matcher<Container>() const { operator Matcher<Container>() const {
return Matcher<Container>(new Impl<const Container&>(distance_matcher_)); return Matcher<Container>(new Impl<const Container&>(distance_matcher_));
} }
template <typename Container> template <typename Container>
class Impl : public MatcherInterface<Container> { class Impl : public MatcherInterface<Container> {
public: public:
typedef internal::StlContainerView< typedef internal::StlContainerView<GTEST_REMOVE_REFERENCE_AND_CONST_(
GTEST_REMOVE_REFERENCE_AND_CONST_(Container)> ContainerView; Container)>
ContainerView;
typedef typename std::iterator_traits< typedef typename std::iterator_traits<
typename ContainerView::type::const_iterator>::difference_type typename ContainerView::type::const_iterator>::difference_type
DistanceType; DistanceType;
explicit Impl(const DistanceMatcher& distance_matcher) explicit Impl(const DistanceMatcher& distance_matcher)
: distance_matcher_(MatcherCast<DistanceType>(distance_matcher)) {} : distance_matcher_(MatcherCast<DistanceType>(distance_matcher)) {}
void DescribeTo(::std::ostream* os) const override { void DescribeTo(::std::ostream* os) const override {
*os << "distance between begin() and end() "; *os << "distance between begin() and end() ";
distance_matcher_.DescribeTo(os); distance_matcher_.DescribeTo(os);
} }
skipping to change at line 2366 skipping to change at line 2437
*os << "does not equal "; *os << "does not equal ";
UniversalPrint(expected_, os); UniversalPrint(expected_, os);
} }
template <typename LhsContainer> template <typename LhsContainer>
bool MatchAndExplain(const LhsContainer& lhs, bool MatchAndExplain(const LhsContainer& lhs,
MatchResultListener* listener) const { MatchResultListener* listener) const {
typedef internal::StlContainerView< typedef internal::StlContainerView<
typename std::remove_const<LhsContainer>::type> typename std::remove_const<LhsContainer>::type>
LhsView; LhsView;
typedef typename LhsView::type LhsStlContainer;
StlContainerReference lhs_stl_container = LhsView::ConstReference(lhs); StlContainerReference lhs_stl_container = LhsView::ConstReference(lhs);
if (lhs_stl_container == expected_) if (lhs_stl_container == expected_) return true;
return true;
::std::ostream* const os = listener->stream(); ::std::ostream* const os = listener->stream();
if (os != nullptr) { if (os != nullptr) {
// Something is different. Check for extra values first. // Something is different. Check for extra values first.
bool printed_header = false; bool printed_header = false;
for (typename LhsStlContainer::const_iterator it = for (auto it = lhs_stl_container.begin(); it != lhs_stl_container.end();
lhs_stl_container.begin(); ++it) {
it != lhs_stl_container.end(); ++it) {
if (internal::ArrayAwareFind(expected_.begin(), expected_.end(), *it) == if (internal::ArrayAwareFind(expected_.begin(), expected_.end(), *it) ==
expected_.end()) { expected_.end()) {
if (printed_header) { if (printed_header) {
*os << ", "; *os << ", ";
} else { } else {
*os << "which has these unexpected elements: "; *os << "which has these unexpected elements: ";
printed_header = true; printed_header = true;
} }
UniversalPrint(*it, os); UniversalPrint(*it, os);
} }
} }
// Now check for missing values. // Now check for missing values.
bool printed_header2 = false; bool printed_header2 = false;
for (typename StlContainer::const_iterator it = expected_.begin(); for (auto it = expected_.begin(); it != expected_.end(); ++it) {
it != expected_.end(); ++it) { if (internal::ArrayAwareFind(lhs_stl_container.begin(),
if (internal::ArrayAwareFind( lhs_stl_container.end(),
lhs_stl_container.begin(), lhs_stl_container.end(), *it) == *it) == lhs_stl_container.end()) {
lhs_stl_container.end()) {
if (printed_header2) { if (printed_header2) {
*os << ", "; *os << ", ";
} else { } else {
*os << (printed_header ? ",\nand" : "which") *os << (printed_header ? ",\nand" : "which")
<< " doesn't have these expected elements: "; << " doesn't have these expected elements: ";
printed_header2 = true; printed_header2 = true;
} }
UniversalPrint(*it, os); UniversalPrint(*it, os);
} }
} }
skipping to change at line 2419 skipping to change at line 2486
return false; return false;
} }
private: private:
const StlContainer expected_; const StlContainer expected_;
}; };
// A comparator functor that uses the < operator to compare two values. // A comparator functor that uses the < operator to compare two values.
struct LessComparator { struct LessComparator {
template <typename T, typename U> template <typename T, typename U>
bool operator()(const T& lhs, const U& rhs) const { return lhs < rhs; } bool operator()(const T& lhs, const U& rhs) const {
return lhs < rhs;
}
}; };
// Implements WhenSortedBy(comparator, container_matcher). // Implements WhenSortedBy(comparator, container_matcher).
template <typename Comparator, typename ContainerMatcher> template <typename Comparator, typename ContainerMatcher>
class WhenSortedByMatcher { class WhenSortedByMatcher {
public: public:
WhenSortedByMatcher(const Comparator& comparator, WhenSortedByMatcher(const Comparator& comparator,
const ContainerMatcher& matcher) const ContainerMatcher& matcher)
: comparator_(comparator), matcher_(matcher) {} : comparator_(comparator), matcher_(matcher) {}
template <typename LhsContainer> template <typename LhsContainer>
operator Matcher<LhsContainer>() const { operator Matcher<LhsContainer>() const {
return MakeMatcher(new Impl<LhsContainer>(comparator_, matcher_)); return MakeMatcher(new Impl<LhsContainer>(comparator_, matcher_));
} }
template <typename LhsContainer> template <typename LhsContainer>
class Impl : public MatcherInterface<LhsContainer> { class Impl : public MatcherInterface<LhsContainer> {
public: public:
typedef internal::StlContainerView< typedef internal::StlContainerView<GTEST_REMOVE_REFERENCE_AND_CONST_(
GTEST_REMOVE_REFERENCE_AND_CONST_(LhsContainer)> LhsView; LhsContainer)>
LhsView;
typedef typename LhsView::type LhsStlContainer; typedef typename LhsView::type LhsStlContainer;
typedef typename LhsView::const_reference LhsStlContainerReference; typedef typename LhsView::const_reference LhsStlContainerReference;
// Transforms std::pair<const Key, Value> into std::pair<Key, Value> // Transforms std::pair<const Key, Value> into std::pair<Key, Value>
// so that we can match associative containers. // so that we can match associative containers.
typedef typename RemoveConstFromKey< typedef
typename LhsStlContainer::value_type>::type LhsValue; typename RemoveConstFromKey<typename LhsStlContainer::value_type>::type
LhsValue;
Impl(const Comparator& comparator, const ContainerMatcher& matcher) Impl(const Comparator& comparator, const ContainerMatcher& matcher)
: comparator_(comparator), matcher_(matcher) {} : comparator_(comparator), matcher_(matcher) {}
void DescribeTo(::std::ostream* os) const override { void DescribeTo(::std::ostream* os) const override {
*os << "(when sorted) "; *os << "(when sorted) ";
matcher_.DescribeTo(os); matcher_.DescribeTo(os);
} }
void DescribeNegationTo(::std::ostream* os) const override { void DescribeNegationTo(::std::ostream* os) const override {
*os << "(when sorted) "; *os << "(when sorted) ";
matcher_.DescribeNegationTo(os); matcher_.DescribeNegationTo(os);
} }
bool MatchAndExplain(LhsContainer lhs, bool MatchAndExplain(LhsContainer lhs,
MatchResultListener* listener) const override { MatchResultListener* listener) const override {
LhsStlContainerReference lhs_stl_container = LhsView::ConstReference(lhs); LhsStlContainerReference lhs_stl_container = LhsView::ConstReference(lhs);
::std::vector<LhsValue> sorted_container(lhs_stl_container.begin(), ::std::vector<LhsValue> sorted_container(lhs_stl_container.begin(),
lhs_stl_container.end()); lhs_stl_container.end());
::std::sort( ::std::sort(sorted_container.begin(), sorted_container.end(),
sorted_container.begin(), sorted_container.end(), comparator_); comparator_);
if (!listener->IsInterested()) { if (!listener->IsInterested()) {
// If the listener is not interested, we do not need to // If the listener is not interested, we do not need to
// construct the inner explanation. // construct the inner explanation.
return matcher_.Matches(sorted_container); return matcher_.Matches(sorted_container);
} }
*listener << "which is "; *listener << "which is ";
UniversalPrint(sorted_container, listener->stream()); UniversalPrint(sorted_container, listener->stream());
*listener << " when sorted"; *listener << " when sorted";
StringMatchResultListener inner_listener; StringMatchResultListener inner_listener;
const bool match = matcher_.MatchAndExplain(sorted_container, const bool match =
&inner_listener); matcher_.MatchAndExplain(sorted_container, &inner_listener);
PrintIfNotEmpty(inner_listener.str(), listener->stream()); PrintIfNotEmpty(inner_listener.str(), listener->stream());
return match; return match;
} }
private: private:
const Comparator comparator_; const Comparator comparator_;
const Matcher<const ::std::vector<LhsValue>&> matcher_; const Matcher<const ::std::vector<LhsValue>&> matcher_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(Impl); Impl(const Impl&) = delete;
Impl& operator=(const Impl&) = delete;
}; };
private: private:
const Comparator comparator_; const Comparator comparator_;
const ContainerMatcher matcher_; const ContainerMatcher matcher_;
}; };
// Implements Pointwise(tuple_matcher, rhs_container). tuple_matcher // Implements Pointwise(tuple_matcher, rhs_container). tuple_matcher
// must be able to be safely cast to Matcher<std::tuple<const T1&, const // must be able to be safely cast to Matcher<std::tuple<const T1&, const
// T2&> >, where T1 and T2 are the types of elements in the LHS // T2&> >, where T1 and T2 are the types of elements in the LHS
// 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_( static_assert(
!IsHashTable<GTEST_REMOVE_REFERENCE_AND_CONST_(RhsContainer)>::value, !IsHashTable<GTEST_REMOVE_REFERENCE_AND_CONST_(RhsContainer)>::value,
use_UnorderedPointwise_with_hash_tables); "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;
typedef typename RhsStlContainer::value_type RhsValue; typedef typename RhsStlContainer::value_type RhsValue;
static_assert(!std::is_const<RhsContainer>::value, static_assert(!std::is_const<RhsContainer>::value,
"RhsContainer type must not be const"); "RhsContainer type must not be const");
static_assert(!std::is_reference<RhsContainer>::value, static_assert(!std::is_reference<RhsContainer>::value,
"RhsContainer type must not be a reference"); "RhsContainer type must not be a reference");
// Like ContainerEq, we make a copy of rhs in case the elements in // Like ContainerEq, we make a copy of rhs in case the elements in
// it are modified after this matcher is created. // it are modified after this matcher is created.
PointwiseMatcher(const TupleMatcher& tuple_matcher, const RhsContainer& rhs) PointwiseMatcher(const TupleMatcher& tuple_matcher, const RhsContainer& rhs)
: tuple_matcher_(tuple_matcher), rhs_(RhsView::Copy(rhs)) {} : tuple_matcher_(tuple_matcher), rhs_(RhsView::Copy(rhs)) {}
template <typename LhsContainer> template <typename LhsContainer>
operator Matcher<LhsContainer>() const { operator Matcher<LhsContainer>() const {
GTEST_COMPILE_ASSERT_( static_assert(
!IsHashTable<GTEST_REMOVE_REFERENCE_AND_CONST_(LhsContainer)>::value, !IsHashTable<GTEST_REMOVE_REFERENCE_AND_CONST_(LhsContainer)>::value,
use_UnorderedPointwise_with_hash_tables); "use UnorderedPointwise with hash tables");
return Matcher<LhsContainer>( return Matcher<LhsContainer>(
new Impl<const LhsContainer&>(tuple_matcher_, rhs_)); new Impl<const LhsContainer&>(tuple_matcher_, rhs_));
} }
template <typename LhsContainer> template <typename LhsContainer>
class Impl : public MatcherInterface<LhsContainer> { class Impl : public MatcherInterface<LhsContainer> {
public: public:
typedef internal::StlContainerView< typedef internal::StlContainerView<GTEST_REMOVE_REFERENCE_AND_CONST_(
GTEST_REMOVE_REFERENCE_AND_CONST_(LhsContainer)> LhsView; LhsContainer)>
LhsView;
typedef typename LhsView::type LhsStlContainer; typedef typename LhsView::type LhsStlContainer;
typedef typename LhsView::const_reference LhsStlContainerReference; typedef typename LhsView::const_reference LhsStlContainerReference;
typedef typename LhsStlContainer::value_type LhsValue; typedef typename LhsStlContainer::value_type LhsValue;
// We pass the LHS value and the RHS value to the inner matcher by // We pass the LHS value and the RHS value to the inner matcher by
// reference, as they may be expensive to copy. We must use tuple // reference, as they may be expensive to copy. We must use tuple
// instead of pair here, as a pair cannot hold references (C++ 98, // instead of pair here, as a pair cannot hold references (C++ 98,
// 20.2.2 [lib.pairs]). // 20.2.2 [lib.pairs]).
typedef ::std::tuple<const LhsValue&, const RhsValue&> InnerMatcherArg; typedef ::std::tuple<const LhsValue&, const RhsValue&> InnerMatcherArg;
Impl(const TupleMatcher& tuple_matcher, const RhsStlContainer& rhs) Impl(const TupleMatcher& tuple_matcher, const RhsStlContainer& rhs)
skipping to change at line 2576 skipping to change at line 2649
bool MatchAndExplain(LhsContainer lhs, bool MatchAndExplain(LhsContainer lhs,
MatchResultListener* listener) const override { MatchResultListener* listener) const override {
LhsStlContainerReference lhs_stl_container = LhsView::ConstReference(lhs); LhsStlContainerReference lhs_stl_container = LhsView::ConstReference(lhs);
const size_t actual_size = lhs_stl_container.size(); const size_t actual_size = lhs_stl_container.size();
if (actual_size != rhs_.size()) { if (actual_size != rhs_.size()) {
*listener << "which contains " << actual_size << " values"; *listener << "which contains " << actual_size << " values";
return false; return false;
} }
typename LhsStlContainer::const_iterator left = lhs_stl_container.begin(); auto left = lhs_stl_container.begin();
typename RhsStlContainer::const_iterator right = rhs_.begin(); auto 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) {
if (listener->IsInterested()) { if (listener->IsInterested()) {
StringMatchResultListener inner_listener; StringMatchResultListener inner_listener;
// Create InnerMatcherArg as a temporarily object to avoid it outlives // Create InnerMatcherArg as a temporarily object to avoid it outlives
// *left and *right. Dereference or the conversion to `const T&` may // *left and *right. Dereference or the conversion to `const T&` may
// return temp objects, e.g for vector<bool>. // return temp objects, e.g. for vector<bool>.
if (!mono_tuple_matcher_.MatchAndExplain( if (!mono_tuple_matcher_.MatchAndExplain(
InnerMatcherArg(ImplicitCast_<const LhsValue&>(*left), InnerMatcherArg(ImplicitCast_<const LhsValue&>(*left),
ImplicitCast_<const RhsValue&>(*right)), ImplicitCast_<const RhsValue&>(*right)),
&inner_listener)) { &inner_listener)) {
*listener << "where the value pair ("; *listener << "where the value pair (";
UniversalPrint(*left, listener->stream()); UniversalPrint(*left, listener->stream());
*listener << ", "; *listener << ", ";
UniversalPrint(*right, listener->stream()); UniversalPrint(*right, listener->stream());
*listener << ") at index #" << i << " don't match"; *listener << ") at index #" << i << " don't match";
PrintIfNotEmpty(inner_listener.str(), listener->stream()); PrintIfNotEmpty(inner_listener.str(), listener->stream());
skipping to change at line 2630 skipping to change at line 2703
public: public:
typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer; typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer;
typedef StlContainerView<RawContainer> View; typedef StlContainerView<RawContainer> View;
typedef typename View::type StlContainer; typedef typename View::type StlContainer;
typedef typename View::const_reference StlContainerReference; typedef typename View::const_reference StlContainerReference;
typedef typename StlContainer::value_type Element; typedef typename StlContainer::value_type Element;
template <typename InnerMatcher> template <typename InnerMatcher>
explicit QuantifierMatcherImpl(InnerMatcher inner_matcher) explicit QuantifierMatcherImpl(InnerMatcher inner_matcher)
: inner_matcher_( : inner_matcher_(
testing::SafeMatcherCast<const Element&>(inner_matcher)) {} testing::SafeMatcherCast<const Element&>(inner_matcher)) {}
// Checks whether: // Checks whether:
// * All elements in the container match, if all_elements_should_match. // * All elements in the container match, if all_elements_should_match.
// * Any element in the container matches, if !all_elements_should_match. // * Any element in the container matches, if !all_elements_should_match.
bool MatchAndExplainImpl(bool all_elements_should_match, bool MatchAndExplainImpl(bool all_elements_should_match, Container container,
Container container,
MatchResultListener* listener) const { MatchResultListener* listener) const {
StlContainerReference stl_container = View::ConstReference(container); StlContainerReference stl_container = View::ConstReference(container);
size_t i = 0; size_t i = 0;
for (typename StlContainer::const_iterator it = stl_container.begin(); for (auto it = stl_container.begin(); it != stl_container.end();
it != stl_container.end(); ++it, ++i) { ++it, ++i) {
StringMatchResultListener inner_listener; StringMatchResultListener inner_listener;
const bool matches = inner_matcher_.MatchAndExplain(*it, &inner_listener); const bool matches = inner_matcher_.MatchAndExplain(*it, &inner_listener);
if (matches != all_elements_should_match) { if (matches != all_elements_should_match) {
*listener << "whose element #" << i *listener << "whose element #" << i
<< (matches ? " matches" : " doesn't match"); << (matches ? " matches" : " doesn't match");
PrintIfNotEmpty(inner_listener.str(), listener->stream()); PrintIfNotEmpty(inner_listener.str(), listener->stream());
return !all_elements_should_match; return !all_elements_should_match;
} }
} }
return all_elements_should_match; return all_elements_should_match;
} }
bool MatchAndExplainImpl(const Matcher<size_t>& count_matcher,
Container container,
MatchResultListener* listener) const {
StlContainerReference stl_container = View::ConstReference(container);
size_t i = 0;
std::vector<size_t> match_elements;
for (auto it = stl_container.begin(); it != stl_container.end();
++it, ++i) {
StringMatchResultListener inner_listener;
const bool matches = inner_matcher_.MatchAndExplain(*it, &inner_listener);
if (matches) {
match_elements.push_back(i);
}
}
if (listener->IsInterested()) {
if (match_elements.empty()) {
*listener << "has no element that matches";
} else if (match_elements.size() == 1) {
*listener << "whose element #" << match_elements[0] << " matches";
} else {
*listener << "whose elements (";
std::string sep = "";
for (size_t e : match_elements) {
*listener << sep << e;
sep = ", ";
}
*listener << ") match";
}
}
StringMatchResultListener count_listener;
if (count_matcher.MatchAndExplain(match_elements.size(), &count_listener)) {
*listener << " and whose match quantity of " << match_elements.size()
<< " matches";
PrintIfNotEmpty(count_listener.str(), listener->stream());
return true;
} else {
if (match_elements.empty()) {
*listener << " and";
} else {
*listener << " but";
}
*listener << " whose match quantity of " << match_elements.size()
<< " does not match";
PrintIfNotEmpty(count_listener.str(), listener->stream());
return false;
}
}
protected: protected:
const Matcher<const Element&> inner_matcher_; const Matcher<const Element&> inner_matcher_;
}; };
// Implements Contains(element_matcher) for the given argument type Container. // Implements Contains(element_matcher) for the given argument type Container.
// Symmetric to EachMatcherImpl. // Symmetric to EachMatcherImpl.
template <typename Container> template <typename Container>
class ContainsMatcherImpl : public QuantifierMatcherImpl<Container> { class ContainsMatcherImpl : public QuantifierMatcherImpl<Container> {
public: public:
template <typename InnerMatcher> template <typename InnerMatcher>
skipping to change at line 2711 skipping to change at line 2831
*os << "contains some element that "; *os << "contains some element that ";
this->inner_matcher_.DescribeNegationTo(os); this->inner_matcher_.DescribeNegationTo(os);
} }
bool MatchAndExplain(Container container, bool MatchAndExplain(Container container,
MatchResultListener* listener) const override { MatchResultListener* listener) const override {
return this->MatchAndExplainImpl(true, container, listener); return this->MatchAndExplainImpl(true, container, listener);
} }
}; };
// Implements Contains(element_matcher).Times(n) for the given argument type
// Container.
template <typename Container>
class ContainsTimesMatcherImpl : public QuantifierMatcherImpl<Container> {
public:
template <typename InnerMatcher>
explicit ContainsTimesMatcherImpl(InnerMatcher inner_matcher,
Matcher<size_t> count_matcher)
: QuantifierMatcherImpl<Container>(inner_matcher),
count_matcher_(std::move(count_matcher)) {}
void DescribeTo(::std::ostream* os) const override {
*os << "quantity of elements that match ";
this->inner_matcher_.DescribeTo(os);
*os << " ";
count_matcher_.DescribeTo(os);
}
void DescribeNegationTo(::std::ostream* os) const override {
*os << "quantity of elements that match ";
this->inner_matcher_.DescribeTo(os);
*os << " ";
count_matcher_.DescribeNegationTo(os);
}
bool MatchAndExplain(Container container,
MatchResultListener* listener) const override {
return this->MatchAndExplainImpl(count_matcher_, container, listener);
}
private:
const Matcher<size_t> count_matcher_;
};
// Implements polymorphic Contains(element_matcher).Times(n).
template <typename M>
class ContainsTimesMatcher {
public:
explicit ContainsTimesMatcher(M m, Matcher<size_t> count_matcher)
: inner_matcher_(m), count_matcher_(std::move(count_matcher)) {}
template <typename Container>
operator Matcher<Container>() const { // NOLINT
return Matcher<Container>(new ContainsTimesMatcherImpl<const Container&>(
inner_matcher_, count_matcher_));
}
private:
const M inner_matcher_;
const Matcher<size_t> count_matcher_;
};
// Implements polymorphic Contains(element_matcher). // Implements polymorphic Contains(element_matcher).
template <typename M> template <typename M>
class ContainsMatcher { class ContainsMatcher {
public: public:
explicit ContainsMatcher(M m) : inner_matcher_(m) {} explicit ContainsMatcher(M m) : inner_matcher_(m) {}
template <typename Container> template <typename Container>
operator Matcher<Container>() const { operator Matcher<Container>() const { // NOLINT
return Matcher<Container>( return Matcher<Container>(
new ContainsMatcherImpl<const Container&>(inner_matcher_)); new ContainsMatcherImpl<const Container&>(inner_matcher_));
} }
ContainsTimesMatcher<M> Times(Matcher<size_t> count_matcher) const {
return ContainsTimesMatcher<M>(inner_matcher_, std::move(count_matcher));
}
private: private:
const M inner_matcher_; const M inner_matcher_;
}; };
// Implements polymorphic Each(element_matcher). // Implements polymorphic Each(element_matcher).
template <typename M> template <typename M>
class EachMatcher { class EachMatcher {
public: public:
explicit EachMatcher(M m) : inner_matcher_(m) {} explicit EachMatcher(M m) : inner_matcher_(m) {}
template <typename Container> template <typename Container>
operator Matcher<Container>() const { operator Matcher<Container>() const { // NOLINT
return Matcher<Container>( return Matcher<Container>(
new EachMatcherImpl<const Container&>(inner_matcher_)); new EachMatcherImpl<const Container&>(inner_matcher_));
} }
private: private:
const M inner_matcher_; const M inner_matcher_;
}; };
struct Rank1 {}; struct Rank1 {};
struct Rank0 : Rank1 {}; struct Rank0 : Rank1 {};
skipping to change at line 2780 skipping to change at line 2956
// std::map that contains at least one element whose key is >= 5. // std::map that contains at least one element whose key is >= 5.
template <typename PairType> template <typename PairType>
class KeyMatcherImpl : public MatcherInterface<PairType> { class KeyMatcherImpl : public MatcherInterface<PairType> {
public: public:
typedef GTEST_REMOVE_REFERENCE_AND_CONST_(PairType) RawPairType; typedef GTEST_REMOVE_REFERENCE_AND_CONST_(PairType) RawPairType;
typedef typename RawPairType::first_type KeyType; typedef typename RawPairType::first_type KeyType;
template <typename InnerMatcher> template <typename InnerMatcher>
explicit KeyMatcherImpl(InnerMatcher inner_matcher) explicit KeyMatcherImpl(InnerMatcher inner_matcher)
: inner_matcher_( : inner_matcher_(
testing::SafeMatcherCast<const KeyType&>(inner_matcher)) { testing::SafeMatcherCast<const KeyType&>(inner_matcher)) {}
}
// Returns true if and only if 'key_value.first' (the key) matches the inner // Returns true if and only if 'key_value.first' (the key) matches the inner
// matcher. // matcher.
bool MatchAndExplain(PairType key_value, bool MatchAndExplain(PairType key_value,
MatchResultListener* listener) const override { MatchResultListener* listener) const override {
StringMatchResultListener inner_listener; StringMatchResultListener inner_listener;
const bool match = inner_matcher_.MatchAndExplain( const bool match = inner_matcher_.MatchAndExplain(
pair_getters::First(key_value, Rank0()), &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 != "") {
skipping to change at line 2886 skipping to change at line 3061
public: public:
typedef GTEST_REMOVE_REFERENCE_AND_CONST_(PairType) RawPairType; typedef GTEST_REMOVE_REFERENCE_AND_CONST_(PairType) RawPairType;
typedef typename RawPairType::first_type FirstType; typedef typename RawPairType::first_type FirstType;
typedef typename RawPairType::second_type SecondType; typedef typename RawPairType::second_type SecondType;
template <typename FirstMatcher, typename SecondMatcher> template <typename FirstMatcher, typename SecondMatcher>
PairMatcherImpl(FirstMatcher first_matcher, SecondMatcher second_matcher) PairMatcherImpl(FirstMatcher first_matcher, SecondMatcher second_matcher)
: first_matcher_( : first_matcher_(
testing::SafeMatcherCast<const FirstType&>(first_matcher)), testing::SafeMatcherCast<const FirstType&>(first_matcher)),
second_matcher_( second_matcher_(
testing::SafeMatcherCast<const SecondType&>(second_matcher)) { testing::SafeMatcherCast<const SecondType&>(second_matcher)) {}
}
// Describes what this matcher does. // Describes what this matcher does.
void DescribeTo(::std::ostream* os) const override { void DescribeTo(::std::ostream* os) const override {
*os << "has a first field that "; *os << "has a first field that ";
first_matcher_.DescribeTo(os); first_matcher_.DescribeTo(os);
*os << ", and has a second field that "; *os << ", and has a second field that ";
second_matcher_.DescribeTo(os); second_matcher_.DescribeTo(os);
} }
// Describes what the negation of this matcher does. // Describes what the negation of this matcher does.
skipping to change at line 2965 skipping to change at line 3139
}; };
// Implements polymorphic Pair(first_matcher, second_matcher). // Implements polymorphic Pair(first_matcher, second_matcher).
template <typename FirstMatcher, typename SecondMatcher> template <typename FirstMatcher, typename SecondMatcher>
class PairMatcher { class PairMatcher {
public: public:
PairMatcher(FirstMatcher first_matcher, SecondMatcher second_matcher) PairMatcher(FirstMatcher first_matcher, SecondMatcher second_matcher)
: first_matcher_(first_matcher), second_matcher_(second_matcher) {} : first_matcher_(first_matcher), second_matcher_(second_matcher) {}
template <typename PairType> template <typename PairType>
operator Matcher<PairType> () const { operator Matcher<PairType>() const {
return Matcher<PairType>( return Matcher<PairType>(
new PairMatcherImpl<const PairType&>(first_matcher_, second_matcher_)); new PairMatcherImpl<const PairType&>(first_matcher_, second_matcher_));
} }
private: private:
const FirstMatcher first_matcher_; const FirstMatcher first_matcher_;
const SecondMatcher second_matcher_; const SecondMatcher second_matcher_;
}; };
template <typename T, size_t... I> template <typename T, size_t... I>
skipping to change at line 3237 skipping to change at line 3411
bool MatchAndExplain(Container container, bool MatchAndExplain(Container container,
MatchResultListener* listener) const override { MatchResultListener* listener) const override {
// To work with stream-like "containers", we must only walk // To work with stream-like "containers", we must only walk
// through the elements in one pass. // through the elements in one pass.
const bool listener_interested = listener->IsInterested(); const bool listener_interested = listener->IsInterested();
// explanations[i] is the explanation of the element at index i. // explanations[i] is the explanation of the element at index i.
::std::vector<std::string> explanations(count()); ::std::vector<std::string> explanations(count());
StlContainerReference stl_container = View::ConstReference(container); StlContainerReference stl_container = View::ConstReference(container);
typename StlContainer::const_iterator it = stl_container.begin(); auto it = stl_container.begin();
size_t exam_pos = 0; size_t exam_pos = 0;
bool mismatch_found = false; // Have we found a mismatched element yet? bool mismatch_found = false; // Have we found a mismatched element yet?
// Go through the elements and matchers in pairs, until we reach // Go through the elements and matchers in pairs, until we reach
// the end of either the elements or the matchers, or until we find a // the end of either the elements or the matchers, or until we find a
// mismatch. // mismatch.
for (; it != stl_container.end() && exam_pos != count(); ++it, ++exam_pos) { for (; it != stl_container.end() && exam_pos != count(); ++it, ++exam_pos) {
bool match; // Does the current element match the current matcher? bool match; // Does the current element match the current matcher?
if (listener_interested) { if (listener_interested) {
StringMatchResultListener s; StringMatchResultListener s;
skipping to change at line 3314 skipping to change at line 3488
return true; return true;
} }
private: private:
static Message Elements(size_t count) { static Message Elements(size_t count) {
return Message() << count << (count == 1 ? " element" : " elements"); return Message() << count << (count == 1 ? " element" : " elements");
} }
size_t count() const { return matchers_.size(); } size_t count() const { return matchers_.size(); }
::std::vector<Matcher<const Element&> > matchers_; ::std::vector<Matcher<const Element&>> matchers_;
}; };
// Connectivity matrix of (elements X matchers), in element-major order. // Connectivity matrix of (elements X matchers), in element-major order.
// Initially, there are no edges. // Initially, there are no edges.
// Use NextGraph() to iterate over all possible edge configurations. // Use NextGraph() to iterate over all possible edge configurations.
// Use Randomize() to generate a random edge configuration. // Use Randomize() to generate a random edge configuration.
class GTEST_API_ MatchMatrix { class GTEST_API_ MatchMatrix {
public: public:
MatchMatrix(size_t num_elements, size_t num_matchers) MatchMatrix(size_t num_elements, size_t num_matchers)
: num_elements_(num_elements), : num_elements_(num_elements),
num_matchers_(num_matchers), num_matchers_(num_matchers),
matched_(num_elements_* num_matchers_, 0) { matched_(num_elements_ * num_matchers_, 0) {}
}
size_t LhsSize() const { return num_elements_; } size_t LhsSize() const { return num_elements_; }
size_t RhsSize() const { return num_matchers_; } size_t RhsSize() const { return num_matchers_; }
bool HasEdge(size_t ilhs, size_t irhs) const { bool HasEdge(size_t ilhs, size_t irhs) const {
return matched_[SpaceIndex(ilhs, irhs)] == 1; return matched_[SpaceIndex(ilhs, irhs)] == 1;
} }
void SetEdge(size_t ilhs, size_t irhs, bool b) { void SetEdge(size_t ilhs, size_t irhs, bool b) {
matched_[SpaceIndex(ilhs, irhs)] = b ? 1 : 0; matched_[SpaceIndex(ilhs, irhs)] = b ? 1 : 0;
} }
skipping to change at line 3366 skipping to change at line 3539
// flattened array in lhs-major order, use 'SpaceIndex()' to translate // flattened array in lhs-major order, use 'SpaceIndex()' to translate
// a (ilhs, irhs) matrix coordinate into an offset. // a (ilhs, irhs) matrix coordinate into an offset.
::std::vector<char> matched_; ::std::vector<char> matched_;
}; };
typedef ::std::pair<size_t, size_t> ElementMatcherPair; typedef ::std::pair<size_t, size_t> ElementMatcherPair;
typedef ::std::vector<ElementMatcherPair> ElementMatcherPairs; typedef ::std::vector<ElementMatcherPair> ElementMatcherPairs;
// Returns a maximum bipartite matching for the specified graph 'g'. // Returns a maximum bipartite matching for the specified graph 'g'.
// The matching is represented as a vector of {element, matcher} pairs. // The matching is represented as a vector of {element, matcher} pairs.
GTEST_API_ ElementMatcherPairs GTEST_API_ ElementMatcherPairs FindMaxBipartiteMatching(const MatchMatrix& g);
FindMaxBipartiteMatching(const MatchMatrix& g);
struct UnorderedMatcherRequire { struct UnorderedMatcherRequire {
enum Flags { enum Flags {
Superset = 1 << 0, Superset = 1 << 0,
Subset = 1 << 1, Subset = 1 << 1,
ExactMatch = Superset | Subset, ExactMatch = Superset | Subset,
}; };
}; };
// Untyped base class for implementing UnorderedElementsAre. By // Untyped base class for implementing UnorderedElementsAre. By
skipping to change at line 3404 skipping to change at line 3576
// Describes the negation of this UnorderedElementsAre matcher. // Describes the negation of this UnorderedElementsAre matcher.
void DescribeNegationToImpl(::std::ostream* os) const; void DescribeNegationToImpl(::std::ostream* os) const;
bool VerifyMatchMatrix(const ::std::vector<std::string>& element_printouts, bool VerifyMatchMatrix(const ::std::vector<std::string>& element_printouts,
const MatchMatrix& matrix, const MatchMatrix& matrix,
MatchResultListener* listener) const; MatchResultListener* listener) const;
bool FindPairing(const MatchMatrix& matrix, bool FindPairing(const MatchMatrix& matrix,
MatchResultListener* listener) const; MatchResultListener* listener) const;
MatcherDescriberVec& matcher_describers() { MatcherDescriberVec& matcher_describers() { return matcher_describers_; }
return matcher_describers_;
}
static Message Elements(size_t n) { static Message Elements(size_t n) {
return Message() << n << " element" << (n == 1 ? "" : "s"); return Message() << n << " element" << (n == 1 ? "" : "s");
} }
UnorderedMatcherRequire::Flags match_flags() const { return match_flags_; } UnorderedMatcherRequire::Flags match_flags() const { return match_flags_; }
private: private:
UnorderedMatcherRequire::Flags match_flags_; UnorderedMatcherRequire::Flags match_flags_;
MatcherDescriberVec matcher_describers_; MatcherDescriberVec matcher_describers_;
skipping to change at line 3430 skipping to change at line 3600
// IsSupersetOf. // IsSupersetOf.
template <typename Container> template <typename Container>
class UnorderedElementsAreMatcherImpl class UnorderedElementsAreMatcherImpl
: public MatcherInterface<Container>, : public MatcherInterface<Container>,
public UnorderedElementsAreMatcherImplBase { public UnorderedElementsAreMatcherImplBase {
public: public:
typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer; typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer;
typedef internal::StlContainerView<RawContainer> View; typedef internal::StlContainerView<RawContainer> View;
typedef typename View::type StlContainer; typedef typename View::type StlContainer;
typedef typename View::const_reference StlContainerReference; typedef typename View::const_reference StlContainerReference;
typedef typename StlContainer::const_iterator StlContainerConstIterator;
typedef typename StlContainer::value_type Element; typedef typename StlContainer::value_type Element;
template <typename InputIter> template <typename InputIter>
UnorderedElementsAreMatcherImpl(UnorderedMatcherRequire::Flags matcher_flags, UnorderedElementsAreMatcherImpl(UnorderedMatcherRequire::Flags matcher_flags,
InputIter first, InputIter last) InputIter first, InputIter last)
: UnorderedElementsAreMatcherImplBase(matcher_flags) { : UnorderedElementsAreMatcherImplBase(matcher_flags) {
for (; first != last; ++first) { for (; first != last; ++first) {
matchers_.push_back(MatcherCast<const Element&>(*first)); matchers_.push_back(MatcherCast<const Element&>(*first));
} }
for (const auto& m : matchers_) { for (const auto& m : matchers_) {
skipping to change at line 3513 skipping to change at line 3682
MatchMatrix matrix(num_elements, matchers_.size()); MatchMatrix matrix(num_elements, matchers_.size());
::std::vector<char>::const_iterator did_match_iter = did_match.begin(); ::std::vector<char>::const_iterator did_match_iter = did_match.begin();
for (size_t ilhs = 0; ilhs != num_elements; ++ilhs) { for (size_t ilhs = 0; ilhs != num_elements; ++ilhs) {
for (size_t irhs = 0; irhs != matchers_.size(); ++irhs) { for (size_t irhs = 0; irhs != matchers_.size(); ++irhs) {
matrix.SetEdge(ilhs, irhs, *did_match_iter++ != 0); matrix.SetEdge(ilhs, irhs, *did_match_iter++ != 0);
} }
} }
return matrix; return matrix;
} }
::std::vector<Matcher<const Element&> > matchers_; ::std::vector<Matcher<const Element&>> matchers_;
}; };
// Functor for use in TransformTuple. // Functor for use in TransformTuple.
// Performs MatcherCast<Target> on an input argument of any type. // Performs MatcherCast<Target> on an input argument of any type.
template <typename Target> template <typename Target>
struct CastAndAppendTransform { struct CastAndAppendTransform {
template <typename Arg> template <typename Arg>
Matcher<Target> operator()(const Arg& a) const { Matcher<Target> operator()(const Arg& a) const {
return MatcherCast<Target>(a); return MatcherCast<Target>(a);
} }
skipping to change at line 3538 skipping to change at line 3707
class UnorderedElementsAreMatcher { class UnorderedElementsAreMatcher {
public: public:
explicit UnorderedElementsAreMatcher(const MatcherTuple& args) explicit UnorderedElementsAreMatcher(const MatcherTuple& args)
: matchers_(args) {} : matchers_(args) {}
template <typename Container> template <typename Container>
operator Matcher<Container>() const { operator Matcher<Container>() const {
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;
typedef ::std::vector<Matcher<const Element&> > MatcherVec; typedef ::std::vector<Matcher<const Element&>> MatcherVec;
MatcherVec matchers; MatcherVec matchers;
matchers.reserve(::std::tuple_size<MatcherTuple>::value); matchers.reserve(::std::tuple_size<MatcherTuple>::value);
TransformTupleValues(CastAndAppendTransform<const Element&>(), matchers_, TransformTupleValues(CastAndAppendTransform<const Element&>(), matchers_,
::std::back_inserter(matchers)); ::std::back_inserter(matchers));
return Matcher<Container>( return Matcher<Container>(
new UnorderedElementsAreMatcherImpl<const Container&>( new UnorderedElementsAreMatcherImpl<const Container&>(
UnorderedMatcherRequire::ExactMatch, matchers.begin(), UnorderedMatcherRequire::ExactMatch, matchers.begin(),
matchers.end())); matchers.end()));
} }
skipping to change at line 3561 skipping to change at line 3730
}; };
// Implements ElementsAre. // Implements ElementsAre.
template <typename MatcherTuple> template <typename MatcherTuple>
class ElementsAreMatcher { class ElementsAreMatcher {
public: public:
explicit ElementsAreMatcher(const MatcherTuple& args) : matchers_(args) {} explicit ElementsAreMatcher(const MatcherTuple& args) : matchers_(args) {}
template <typename Container> template <typename Container>
operator Matcher<Container>() const { operator Matcher<Container>() const {
GTEST_COMPILE_ASSERT_( static_assert(
!IsHashTable<GTEST_REMOVE_REFERENCE_AND_CONST_(Container)>::value || !IsHashTable<GTEST_REMOVE_REFERENCE_AND_CONST_(Container)>::value ||
::std::tuple_size<MatcherTuple>::value < 2, ::std::tuple_size<MatcherTuple>::value < 2,
use_UnorderedElementsAre_with_hash_tables); "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;
typedef ::std::vector<Matcher<const Element&> > MatcherVec; typedef ::std::vector<Matcher<const Element&>> MatcherVec;
MatcherVec matchers; MatcherVec matchers;
matchers.reserve(::std::tuple_size<MatcherTuple>::value); matchers.reserve(::std::tuple_size<MatcherTuple>::value);
TransformTupleValues(CastAndAppendTransform<const Element&>(), matchers_, TransformTupleValues(CastAndAppendTransform<const Element&>(), matchers_,
::std::back_inserter(matchers)); ::std::back_inserter(matchers));
return Matcher<Container>(new ElementsAreMatcherImpl<const Container&>( return Matcher<Container>(new ElementsAreMatcherImpl<const Container&>(
matchers.begin(), matchers.end())); matchers.begin(), matchers.end()));
} }
private: private:
const MatcherTuple matchers_; const MatcherTuple matchers_;
skipping to change at line 3612 skipping to change at line 3781
// Implements ElementsAreArray(). // Implements ElementsAreArray().
template <typename T> template <typename T>
class ElementsAreArrayMatcher { class ElementsAreArrayMatcher {
public: public:
template <typename Iter> template <typename Iter>
ElementsAreArrayMatcher(Iter first, Iter last) : matchers_(first, last) {} ElementsAreArrayMatcher(Iter first, Iter last) : matchers_(first, last) {}
template <typename Container> template <typename Container>
operator Matcher<Container>() const { operator Matcher<Container>() const {
GTEST_COMPILE_ASSERT_( static_assert(
!IsHashTable<GTEST_REMOVE_REFERENCE_AND_CONST_(Container)>::value, !IsHashTable<GTEST_REMOVE_REFERENCE_AND_CONST_(Container)>::value,
use_UnorderedElementsAreArray_with_hash_tables); "use UnorderedElementsAreArray with hash tables");
return Matcher<Container>(new ElementsAreMatcherImpl<const Container&>( return Matcher<Container>(new ElementsAreMatcherImpl<const Container&>(
matchers_.begin(), matchers_.end())); matchers_.begin(), matchers_.end()));
} }
private: private:
const ::std::vector<T> matchers_; const ::std::vector<T> matchers_;
}; };
// Given a 2-tuple matcher tm of type Tuple2Matcher and a value second // Given a 2-tuple matcher tm of type Tuple2Matcher and a value second
skipping to change at line 3704 skipping to change at line 3873
BoundSecondMatcher<Tuple2Matcher, Second> MatcherBindSecond( BoundSecondMatcher<Tuple2Matcher, Second> MatcherBindSecond(
const Tuple2Matcher& tm, const Second& second) { const Tuple2Matcher& tm, const Second& second) {
return BoundSecondMatcher<Tuple2Matcher, Second>(tm, second); return BoundSecondMatcher<Tuple2Matcher, Second>(tm, second);
} }
// Returns the description for a matcher defined using the MATCHER*() // Returns the description for a matcher defined using the MATCHER*()
// macro where the user-supplied description string is "", if // macro where the user-supplied description string is "", if
// 'negation' is false; otherwise returns the description of the // 'negation' is false; otherwise returns the description of the
// negation of the matcher. 'param_values' contains a list of strings // negation of the matcher. 'param_values' contains a list of strings
// that are the print-out of the matcher's parameters. // that are the print-out of the matcher's parameters.
GTEST_API_ std::string FormatMatcherDescription(bool negation, GTEST_API_ std::string FormatMatcherDescription(
const char* matcher_name, bool negation, const char* matcher_name,
const Strings& param_values); const std::vector<const char*>& param_names, const Strings& param_values);
// Implements a matcher that checks the value of a optional<> type variable. // Implements a matcher that checks the value of a optional<> type variable.
template <typename ValueMatcher> template <typename ValueMatcher>
class OptionalMatcher { class OptionalMatcher {
public: public:
explicit OptionalMatcher(const ValueMatcher& value_matcher) explicit OptionalMatcher(const ValueMatcher& value_matcher)
: value_matcher_(value_matcher) {} : value_matcher_(value_matcher) {}
template <typename Optional> template <typename Optional>
operator Matcher<Optional>() const { operator Matcher<Optional>() const {
skipping to change at line 3983 skipping to change at line 4152
template <typename Iter> template <typename Iter>
inline internal::ElementsAreArrayMatcher< inline internal::ElementsAreArrayMatcher<
typename ::std::iterator_traits<Iter>::value_type> typename ::std::iterator_traits<Iter>::value_type>
ElementsAreArray(Iter first, Iter last) { ElementsAreArray(Iter first, Iter last) {
typedef typename ::std::iterator_traits<Iter>::value_type T; typedef typename ::std::iterator_traits<Iter>::value_type T;
return internal::ElementsAreArrayMatcher<T>(first, last); return internal::ElementsAreArrayMatcher<T>(first, last);
} }
template <typename T> template <typename T>
inline internal::ElementsAreArrayMatcher<T> ElementsAreArray( inline auto ElementsAreArray(const T* pointer, size_t count)
const T* pointer, size_t count) { -> decltype(ElementsAreArray(pointer, pointer + count)) {
return ElementsAreArray(pointer, pointer + count); return ElementsAreArray(pointer, pointer + count);
} }
template <typename T, size_t N> template <typename T, size_t N>
inline internal::ElementsAreArrayMatcher<T> ElementsAreArray( inline auto ElementsAreArray(const T (&array)[N])
const T (&array)[N]) { -> decltype(ElementsAreArray(array, N)) {
return ElementsAreArray(array, N); return ElementsAreArray(array, N);
} }
template <typename Container> template <typename Container>
inline internal::ElementsAreArrayMatcher<typename Container::value_type> inline auto ElementsAreArray(const Container& container)
ElementsAreArray(const Container& container) { -> decltype(ElementsAreArray(container.begin(), container.end())) {
return ElementsAreArray(container.begin(), container.end()); return ElementsAreArray(container.begin(), container.end());
} }
template <typename T> template <typename T>
inline internal::ElementsAreArrayMatcher<T> inline auto ElementsAreArray(::std::initializer_list<T> xs)
ElementsAreArray(::std::initializer_list<T> xs) { -> decltype(ElementsAreArray(xs.begin(), xs.end())) {
return ElementsAreArray(xs.begin(), xs.end()); return ElementsAreArray(xs.begin(), xs.end());
} }
// UnorderedElementsAreArray(iterator_first, iterator_last) // UnorderedElementsAreArray(iterator_first, iterator_last)
// UnorderedElementsAreArray(pointer, count) // UnorderedElementsAreArray(pointer, count)
// UnorderedElementsAreArray(array) // UnorderedElementsAreArray(array)
// UnorderedElementsAreArray(container) // UnorderedElementsAreArray(container)
// UnorderedElementsAreArray({ e1, e2, ..., en }) // UnorderedElementsAreArray({ e1, e2, ..., en })
// //
// UnorderedElementsAreArray() verifies that a bijective mapping onto a // UnorderedElementsAreArray() verifies that a bijective mapping onto a
skipping to change at line 4029 skipping to change at line 4198
template <typename Iter> template <typename Iter>
inline internal::UnorderedElementsAreArrayMatcher< inline internal::UnorderedElementsAreArrayMatcher<
typename ::std::iterator_traits<Iter>::value_type> typename ::std::iterator_traits<Iter>::value_type>
UnorderedElementsAreArray(Iter first, Iter last) { UnorderedElementsAreArray(Iter first, Iter last) {
typedef typename ::std::iterator_traits<Iter>::value_type T; typedef typename ::std::iterator_traits<Iter>::value_type T;
return internal::UnorderedElementsAreArrayMatcher<T>( return internal::UnorderedElementsAreArrayMatcher<T>(
internal::UnorderedMatcherRequire::ExactMatch, first, last); internal::UnorderedMatcherRequire::ExactMatch, first, last);
} }
template <typename T> template <typename T>
inline internal::UnorderedElementsAreArrayMatcher<T> inline internal::UnorderedElementsAreArrayMatcher<T> UnorderedElementsAreArray(
UnorderedElementsAreArray(const T* pointer, size_t count) { const T* pointer, size_t count) {
return UnorderedElementsAreArray(pointer, pointer + count); return UnorderedElementsAreArray(pointer, pointer + count);
} }
template <typename T, size_t N> template <typename T, size_t N>
inline internal::UnorderedElementsAreArrayMatcher<T> inline internal::UnorderedElementsAreArrayMatcher<T> UnorderedElementsAreArray(
UnorderedElementsAreArray(const T (&array)[N]) { const T (&array)[N]) {
return UnorderedElementsAreArray(array, N); return UnorderedElementsAreArray(array, N);
} }
template <typename Container> template <typename Container>
inline internal::UnorderedElementsAreArrayMatcher< inline internal::UnorderedElementsAreArrayMatcher<
typename Container::value_type> typename Container::value_type>
UnorderedElementsAreArray(const Container& container) { UnorderedElementsAreArray(const Container& container) {
return UnorderedElementsAreArray(container.begin(), container.end()); return UnorderedElementsAreArray(container.begin(), container.end());
} }
template <typename T> template <typename T>
inline internal::UnorderedElementsAreArrayMatcher<T> inline internal::UnorderedElementsAreArrayMatcher<T> UnorderedElementsAreArray(
UnorderedElementsAreArray(::std::initializer_list<T> xs) { ::std::initializer_list<T> xs) {
return UnorderedElementsAreArray(xs.begin(), xs.end()); return UnorderedElementsAreArray(xs.begin(), xs.end());
} }
// _ is a matcher that matches anything of any type. // _ is a matcher that matches anything of any type.
// //
// This definition is fine as: // This definition is fine as:
// //
// 1. The C++ standard permits using the name _ in a namespace that // 1. The C++ standard permits using the name _ in a namespace that
// is not the global namespace or ::std. // is not the global namespace or ::std.
// 2. The AnythingMatcher class has no data member or constructor, // 2. The AnythingMatcher class has no data member or constructor,
skipping to change at line 4083 skipping to change at line 4252
} }
template <typename T, typename M> template <typename T, typename M>
Matcher<T> internal::MatcherCastImpl<T, M>::CastImpl( Matcher<T> internal::MatcherCastImpl<T, M>::CastImpl(
const M& value, std::false_type /* convertible_to_matcher */, const M& value, std::false_type /* convertible_to_matcher */,
std::false_type /* convertible_to_T */) { std::false_type /* convertible_to_T */) {
return Eq(value); return Eq(value);
} }
// Creates a polymorphic matcher that matches any NULL pointer. // Creates a polymorphic matcher that matches any NULL pointer.
inline PolymorphicMatcher<internal::IsNullMatcher > IsNull() { inline PolymorphicMatcher<internal::IsNullMatcher> IsNull() {
return MakePolymorphicMatcher(internal::IsNullMatcher()); return MakePolymorphicMatcher(internal::IsNullMatcher());
} }
// Creates a polymorphic matcher that matches any non-NULL pointer. // Creates a polymorphic matcher that matches any non-NULL pointer.
// This is convenient as Not(NULL) doesn't compile (the compiler // This is convenient as Not(NULL) doesn't compile (the compiler
// thinks that that expression is comparing a pointer with an integer). // thinks that that expression is comparing a pointer with an integer).
inline PolymorphicMatcher<internal::NotNullMatcher > NotNull() { inline PolymorphicMatcher<internal::NotNullMatcher> NotNull() {
return MakePolymorphicMatcher(internal::NotNullMatcher()); return MakePolymorphicMatcher(internal::NotNullMatcher());
} }
// Creates a polymorphic matcher that matches any argument that // Creates a polymorphic matcher that matches any argument that
// references variable x. // references variable x.
template <typename T> template <typename T>
inline internal::RefMatcher<T&> Ref(T& x) { // NOLINT inline internal::RefMatcher<T&> Ref(T& x) { // NOLINT
return internal::RefMatcher<T&>(x); return internal::RefMatcher<T&>(x);
} }
skipping to change at line 4121 skipping to change at line 4290
// Creates a matcher that matches any double argument approximately // Creates a matcher that matches any double argument approximately
// equal to rhs, including NaN values when rhs is NaN. // equal to rhs, including NaN values when rhs is NaN.
inline internal::FloatingEqMatcher<double> NanSensitiveDoubleEq(double rhs) { inline internal::FloatingEqMatcher<double> NanSensitiveDoubleEq(double rhs) {
return internal::FloatingEqMatcher<double>(rhs, true); return internal::FloatingEqMatcher<double>(rhs, true);
} }
// Creates a matcher that matches any double argument approximately equal to // Creates a matcher that matches any double argument approximately equal to
// rhs, up to the specified max absolute error bound, where two NANs are // rhs, up to the specified max absolute error bound, where two NANs are
// considered unequal. The max absolute error bound must be non-negative. // considered unequal. The max absolute error bound must be non-negative.
inline internal::FloatingEqMatcher<double> DoubleNear( inline internal::FloatingEqMatcher<double> DoubleNear(double rhs,
double rhs, double max_abs_error) { double max_abs_error) {
return internal::FloatingEqMatcher<double>(rhs, false, max_abs_error); return internal::FloatingEqMatcher<double>(rhs, false, max_abs_error);
} }
// Creates a matcher that matches any double argument approximately equal to // Creates a matcher that matches any double argument approximately equal to
// rhs, up to the specified max absolute error bound, including NaN values when // rhs, up to the specified max absolute error bound, including NaN values when
// rhs is NaN. The max absolute error bound must be non-negative. // rhs is NaN. The max absolute error bound must be non-negative.
inline internal::FloatingEqMatcher<double> NanSensitiveDoubleNear( inline internal::FloatingEqMatcher<double> NanSensitiveDoubleNear(
double rhs, double max_abs_error) { double rhs, double max_abs_error) {
return internal::FloatingEqMatcher<double>(rhs, true, max_abs_error); return internal::FloatingEqMatcher<double>(rhs, true, max_abs_error);
} }
skipping to change at line 4149 skipping to change at line 4318
// Creates a matcher that matches any float argument approximately // Creates a matcher that matches any float argument approximately
// equal to rhs, including NaN values when rhs is NaN. // equal to rhs, including NaN values when rhs is NaN.
inline internal::FloatingEqMatcher<float> NanSensitiveFloatEq(float rhs) { inline internal::FloatingEqMatcher<float> NanSensitiveFloatEq(float rhs) {
return internal::FloatingEqMatcher<float>(rhs, true); return internal::FloatingEqMatcher<float>(rhs, true);
} }
// Creates a matcher that matches any float argument approximately equal to // Creates a matcher that matches any float argument approximately equal to
// rhs, up to the specified max absolute error bound, where two NANs are // rhs, up to the specified max absolute error bound, where two NANs are
// considered unequal. The max absolute error bound must be non-negative. // considered unequal. The max absolute error bound must be non-negative.
inline internal::FloatingEqMatcher<float> FloatNear( inline internal::FloatingEqMatcher<float> FloatNear(float rhs,
float rhs, float max_abs_error) { float max_abs_error) {
return internal::FloatingEqMatcher<float>(rhs, false, max_abs_error); return internal::FloatingEqMatcher<float>(rhs, false, max_abs_error);
} }
// Creates a matcher that matches any float argument approximately equal to // Creates a matcher that matches any float argument approximately equal to
// rhs, up to the specified max absolute error bound, including NaN values when // rhs, up to the specified max absolute error bound, including NaN values when
// rhs is NaN. The max absolute error bound must be non-negative. // rhs is NaN. The max absolute error bound must be non-negative.
inline internal::FloatingEqMatcher<float> NanSensitiveFloatNear( inline internal::FloatingEqMatcher<float> NanSensitiveFloatNear(
float rhs, float max_abs_error) { float rhs, float max_abs_error) {
return internal::FloatingEqMatcher<float>(rhs, true, max_abs_error); return internal::FloatingEqMatcher<float>(rhs, true, max_abs_error);
} }
skipping to change at line 4178 skipping to change at line 4347
} }
#if GTEST_HAS_RTTI #if GTEST_HAS_RTTI
// Creates a matcher that matches a pointer or reference that matches // Creates a matcher that matches a pointer or reference that matches
// inner_matcher when dynamic_cast<To> is applied. // inner_matcher when dynamic_cast<To> is applied.
// The result of dynamic_cast<To> is forwarded to the inner matcher. // The result of dynamic_cast<To> is forwarded to the inner matcher.
// If To is a pointer and the cast fails, the inner matcher will receive NULL. // If To is a pointer and the cast fails, the inner matcher will receive NULL.
// If To is a reference and the cast fails, this matcher returns false // If To is a reference and the cast fails, this matcher returns false
// immediately. // immediately.
template <typename To> template <typename To>
inline PolymorphicMatcher<internal::WhenDynamicCastToMatcher<To> > inline PolymorphicMatcher<internal::WhenDynamicCastToMatcher<To>>
WhenDynamicCastTo(const Matcher<To>& inner_matcher) { WhenDynamicCastTo(const Matcher<To>& inner_matcher) {
return MakePolymorphicMatcher( return MakePolymorphicMatcher(
internal::WhenDynamicCastToMatcher<To>(inner_matcher)); internal::WhenDynamicCastToMatcher<To>(inner_matcher));
} }
#endif // GTEST_HAS_RTTI #endif // GTEST_HAS_RTTI
// Creates a matcher that matches an object whose given field matches // Creates a matcher that matches an object whose given field matches
// 'matcher'. For example, // 'matcher'. For example,
// Field(&Foo::number, Ge(5)) // Field(&Foo::number, Ge(5))
// matches a Foo object x if and only if x.number >= 5. // matches a Foo object x if and only if x.number >= 5.
template <typename Class, typename FieldType, typename FieldMatcher> template <typename Class, typename FieldType, typename FieldMatcher>
inline PolymorphicMatcher< inline PolymorphicMatcher<internal::FieldMatcher<Class, FieldType>> Field(
internal::FieldMatcher<Class, FieldType> > Field(
FieldType Class::*field, const FieldMatcher& matcher) { FieldType Class::*field, const FieldMatcher& matcher) {
return MakePolymorphicMatcher( return MakePolymorphicMatcher(internal::FieldMatcher<Class, FieldType>(
internal::FieldMatcher<Class, FieldType>( field, MatcherCast<const FieldType&>(matcher)));
field, MatcherCast<const FieldType&>(matcher)));
// The call to MatcherCast() is required for supporting inner // The call to MatcherCast() is required for supporting inner
// matchers of compatible types. For example, it allows // matchers of compatible types. For example, it allows
// Field(&Foo::bar, m) // Field(&Foo::bar, m)
// 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 // Same as Field() but also takes the name of the field to provide better error
// messages. // messages.
template <typename Class, typename FieldType, typename FieldMatcher> template <typename Class, typename FieldType, typename FieldMatcher>
inline PolymorphicMatcher<internal::FieldMatcher<Class, FieldType> > Field( inline PolymorphicMatcher<internal::FieldMatcher<Class, FieldType>> Field(
const std::string& field_name, FieldType Class::*field, const std::string& field_name, FieldType Class::*field,
const FieldMatcher& matcher) { const FieldMatcher& matcher) {
return MakePolymorphicMatcher(internal::FieldMatcher<Class, FieldType>( return MakePolymorphicMatcher(internal::FieldMatcher<Class, FieldType>(
field_name, field, MatcherCast<const FieldType&>(matcher))); 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"))
// matches a Foo object x if and only if x.str() starts with "hi". // matches a Foo object x if and only if x.str() starts with "hi".
template <typename Class, typename PropertyType, typename PropertyMatcher> template <typename Class, typename PropertyType, typename PropertyMatcher>
inline PolymorphicMatcher<internal::PropertyMatcher< inline PolymorphicMatcher<internal::PropertyMatcher<
Class, PropertyType, PropertyType (Class::*)() const> > Class, PropertyType, PropertyType (Class::*)() const>>
Property(PropertyType (Class::*property)() const, Property(PropertyType (Class::*property)() const,
const PropertyMatcher& matcher) { const PropertyMatcher& matcher) {
return MakePolymorphicMatcher( return MakePolymorphicMatcher(
internal::PropertyMatcher<Class, PropertyType, internal::PropertyMatcher<Class, PropertyType,
PropertyType (Class::*)() const>( PropertyType (Class::*)() const>(
property, MatcherCast<const PropertyType&>(matcher))); property, MatcherCast<const PropertyType&>(matcher)));
// The call to MatcherCast() is required for supporting inner // The call to MatcherCast() is required for supporting inner
// matchers of compatible types. For example, it allows // matchers of compatible types. For example, it allows
// Property(&Foo::bar, m) // Property(&Foo::bar, m)
// 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 // Same as Property() above, but also takes the name of the property to provide
// better error messages. // better error messages.
template <typename Class, typename PropertyType, typename PropertyMatcher> template <typename Class, typename PropertyType, typename PropertyMatcher>
inline PolymorphicMatcher<internal::PropertyMatcher< inline PolymorphicMatcher<internal::PropertyMatcher<
Class, PropertyType, PropertyType (Class::*)() const> > Class, PropertyType, PropertyType (Class::*)() const>>
Property(const std::string& property_name, Property(const std::string& property_name,
PropertyType (Class::*property)() const, PropertyType (Class::*property)() const,
const PropertyMatcher& matcher) { const PropertyMatcher& matcher) {
return MakePolymorphicMatcher( return MakePolymorphicMatcher(
internal::PropertyMatcher<Class, PropertyType, internal::PropertyMatcher<Class, PropertyType,
PropertyType (Class::*)() const>( PropertyType (Class::*)() const>(
property_name, property, MatcherCast<const PropertyType&>(matcher))); property_name, property, MatcherCast<const PropertyType&>(matcher)));
} }
// 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>
inline PolymorphicMatcher<internal::PropertyMatcher< inline PolymorphicMatcher<internal::PropertyMatcher<
Class, PropertyType, PropertyType (Class::*)() const &> > Class, PropertyType, PropertyType (Class::*)() const&>>
Property(PropertyType (Class::*property)() const &, Property(PropertyType (Class::*property)() const&,
const PropertyMatcher& matcher) { const PropertyMatcher& matcher) {
return MakePolymorphicMatcher( return MakePolymorphicMatcher(
internal::PropertyMatcher<Class, PropertyType, internal::PropertyMatcher<Class, PropertyType,
PropertyType (Class::*)() const&>( PropertyType (Class::*)() const&>(
property, MatcherCast<const PropertyType&>(matcher))); property, MatcherCast<const PropertyType&>(matcher)));
} }
// Three-argument form for reference-qualified member functions. // Three-argument form for reference-qualified member functions.
template <typename Class, typename PropertyType, typename PropertyMatcher> template <typename Class, typename PropertyType, typename PropertyMatcher>
inline PolymorphicMatcher<internal::PropertyMatcher< inline PolymorphicMatcher<internal::PropertyMatcher<
Class, PropertyType, PropertyType (Class::*)() const &> > Class, PropertyType, PropertyType (Class::*)() const&>>
Property(const std::string& property_name, Property(const std::string& property_name,
PropertyType (Class::*property)() const &, PropertyType (Class::*property)() const&,
const PropertyMatcher& matcher) { const PropertyMatcher& matcher) {
return MakePolymorphicMatcher( return MakePolymorphicMatcher(
internal::PropertyMatcher<Class, PropertyType, internal::PropertyMatcher<Class, PropertyType,
PropertyType (Class::*)() const&>( PropertyType (Class::*)() const&>(
property_name, property, MatcherCast<const PropertyType&>(matcher))); property_name, property, MatcherCast<const PropertyType&>(matcher)));
} }
// Creates a matcher that matches an object if and only if the result of // Creates a matcher that matches an object if and only if the result of
// applying a callable to x matches 'matcher'. For example, // applying a callable to x matches 'matcher'. For example,
// ResultOf(f, StartsWith("hi")) // ResultOf(f, StartsWith("hi"))
// matches a Foo object x if and only if f(x) starts with "hi". // matches a Foo object x if and only if f(x) starts with "hi".
// `callable` parameter can be a function, function pointer, or a functor. It is // `callable` parameter can be a function, function pointer, or a functor. It is
// required to keep no state affecting the results of the calls on it and make // required to keep no state affecting the results of the calls on it and make
// no assumptions about how many calls will be made. Any state it keeps must be // no assumptions about how many calls will be made. Any state it keeps must be
// protected from the concurrent access. // protected from the concurrent access.
template <typename Callable, typename InnerMatcher> template <typename Callable, typename InnerMatcher>
internal::ResultOfMatcher<Callable, InnerMatcher> ResultOf( internal::ResultOfMatcher<Callable, InnerMatcher> ResultOf(
Callable callable, InnerMatcher matcher) { Callable callable, InnerMatcher matcher) {
return internal::ResultOfMatcher<Callable, InnerMatcher>(std::move(callable),
std::move(matcher));
}
// Same as ResultOf() above, but also takes a description of the `callable`
// result to provide better error messages.
template <typename Callable, typename InnerMatcher>
internal::ResultOfMatcher<Callable, InnerMatcher> ResultOf(
const std::string& result_description, Callable callable,
InnerMatcher matcher) {
return internal::ResultOfMatcher<Callable, InnerMatcher>( return internal::ResultOfMatcher<Callable, InnerMatcher>(
std::move(callable), std::move(matcher)); result_description, std::move(callable), std::move(matcher));
} }
// String matchers. // String matchers.
// Matches a string equal to str. // Matches a string equal to str.
template <typename T = std::string> template <typename T = std::string>
PolymorphicMatcher<internal::StrEqualityMatcher<std::string> > StrEq( PolymorphicMatcher<internal::StrEqualityMatcher<std::string>> StrEq(
const internal::StringLike<T>& str) { const internal::StringLike<T>& str) {
return MakePolymorphicMatcher( return MakePolymorphicMatcher(
internal::StrEqualityMatcher<std::string>(std::string(str), true, true)); internal::StrEqualityMatcher<std::string>(std::string(str), true, true));
} }
// Matches a string not equal to str. // Matches a string not equal to str.
template <typename T = std::string> template <typename T = std::string>
PolymorphicMatcher<internal::StrEqualityMatcher<std::string> > StrNe( PolymorphicMatcher<internal::StrEqualityMatcher<std::string>> StrNe(
const internal::StringLike<T>& str) { const internal::StringLike<T>& str) {
return MakePolymorphicMatcher( return MakePolymorphicMatcher(
internal::StrEqualityMatcher<std::string>(std::string(str), false, true)); internal::StrEqualityMatcher<std::string>(std::string(str), false, true));
} }
// Matches a string equal to str, ignoring case. // Matches a string equal to str, ignoring case.
template <typename T = std::string> template <typename T = std::string>
PolymorphicMatcher<internal::StrEqualityMatcher<std::string> > StrCaseEq( PolymorphicMatcher<internal::StrEqualityMatcher<std::string>> StrCaseEq(
const internal::StringLike<T>& str) { const internal::StringLike<T>& str) {
return MakePolymorphicMatcher( return MakePolymorphicMatcher(
internal::StrEqualityMatcher<std::string>(std::string(str), true, false)); internal::StrEqualityMatcher<std::string>(std::string(str), true, false));
} }
// Matches a string not equal to str, ignoring case. // Matches a string not equal to str, ignoring case.
template <typename T = std::string> template <typename T = std::string>
PolymorphicMatcher<internal::StrEqualityMatcher<std::string> > StrCaseNe( PolymorphicMatcher<internal::StrEqualityMatcher<std::string>> StrCaseNe(
const internal::StringLike<T>& str) { const internal::StringLike<T>& str) {
return MakePolymorphicMatcher(internal::StrEqualityMatcher<std::string>( return MakePolymorphicMatcher(internal::StrEqualityMatcher<std::string>(
std::string(str), false, false)); std::string(str), false, false));
} }
// Creates a matcher that matches any string, std::string, or C string // Creates a matcher that matches any string, std::string, or C string
// that contains the given substring. // that contains the given substring.
template <typename T = std::string> template <typename T = std::string>
PolymorphicMatcher<internal::HasSubstrMatcher<std::string> > HasSubstr( PolymorphicMatcher<internal::HasSubstrMatcher<std::string>> HasSubstr(
const internal::StringLike<T>& substring) { const internal::StringLike<T>& substring) {
return MakePolymorphicMatcher( return MakePolymorphicMatcher(
internal::HasSubstrMatcher<std::string>(std::string(substring))); internal::HasSubstrMatcher<std::string>(std::string(substring)));
} }
// Matches a string that starts with 'prefix' (case-sensitive). // Matches a string that starts with 'prefix' (case-sensitive).
template <typename T = std::string> template <typename T = std::string>
PolymorphicMatcher<internal::StartsWithMatcher<std::string> > StartsWith( PolymorphicMatcher<internal::StartsWithMatcher<std::string>> StartsWith(
const internal::StringLike<T>& prefix) { const internal::StringLike<T>& prefix) {
return MakePolymorphicMatcher( return MakePolymorphicMatcher(
internal::StartsWithMatcher<std::string>(std::string(prefix))); internal::StartsWithMatcher<std::string>(std::string(prefix)));
} }
// Matches a string that ends with 'suffix' (case-sensitive). // Matches a string that ends with 'suffix' (case-sensitive).
template <typename T = std::string> template <typename T = std::string>
PolymorphicMatcher<internal::EndsWithMatcher<std::string> > EndsWith( PolymorphicMatcher<internal::EndsWithMatcher<std::string>> EndsWith(
const internal::StringLike<T>& suffix) { const internal::StringLike<T>& suffix) {
return MakePolymorphicMatcher( return MakePolymorphicMatcher(
internal::EndsWithMatcher<std::string>(std::string(suffix))); internal::EndsWithMatcher<std::string>(std::string(suffix)));
} }
#if GTEST_HAS_STD_WSTRING #if GTEST_HAS_STD_WSTRING
// Wide string matchers. // Wide string matchers.
// Matches a string equal to str. // Matches a string equal to str.
inline PolymorphicMatcher<internal::StrEqualityMatcher<std::wstring> > StrEq( inline PolymorphicMatcher<internal::StrEqualityMatcher<std::wstring>> StrEq(
const std::wstring& str) { const std::wstring& str) {
return MakePolymorphicMatcher( return MakePolymorphicMatcher(
internal::StrEqualityMatcher<std::wstring>(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<std::wstring> > StrNe( inline PolymorphicMatcher<internal::StrEqualityMatcher<std::wstring>> StrNe(
const std::wstring& str) { const std::wstring& str) {
return MakePolymorphicMatcher( return MakePolymorphicMatcher(
internal::StrEqualityMatcher<std::wstring>(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<std::wstring> > inline PolymorphicMatcher<internal::StrEqualityMatcher<std::wstring>> StrCaseEq(
StrCaseEq(const std::wstring& str) { const std::wstring& str) {
return MakePolymorphicMatcher( return MakePolymorphicMatcher(
internal::StrEqualityMatcher<std::wstring>(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<std::wstring> > inline PolymorphicMatcher<internal::StrEqualityMatcher<std::wstring>> StrCaseNe(
StrCaseNe(const std::wstring& str) { const std::wstring& str) {
return MakePolymorphicMatcher( return MakePolymorphicMatcher(
internal::StrEqualityMatcher<std::wstring>(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<std::wstring> > HasSubstr( inline PolymorphicMatcher<internal::HasSubstrMatcher<std::wstring>> HasSubstr(
const std::wstring& substring) { const std::wstring& substring) {
return MakePolymorphicMatcher( return MakePolymorphicMatcher(
internal::HasSubstrMatcher<std::wstring>(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<std::wstring> > inline PolymorphicMatcher<internal::StartsWithMatcher<std::wstring>> StartsWith(
StartsWith(const std::wstring& prefix) { const std::wstring& prefix) {
return MakePolymorphicMatcher( return MakePolymorphicMatcher(
internal::StartsWithMatcher<std::wstring>(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<std::wstring> > EndsWith( inline PolymorphicMatcher<internal::EndsWithMatcher<std::wstring>> EndsWith(
const std::wstring& suffix) { const std::wstring& suffix) {
return MakePolymorphicMatcher( return MakePolymorphicMatcher(
internal::EndsWithMatcher<std::wstring>(suffix)); internal::EndsWithMatcher<std::wstring>(suffix));
} }
#endif // GTEST_HAS_STD_WSTRING #endif // GTEST_HAS_STD_WSTRING
// Creates a polymorphic matcher that matches a 2-tuple where the // Creates a polymorphic matcher that matches a 2-tuple where the
// first field == the second field. // first field == the second field.
inline internal::Eq2Matcher Eq() { return internal::Eq2Matcher(); } inline internal::Eq2Matcher Eq() { return internal::Eq2Matcher(); }
skipping to change at line 4486 skipping to change at line 4663
// match. // match.
template <typename InnerMatcher> template <typename InnerMatcher>
inline internal::NotMatcher<InnerMatcher> Not(InnerMatcher m) { inline internal::NotMatcher<InnerMatcher> Not(InnerMatcher m) {
return internal::NotMatcher<InnerMatcher>(m); return internal::NotMatcher<InnerMatcher>(m);
} }
// Returns a matcher that matches anything that satisfies the given // Returns a matcher that matches anything that satisfies the given
// predicate. The predicate can be any unary function or functor // predicate. The predicate can be any unary function or functor
// whose return type can be implicitly converted to bool. // whose return type can be implicitly converted to bool.
template <typename Predicate> template <typename Predicate>
inline PolymorphicMatcher<internal::TrulyMatcher<Predicate> > inline PolymorphicMatcher<internal::TrulyMatcher<Predicate>> Truly(
Truly(Predicate pred) { Predicate pred) {
return MakePolymorphicMatcher(internal::TrulyMatcher<Predicate>(pred)); return MakePolymorphicMatcher(internal::TrulyMatcher<Predicate>(pred));
} }
// Returns a matcher that matches the container size. The container must // Returns a matcher that matches the container size. The container must
// support both size() and size_type which all STL-like containers provide. // support both size() and size_type which all STL-like containers provide.
// Note that the parameter 'size' can be a value of type size_type as well as // Note that the parameter 'size' can be a value of type size_type as well as
// matcher. For instance: // matcher. For instance:
// EXPECT_THAT(container, SizeIs(2)); // Checks container has 2 elements. // EXPECT_THAT(container, SizeIs(2)); // Checks container has 2 elements.
// EXPECT_THAT(container, SizeIs(Le(2)); // Checks container has at most 2. // EXPECT_THAT(container, SizeIs(Le(2)); // Checks container has at most 2.
template <typename SizeMatcher> template <typename SizeMatcher>
inline internal::SizeIsMatcher<SizeMatcher> inline internal::SizeIsMatcher<SizeMatcher> SizeIs(
SizeIs(const SizeMatcher& size_matcher) { const SizeMatcher& size_matcher) {
return internal::SizeIsMatcher<SizeMatcher>(size_matcher); return internal::SizeIsMatcher<SizeMatcher>(size_matcher);
} }
// Returns a matcher that matches the distance between the container's begin() // Returns a matcher that matches the distance between the container's begin()
// iterator and its end() iterator, i.e. the size of the container. This matcher // iterator and its end() iterator, i.e. the size of the container. This matcher
// can be used instead of SizeIs with containers such as std::forward_list which // can be used instead of SizeIs with containers such as std::forward_list which
// do not implement size(). The container must provide const_iterator (with // do not implement size(). The container must provide const_iterator (with
// valid iterator_traits), begin() and end(). // valid iterator_traits), begin() and end().
template <typename DistanceMatcher> template <typename DistanceMatcher>
inline internal::BeginEndDistanceIsMatcher<DistanceMatcher> inline internal::BeginEndDistanceIsMatcher<DistanceMatcher> BeginEndDistanceIs(
BeginEndDistanceIs(const DistanceMatcher& distance_matcher) { const DistanceMatcher& distance_matcher) {
return internal::BeginEndDistanceIsMatcher<DistanceMatcher>(distance_matcher); return internal::BeginEndDistanceIsMatcher<DistanceMatcher>(distance_matcher);
} }
// Returns a matcher that matches an equal container. // Returns a matcher that matches an equal container.
// This matcher behaves like Eq(), but in the event of mismatch lists the // This matcher behaves like Eq(), but in the event of mismatch lists the
// values that are included in one container but not the other. (Duplicate // values that are included in one container but not the other. (Duplicate
// values and order differences are not explained.) // values and order differences are not explained.)
template <typename Container> template <typename Container>
inline PolymorphicMatcher<internal::ContainerEqMatcher< inline PolymorphicMatcher<
typename std::remove_const<Container>::type>> internal::ContainerEqMatcher<typename std::remove_const<Container>::type>>
ContainerEq(const Container& rhs) { ContainerEq(const Container& rhs) {
return MakePolymorphicMatcher(internal::ContainerEqMatcher<Container>(rhs)); return MakePolymorphicMatcher(internal::ContainerEqMatcher<Container>(rhs));
} }
// Returns a matcher that matches a container that, when sorted using // Returns a matcher that matches a container that, when sorted using
// the given comparator, matches container_matcher. // the given comparator, matches container_matcher.
template <typename Comparator, typename ContainerMatcher> template <typename Comparator, typename ContainerMatcher>
inline internal::WhenSortedByMatcher<Comparator, ContainerMatcher> inline internal::WhenSortedByMatcher<Comparator, ContainerMatcher> WhenSortedBy(
WhenSortedBy(const Comparator& comparator, const Comparator& comparator, const ContainerMatcher& container_matcher) {
const ContainerMatcher& container_matcher) {
return internal::WhenSortedByMatcher<Comparator, ContainerMatcher>( return internal::WhenSortedByMatcher<Comparator, ContainerMatcher>(
comparator, container_matcher); comparator, container_matcher);
} }
// Returns a matcher that matches a container that, when sorted using // Returns a matcher that matches a container that, when sorted using
// the < operator, matches container_matcher. // the < operator, matches container_matcher.
template <typename ContainerMatcher> template <typename ContainerMatcher>
inline internal::WhenSortedByMatcher<internal::LessComparator, ContainerMatcher> inline internal::WhenSortedByMatcher<internal::LessComparator, ContainerMatcher>
WhenSorted(const ContainerMatcher& container_matcher) { WhenSorted(const ContainerMatcher& container_matcher) {
return return internal::WhenSortedByMatcher<internal::LessComparator,
internal::WhenSortedByMatcher<internal::LessComparator, ContainerMatcher>( ContainerMatcher>(
internal::LessComparator(), container_matcher); internal::LessComparator(), container_matcher);
} }
// Matches an STL-style container or a native array that contains the // Matches an STL-style container or a native array that contains the
// same number of elements as in rhs, where its i-th element and rhs's // same number of elements as in rhs, where its i-th element and rhs's
// i-th element (as a pair) satisfy the given pair matcher, for all i. // i-th element (as a pair) satisfy the given pair matcher, for all i.
// TupleMatcher must be able to be safely cast to Matcher<std::tuple<const // TupleMatcher must be able to be safely cast to Matcher<std::tuple<const
// T1&, const T2&> >, where T1 and T2 are the types of elements in the // T1&, const T2&> >, where T1 and T2 are the types of elements in the
// LHS container and the RHS container respectively. // LHS container and the RHS container respectively.
template <typename TupleMatcher, typename Container> template <typename TupleMatcher, typename Container>
inline internal::PointwiseMatcher<TupleMatcher, inline internal::PointwiseMatcher<TupleMatcher,
typename std::remove_const<Container>::type> typename std::remove_const<Container>::type>
Pointwise(const TupleMatcher& tuple_matcher, const Container& rhs) { Pointwise(const TupleMatcher& tuple_matcher, const Container& rhs) {
return internal::PointwiseMatcher<TupleMatcher, Container>(tuple_matcher, return internal::PointwiseMatcher<TupleMatcher, Container>(tuple_matcher,
rhs); rhs);
} }
// Supports the Pointwise(m, {a, b, c}) syntax. // Supports the Pointwise(m, {a, b, c}) syntax.
template <typename TupleMatcher, typename T> template <typename TupleMatcher, typename T>
inline internal::PointwiseMatcher<TupleMatcher, std::vector<T> > Pointwise( inline internal::PointwiseMatcher<TupleMatcher, std::vector<T>> Pointwise(
const TupleMatcher& tuple_matcher, std::initializer_list<T> rhs) { const TupleMatcher& tuple_matcher, std::initializer_list<T> rhs) {
return Pointwise(tuple_matcher, std::vector<T>(rhs)); return Pointwise(tuple_matcher, std::vector<T>(rhs));
} }
// UnorderedPointwise(pair_matcher, rhs) matches an STL-style // UnorderedPointwise(pair_matcher, rhs) matches an STL-style
// container or a native array that contains the same number of // container or a native array that contains the same number of
// elements as in rhs, where in some permutation of the container, its // elements as in rhs, where in some permutation of the container, its
// i-th element and rhs's i-th element (as a pair) satisfy the given // i-th element and rhs's i-th element (as a pair) satisfy the given
// pair matcher, for all i. Tuple2Matcher must be able to be safely // pair matcher, for all i. Tuple2Matcher must be able to be safely
// cast to Matcher<std::tuple<const T1&, const T2&> >, where T1 and T2 are // cast to Matcher<std::tuple<const T1&, const T2&> >, where T1 and T2 are
skipping to change at line 4594 skipping to change at line 4770
const RhsContainer& rhs_container) { const RhsContainer& rhs_container) {
// RhsView allows the same code to handle RhsContainer being a // RhsView allows the same code to handle RhsContainer being a
// STL-style container and it being a native C-style array. // STL-style container and it being a native C-style array.
typedef typename internal::StlContainerView<RhsContainer> RhsView; typedef typename internal::StlContainerView<RhsContainer> RhsView;
typedef typename RhsView::type RhsStlContainer; typedef typename RhsView::type RhsStlContainer;
typedef typename RhsStlContainer::value_type Second; typedef typename RhsStlContainer::value_type Second;
const RhsStlContainer& rhs_stl_container = const RhsStlContainer& rhs_stl_container =
RhsView::ConstReference(rhs_container); RhsView::ConstReference(rhs_container);
// Create a matcher for each element in rhs_container. // Create a matcher for each element in rhs_container.
::std::vector<internal::BoundSecondMatcher<Tuple2Matcher, Second> > matchers; ::std::vector<internal::BoundSecondMatcher<Tuple2Matcher, Second>> matchers;
for (typename RhsStlContainer::const_iterator it = rhs_stl_container.begin(); for (auto it = rhs_stl_container.begin(); it != rhs_stl_container.end();
it != rhs_stl_container.end(); ++it) { ++it) {
matchers.push_back( matchers.push_back(internal::MatcherBindSecond(tuple2_matcher, *it));
internal::MatcherBindSecond(tuple2_matcher, *it));
} }
// Delegate the work to UnorderedElementsAreArray(). // Delegate the work to UnorderedElementsAreArray().
return UnorderedElementsAreArray(matchers); return UnorderedElementsAreArray(matchers);
} }
// Supports the UnorderedPointwise(m, {a, b, c}) syntax. // Supports the UnorderedPointwise(m, {a, b, c}) syntax.
template <typename Tuple2Matcher, typename T> template <typename Tuple2Matcher, typename T>
inline internal::UnorderedElementsAreArrayMatcher< inline internal::UnorderedElementsAreArrayMatcher<
typename internal::BoundSecondMatcher<Tuple2Matcher, T> > typename internal::BoundSecondMatcher<Tuple2Matcher, T>>
UnorderedPointwise(const Tuple2Matcher& tuple2_matcher, UnorderedPointwise(const Tuple2Matcher& tuple2_matcher,
std::initializer_list<T> rhs) { std::initializer_list<T> rhs) {
return UnorderedPointwise(tuple2_matcher, std::vector<T>(rhs)); return UnorderedPointwise(tuple2_matcher, std::vector<T>(rhs));
} }
// Matches an STL-style container or a native array that contains at // Matches an STL-style container or a native array that contains at
// least one element matching the given value or matcher. // least one element matching the given value or matcher.
// //
// Examples: // Examples:
// ::std::set<int> page_ids; // ::std::set<int> page_ids;
// page_ids.insert(3); // page_ids.insert(3);
// page_ids.insert(1); // page_ids.insert(1);
// EXPECT_THAT(page_ids, Contains(1)); // EXPECT_THAT(page_ids, Contains(1));
// EXPECT_THAT(page_ids, Contains(Gt(2))); // EXPECT_THAT(page_ids, Contains(Gt(2)));
// EXPECT_THAT(page_ids, Not(Contains(4))); // EXPECT_THAT(page_ids, Not(Contains(4))); // See below for Times(0)
// //
// ::std::map<int, size_t> page_lengths; // ::std::map<int, size_t> page_lengths;
// page_lengths[1] = 100; // page_lengths[1] = 100;
// EXPECT_THAT(page_lengths, // EXPECT_THAT(page_lengths,
// Contains(::std::pair<const int, size_t>(1, 100))); // Contains(::std::pair<const int, size_t>(1, 100)));
// //
// const char* user_ids[] = { "joe", "mike", "tom" }; // const char* user_ids[] = { "joe", "mike", "tom" };
// EXPECT_THAT(user_ids, Contains(Eq(::std::string("tom")))); // EXPECT_THAT(user_ids, Contains(Eq(::std::string("tom"))));
//
// The matcher supports a modifier `Times` that allows to check for arbitrary
// occurrences including testing for absence with Times(0).
//
// Examples:
// ::std::vector<int> ids;
// ids.insert(1);
// ids.insert(1);
// ids.insert(3);
// EXPECT_THAT(ids, Contains(1).Times(2)); // 1 occurs 2 times
// EXPECT_THAT(ids, Contains(2).Times(0)); // 2 is not present
// EXPECT_THAT(ids, Contains(3).Times(Ge(1))); // 3 occurs at least once
template <typename M> template <typename M>
inline internal::ContainsMatcher<M> Contains(M matcher) { inline internal::ContainsMatcher<M> Contains(M matcher) {
return internal::ContainsMatcher<M>(matcher); return internal::ContainsMatcher<M>(matcher);
} }
// IsSupersetOf(iterator_first, iterator_last) // IsSupersetOf(iterator_first, iterator_last)
// IsSupersetOf(pointer, count) // IsSupersetOf(pointer, count)
// IsSupersetOf(array) // IsSupersetOf(array)
// IsSupersetOf(container) // IsSupersetOf(container)
// IsSupersetOf({e1, e2, ..., en}) // IsSupersetOf({e1, e2, ..., en})
skipping to change at line 4758 skipping to change at line 4946
template <typename T> template <typename T>
inline internal::UnorderedElementsAreArrayMatcher<T> IsSubsetOf( inline internal::UnorderedElementsAreArrayMatcher<T> IsSubsetOf(
::std::initializer_list<T> xs) { ::std::initializer_list<T> xs) {
return IsSubsetOf(xs.begin(), xs.end()); return IsSubsetOf(xs.begin(), xs.end());
} }
// Matches an STL-style container or a native array that contains only // Matches an STL-style container or a native array that contains only
// elements matching the given value or matcher. // elements matching the given value or matcher.
// //
// Each(m) is semantically equivalent to Not(Contains(Not(m))). Only // Each(m) is semantically equivalent to `Not(Contains(Not(m)))`. Only
// the messages are different. // the messages are different.
// //
// Examples: // Examples:
// ::std::set<int> page_ids; // ::std::set<int> page_ids;
// // Each(m) matches an empty container, regardless of what m is. // // Each(m) matches an empty container, regardless of what m is.
// EXPECT_THAT(page_ids, Each(Eq(1))); // EXPECT_THAT(page_ids, Each(Eq(1)));
// EXPECT_THAT(page_ids, Each(Eq(77))); // EXPECT_THAT(page_ids, Each(Eq(77)));
// //
// page_ids.insert(3); // page_ids.insert(3);
// EXPECT_THAT(page_ids, Each(Gt(0))); // EXPECT_THAT(page_ids, Each(Gt(0)));
skipping to change at line 4801 skipping to change at line 4989
inline internal::KeyMatcher<M> Key(M inner_matcher) { inline internal::KeyMatcher<M> Key(M inner_matcher) {
return internal::KeyMatcher<M>(inner_matcher); return internal::KeyMatcher<M>(inner_matcher);
} }
// Pair(first_matcher, second_matcher) matches a std::pair whose 'first' field // Pair(first_matcher, second_matcher) matches a std::pair whose 'first' field
// matches first_matcher and whose 'second' field matches second_matcher. For // matches first_matcher and whose 'second' field matches second_matcher. For
// example, EXPECT_THAT(map_type, ElementsAre(Pair(Ge(5), "foo"))) can be used // example, EXPECT_THAT(map_type, ElementsAre(Pair(Ge(5), "foo"))) can be used
// to match a std::map<int, string> that contains exactly one element whose key // to match a std::map<int, string> that contains exactly one element whose key
// is >= 5 and whose value equals "foo". // is >= 5 and whose value equals "foo".
template <typename FirstMatcher, typename SecondMatcher> template <typename FirstMatcher, typename SecondMatcher>
inline internal::PairMatcher<FirstMatcher, SecondMatcher> inline internal::PairMatcher<FirstMatcher, SecondMatcher> Pair(
Pair(FirstMatcher first_matcher, SecondMatcher second_matcher) { FirstMatcher first_matcher, SecondMatcher second_matcher) {
return internal::PairMatcher<FirstMatcher, SecondMatcher>( return internal::PairMatcher<FirstMatcher, SecondMatcher>(first_matcher,
first_matcher, second_matcher); second_matcher);
} }
namespace no_adl { namespace no_adl {
// Conditional() creates a matcher that conditionally uses either the first or
// second matcher provided. For example, we could create an `equal if, and only
// if' matcher using the Conditional wrapper as follows:
//
// EXPECT_THAT(result, Conditional(condition, Eq(expected), Ne(expected)));
template <typename MatcherTrue, typename MatcherFalse>
internal::ConditionalMatcher<MatcherTrue, MatcherFalse> Conditional(
bool condition, MatcherTrue matcher_true, MatcherFalse matcher_false) {
return internal::ConditionalMatcher<MatcherTrue, MatcherFalse>(
condition, std::move(matcher_true), std::move(matcher_false));
}
// FieldsAre(matchers...) matches piecewise the fields of compatible structs. // FieldsAre(matchers...) matches piecewise the fields of compatible structs.
// These include those that support `get<I>(obj)`, and when structured bindings // These include those that support `get<I>(obj)`, and when structured bindings
// are enabled any class that supports them. // are enabled any class that supports them.
// In particular, `std::tuple`, `std::pair`, `std::array` and aggregate types. // In particular, `std::tuple`, `std::pair`, `std::array` and aggregate types.
template <typename... M> template <typename... M>
internal::FieldsAreMatcher<typename std::decay<M>::type...> FieldsAre( internal::FieldsAreMatcher<typename std::decay<M>::type...> FieldsAre(
M&&... matchers) { M&&... matchers) {
return internal::FieldsAreMatcher<typename std::decay<M>::type...>( return internal::FieldsAreMatcher<typename std::decay<M>::type...>(
std::forward<M>(matchers)...); std::forward<M>(matchers)...);
} }
skipping to change at line 4834 skipping to change at line 5034
return internal::PointerMatcher<InnerMatcher>(inner_matcher); return internal::PointerMatcher<InnerMatcher>(inner_matcher);
} }
// Creates a matcher that matches an object that has an address that matches // Creates a matcher that matches an object that has an address that matches
// inner_matcher. // inner_matcher.
template <typename InnerMatcher> template <typename InnerMatcher>
inline internal::AddressMatcher<InnerMatcher> Address( inline internal::AddressMatcher<InnerMatcher> Address(
const InnerMatcher& inner_matcher) { const InnerMatcher& inner_matcher) {
return internal::AddressMatcher<InnerMatcher>(inner_matcher); return internal::AddressMatcher<InnerMatcher>(inner_matcher);
} }
// Matches a base64 escaped string, when the unescaped string matches the
// internal matcher.
template <typename MatcherType>
internal::WhenBase64UnescapedMatcher WhenBase64Unescaped(
const MatcherType& internal_matcher) {
return internal::WhenBase64UnescapedMatcher(internal_matcher);
}
} // namespace no_adl } // namespace no_adl
// Returns a predicate that is satisfied by anything that matches the // Returns a predicate that is satisfied by anything that matches the
// given matcher. // given matcher.
template <typename M> template <typename M>
inline internal::MatcherAsPredicate<M> Matches(M matcher) { inline internal::MatcherAsPredicate<M> Matches(M matcher) {
return internal::MatcherAsPredicate<M>(matcher); return internal::MatcherAsPredicate<M>(matcher);
} }
// Returns true if and only if the value matches the matcher. // Returns true if and only if the value matches the matcher.
template <typename T, typename M> template <typename T, typename M>
inline bool Value(const T& value, M matcher) { inline bool Value(const T& value, M matcher) {
return testing::Matches(matcher)(value); return testing::Matches(matcher)(value);
} }
// Matches the value against the given matcher and explains the match // Matches the value against the given matcher and explains the match
// result to listener. // result to listener.
template <typename T, typename M> template <typename T, typename M>
inline bool ExplainMatchResult( inline bool ExplainMatchResult(M matcher, const T& value,
M matcher, const T& value, MatchResultListener* listener) { MatchResultListener* listener) {
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 // Returns a string representation of the given matcher. Useful for description
// strings of matchers defined using MATCHER_P* macros that accept matchers as // strings of matchers defined using MATCHER_P* macros that accept matchers as
// their arguments. For example: // their arguments. For example:
// //
// MATCHER_P(XAndYThat, matcher, // MATCHER_P(XAndYThat, matcher,
// "X that " + DescribeMatcher<int>(matcher, negation) + // "X that " + DescribeMatcher<int>(matcher, negation) +
// " and Y that " + DescribeMatcher<double>(matcher, negation)) { // (negation ? " or" : " and") + " Y that " +
// DescribeMatcher<double>(matcher, negation)) {
// return ExplainMatchResult(matcher, arg.x(), result_listener) && // return ExplainMatchResult(matcher, arg.x(), result_listener) &&
// ExplainMatchResult(matcher, arg.y(), result_listener); // ExplainMatchResult(matcher, arg.y(), result_listener);
// } // }
template <typename T, typename M> template <typename T, typename M>
std::string DescribeMatcher(const M& matcher, bool negation = false) { std::string DescribeMatcher(const M& matcher, bool negation = false) {
::std::stringstream ss; ::std::stringstream ss;
Matcher<T> monomorphic_matcher = SafeMatcherCast<T>(matcher); Matcher<T> monomorphic_matcher = SafeMatcherCast<T>(matcher);
if (negation) { if (negation) {
monomorphic_matcher.DescribeNegationTo(&ss); monomorphic_matcher.DescribeNegationTo(&ss);
} else { } else {
skipping to change at line 5012 skipping to change at line 5221
} }
// AllArgs(m) is a synonym of m. This is useful in // AllArgs(m) is a synonym of m. This is useful in
// //
// EXPECT_CALL(foo, Bar(_, _)).With(AllArgs(Eq())); // EXPECT_CALL(foo, Bar(_, _)).With(AllArgs(Eq()));
// //
// which is easier to read than // which is easier to read than
// //
// EXPECT_CALL(foo, Bar(_, _)).With(Eq()); // EXPECT_CALL(foo, Bar(_, _)).With(Eq());
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. // Returns a matcher that matches the value of an optional<> type variable.
// The matcher implementation only uses '!arg' and requires that the optional<> // 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' // type has a 'value_type' member type and that '*arg' is of type 'value_type'
// and is printable using 'PrintToString'. It is compatible with // and is printable using 'PrintToString'. It is compatible with
// std::optional/std::experimental::optional. // std::optional/std::experimental::optional.
// Note that to compare an optional type variable against nullopt you should // Note that to compare an optional type variable against nullopt you should
// use Eq(nullopt) and not Eq(Optional(nullopt)). The latter implies that the // use Eq(nullopt) and not Eq(Optional(nullopt)). The latter implies that the
// optional value contains an optional itself. // optional value contains an optional itself.
template <typename ValueMatcher> template <typename ValueMatcher>
inline internal::OptionalMatcher<ValueMatcher> Optional( inline internal::OptionalMatcher<ValueMatcher> Optional(
const ValueMatcher& value_matcher) { const ValueMatcher& value_matcher) {
return internal::OptionalMatcher<ValueMatcher>(value_matcher); return internal::OptionalMatcher<ValueMatcher>(value_matcher);
} }
// Returns a matcher that matches the value of a absl::any type variable. // Returns a matcher that matches the value of a absl::any type variable.
template <typename T> template <typename T>
PolymorphicMatcher<internal::any_cast_matcher::AnyCastMatcher<T> > AnyWith( PolymorphicMatcher<internal::any_cast_matcher::AnyCastMatcher<T>> AnyWith(
const Matcher<const T&>& matcher) { const Matcher<const T&>& matcher) {
return MakePolymorphicMatcher( return MakePolymorphicMatcher(
internal::any_cast_matcher::AnyCastMatcher<T>(matcher)); 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.
// It is compatible with std::variant. // It is compatible with std::variant.
template <typename T> template <typename T>
PolymorphicMatcher<internal::variant_matcher::VariantMatcher<T> > VariantWith( PolymorphicMatcher<internal::variant_matcher::VariantMatcher<T>> VariantWith(
const Matcher<const T&>& matcher) { const Matcher<const T&>& matcher) {
return MakePolymorphicMatcher( return MakePolymorphicMatcher(
internal::variant_matcher::VariantMatcher<T>(matcher)); internal::variant_matcher::VariantMatcher<T>(matcher));
} }
#if GTEST_HAS_EXCEPTIONS #if GTEST_HAS_EXCEPTIONS
// Anything inside the `internal` namespace is internal to the implementation // Anything inside the `internal` namespace is internal to the implementation
// and must not be used in user code! // and must not be used in user code!
namespace internal { namespace internal {
skipping to change at line 5070 skipping to change at line 5281
matcher_.DescribeTo(os); matcher_.DescribeTo(os);
} }
void DescribeNegationTo(std::ostream* os) const { void DescribeNegationTo(std::ostream* os) const {
*os << "contains .what() that does not "; *os << "contains .what() that does not ";
matcher_.DescribeTo(os); matcher_.DescribeTo(os);
} }
template <typename Err> template <typename Err>
bool MatchAndExplain(const Err& err, MatchResultListener* listener) const { bool MatchAndExplain(const Err& err, MatchResultListener* listener) const {
*listener << "which contains .what() that "; *listener << "which contains .what() (of value = " << err.what()
<< ") that ";
return matcher_.MatchAndExplain(err.what(), listener); return matcher_.MatchAndExplain(err.what(), listener);
} }
private: private:
const Matcher<std::string> matcher_; const Matcher<std::string> matcher_;
}; };
inline PolymorphicMatcher<WithWhatMatcherImpl> WithWhat( inline PolymorphicMatcher<WithWhatMatcherImpl> WithWhat(
Matcher<std::string> m) { Matcher<std::string> m) {
return MakePolymorphicMatcher(WithWhatMatcherImpl(std::move(m))); return MakePolymorphicMatcher(WithWhatMatcherImpl(std::move(m)));
skipping to change at line 5220 skipping to change at line 5432
return Throws<Err>(internal::WithWhat( return Throws<Err>(internal::WithWhat(
MatcherCast<std::string>(std::forward<MessageMatcher>(message_matcher)))); MatcherCast<std::string>(std::forward<MessageMatcher>(message_matcher))));
} }
#endif // GTEST_HAS_EXCEPTIONS #endif // GTEST_HAS_EXCEPTIONS
// These macros allow using matchers to check values in Google Test // These macros allow using matchers to check values in Google Test
// tests. ASSERT_THAT(value, matcher) and EXPECT_THAT(value, matcher) // tests. ASSERT_THAT(value, matcher) and EXPECT_THAT(value, matcher)
// succeed if and only if the value matches the matcher. If the assertion // succeed if and only if the value matches the matcher. If the assertion
// fails, the value and the description of the matcher will be printed. // fails, the value and the description of the matcher will be printed.
#define ASSERT_THAT(value, matcher) ASSERT_PRED_FORMAT1(\ #define ASSERT_THAT(value, matcher) \
::testing::internal::MakePredicateFormatterFromMatcher(matcher), value) ASSERT_PRED_FORMAT1( \
#define EXPECT_THAT(value, matcher) EXPECT_PRED_FORMAT1(\ ::testing::internal::MakePredicateFormatterFromMatcher(matcher), value)
::testing::internal::MakePredicateFormatterFromMatcher(matcher), value) #define EXPECT_THAT(value, matcher) \
EXPECT_PRED_FORMAT1( \
::testing::internal::MakePredicateFormatterFromMatcher(matcher), value)
// MATCHER* macroses itself are listed below. // MATCHER* macros itself are listed below.
#define MATCHER(name, description) \ #define MATCHER(name, description) \
class name##Matcher \ class name##Matcher \
: public ::testing::internal::MatcherBaseImpl<name##Matcher> { \ : public ::testing::internal::MatcherBaseImpl<name##Matcher> { \
public: \ public: \
template <typename arg_type> \ template <typename arg_type> \
class gmock_Impl : public ::testing::MatcherInterface<const arg_type&> { \ class gmock_Impl : public ::testing::MatcherInterface<const arg_type&> { \
public: \ public: \
gmock_Impl() {} \ gmock_Impl() {} \
bool MatchAndExplain( \ bool MatchAndExplain( \
const arg_type& arg, \ const arg_type& arg, \
::testing::MatchResultListener* result_listener) const override; \ ::testing::MatchResultListener* result_listener) const override; \
void DescribeTo(::std::ostream* gmock_os) const override { \ void DescribeTo(::std::ostream* gmock_os) const override { \
*gmock_os << FormatDescription(false); \ *gmock_os << FormatDescription(false); \
} \ } \
void DescribeNegationTo(::std::ostream* gmock_os) const override { \ void DescribeNegationTo(::std::ostream* gmock_os) const override { \
*gmock_os << FormatDescription(true); \ *gmock_os << FormatDescription(true); \
} \ } \
\ \
private: \ private: \
::std::string FormatDescription(bool negation) const { \ ::std::string FormatDescription(bool negation) const { \
/* NOLINTNEXTLINE readability-redundant-string-init */ \
::std::string gmock_description = (description); \ ::std::string gmock_description = (description); \
if (!gmock_description.empty()) { \ if (!gmock_description.empty()) { \
return gmock_description; \ return gmock_description; \
} \ } \
return ::testing::internal::FormatMatcherDescription(negation, #name, \ return ::testing::internal::FormatMatcherDescription(negation, #name, \
{}); \ {}, {}); \
} \ } \
}; \ }; \
}; \ }; \
GTEST_ATTRIBUTE_UNUSED_ inline name##Matcher name() { return {}; } \ GTEST_ATTRIBUTE_UNUSED_ inline name##Matcher name() { return {}; } \
template <typename arg_type> \ template <typename arg_type> \
bool name##Matcher::gmock_Impl<arg_type>::MatchAndExplain( \ bool name##Matcher::gmock_Impl<arg_type>::MatchAndExplain( \
const arg_type& arg, \ const arg_type& arg, \
::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_) \ ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_) \
const const
#define MATCHER_P(name, p0, description) \ #define MATCHER_P(name, p0, description) \
GMOCK_INTERNAL_MATCHER(name, name##MatcherP, description, (p0)) GMOCK_INTERNAL_MATCHER(name, name##MatcherP, description, (#p0), (p0))
#define MATCHER_P2(name, p0, p1, description) \ #define MATCHER_P2(name, p0, p1, description) \
GMOCK_INTERNAL_MATCHER(name, name##MatcherP2, description, (p0, p1)) GMOCK_INTERNAL_MATCHER(name, name##MatcherP2, description, (#p0, #p1), \
#define MATCHER_P3(name, p0, p1, p2, description) \ (p0, p1))
GMOCK_INTERNAL_MATCHER(name, name##MatcherP3, description, (p0, p1, p2)) #define MATCHER_P3(name, p0, p1, p2, description) \
#define MATCHER_P4(name, p0, p1, p2, p3, description) \ GMOCK_INTERNAL_MATCHER(name, name##MatcherP3, description, (#p0, #p1, #p2), \
GMOCK_INTERNAL_MATCHER(name, name##MatcherP4, description, (p0, p1, p2, p3)) (p0, p1, p2))
#define MATCHER_P4(name, p0, p1, p2, p3, description) \
GMOCK_INTERNAL_MATCHER(name, name##MatcherP4, description, \
(#p0, #p1, #p2, #p3), (p0, p1, p2, p3))
#define MATCHER_P5(name, p0, p1, p2, p3, p4, description) \ #define MATCHER_P5(name, p0, p1, p2, p3, p4, description) \
GMOCK_INTERNAL_MATCHER(name, name##MatcherP5, description, \ GMOCK_INTERNAL_MATCHER(name, name##MatcherP5, description, \
(p0, p1, p2, p3, p4)) (#p0, #p1, #p2, #p3, #p4), (p0, p1, p2, p3, p4))
#define MATCHER_P6(name, p0, p1, p2, p3, p4, p5, description) \ #define MATCHER_P6(name, p0, p1, p2, p3, p4, p5, description) \
GMOCK_INTERNAL_MATCHER(name, name##MatcherP6, description, \ GMOCK_INTERNAL_MATCHER(name, name##MatcherP6, description, \
(#p0, #p1, #p2, #p3, #p4, #p5), \
(p0, p1, p2, p3, p4, p5)) (p0, p1, p2, p3, p4, p5))
#define MATCHER_P7(name, p0, p1, p2, p3, p4, p5, p6, description) \ #define MATCHER_P7(name, p0, p1, p2, p3, p4, p5, p6, description) \
GMOCK_INTERNAL_MATCHER(name, name##MatcherP7, description, \ GMOCK_INTERNAL_MATCHER(name, name##MatcherP7, description, \
(#p0, #p1, #p2, #p3, #p4, #p5, #p6), \
(p0, p1, p2, p3, p4, p5, p6)) (p0, p1, p2, p3, p4, p5, p6))
#define MATCHER_P8(name, p0, p1, p2, p3, p4, p5, p6, p7, description) \ #define MATCHER_P8(name, p0, p1, p2, p3, p4, p5, p6, p7, description) \
GMOCK_INTERNAL_MATCHER(name, name##MatcherP8, description, \ GMOCK_INTERNAL_MATCHER(name, name##MatcherP8, description, \
(#p0, #p1, #p2, #p3, #p4, #p5, #p6, #p7), \
(p0, p1, p2, p3, p4, p5, p6, p7)) (p0, p1, p2, p3, p4, p5, p6, p7))
#define MATCHER_P9(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, description) \ #define MATCHER_P9(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, description) \
GMOCK_INTERNAL_MATCHER(name, name##MatcherP9, description, \ GMOCK_INTERNAL_MATCHER(name, name##MatcherP9, description, \
(#p0, #p1, #p2, #p3, #p4, #p5, #p6, #p7, #p8), \
(p0, p1, p2, p3, p4, p5, p6, p7, p8)) (p0, p1, p2, p3, p4, p5, p6, p7, p8))
#define MATCHER_P10(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, description) \ #define MATCHER_P10(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, description) \
GMOCK_INTERNAL_MATCHER(name, name##MatcherP10, description, \ GMOCK_INTERNAL_MATCHER(name, name##MatcherP10, description, \
(#p0, #p1, #p2, #p3, #p4, #p5, #p6, #p7, #p8, #p9), \
(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9)) (p0, p1, p2, p3, p4, p5, p6, p7, p8, p9))
#define GMOCK_INTERNAL_MATCHER(name, full_name, description, args) \ #define GMOCK_INTERNAL_MATCHER(name, full_name, description, arg_names, args) \
template <GMOCK_INTERNAL_MATCHER_TEMPLATE_PARAMS(args)> \ template <GMOCK_INTERNAL_MATCHER_TEMPLATE_PARAMS(args)> \
class full_name : public ::testing::internal::MatcherBaseImpl< \ class full_name : public ::testing::internal::MatcherBaseImpl< \
full_name<GMOCK_INTERNAL_MATCHER_TYPE_PARAMS(args)>> { \ full_name<GMOCK_INTERNAL_MATCHER_TYPE_PARAMS(args)>> { \
public: \ public: \
using full_name::MatcherBaseImpl::MatcherBaseImpl; \ using full_name::MatcherBaseImpl::MatcherBaseImpl; \
template <typename arg_type> \ template <typename arg_type> \
class gmock_Impl : public ::testing::MatcherInterface<const arg_type&> { \ class gmock_Impl : public ::testing::MatcherInterface<const arg_type&> { \
public: \ public: \
explicit gmock_Impl(GMOCK_INTERNAL_MATCHER_FUNCTION_ARGS(args)) \ explicit gmock_Impl(GMOCK_INTERNAL_MATCHER_FUNCTION_ARGS(args)) \
: GMOCK_INTERNAL_MATCHER_FORWARD_ARGS(args) {} \ : GMOCK_INTERNAL_MATCHER_FORWARD_ARGS(args) {} \
skipping to change at line 5318 skipping to change at line 5541
} \ } \
GMOCK_INTERNAL_MATCHER_MEMBERS(args) \ GMOCK_INTERNAL_MATCHER_MEMBERS(args) \
\ \
private: \ private: \
::std::string FormatDescription(bool negation) const { \ ::std::string FormatDescription(bool negation) const { \
::std::string gmock_description = (description); \ ::std::string gmock_description = (description); \
if (!gmock_description.empty()) { \ if (!gmock_description.empty()) { \
return gmock_description; \ return gmock_description; \
} \ } \
return ::testing::internal::FormatMatcherDescription( \ return ::testing::internal::FormatMatcherDescription( \
negation, #name, \ negation, #name, {GMOCK_PP_REMOVE_PARENS(arg_names)}, \
::testing::internal::UniversalTersePrintTupleFieldsToStrings( \ ::testing::internal::UniversalTersePrintTupleFieldsToStrings( \
::std::tuple<GMOCK_INTERNAL_MATCHER_TYPE_PARAMS(args)>( \ ::std::tuple<GMOCK_INTERNAL_MATCHER_TYPE_PARAMS(args)>( \
GMOCK_INTERNAL_MATCHER_MEMBERS_USAGE(args)))); \ GMOCK_INTERNAL_MATCHER_MEMBERS_USAGE(args)))); \
} \ } \
}; \ }; \
}; \ }; \
template <GMOCK_INTERNAL_MATCHER_TEMPLATE_PARAMS(args)> \ template <GMOCK_INTERNAL_MATCHER_TEMPLATE_PARAMS(args)> \
inline full_name<GMOCK_INTERNAL_MATCHER_TYPE_PARAMS(args)> name( \ inline full_name<GMOCK_INTERNAL_MATCHER_TYPE_PARAMS(args)> name( \
GMOCK_INTERNAL_MATCHER_FUNCTION_ARGS(args)) { \ GMOCK_INTERNAL_MATCHER_FUNCTION_ARGS(args)) { \
return full_name<GMOCK_INTERNAL_MATCHER_TYPE_PARAMS(args)>( \ return full_name<GMOCK_INTERNAL_MATCHER_TYPE_PARAMS(args)>( \
 End of changes. 165 change blocks. 
244 lines changed or deleted 467 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)