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 |