diff options
Diffstat (limited to 'include/gmock')
-rw-r--r-- | include/gmock/gmock-matchers.h | 210 |
1 files changed, 194 insertions, 16 deletions
diff --git a/include/gmock/gmock-matchers.h b/include/gmock/gmock-matchers.h index d4977273..0512ef44 100644 --- a/include/gmock/gmock-matchers.h +++ b/include/gmock/gmock-matchers.h @@ -38,6 +38,7 @@ #ifndef GMOCK_INCLUDE_GMOCK_GMOCK_MATCHERS_H_ #define GMOCK_INCLUDE_GMOCK_GMOCK_MATCHERS_H_ +#include <math.h> #include <algorithm> #include <limits> #include <ostream> // NOLINT @@ -1406,6 +1407,91 @@ class BothOfMatcherImpl : public MatcherInterface<T> { GTEST_DISALLOW_ASSIGN_(BothOfMatcherImpl); }; +#if GTEST_LANG_CXX11 +// MatcherList provides mechanisms for storing a variable number of matchers in +// a list structure (ListType) and creating a combining matcher from such a +// list. +// The template is defined recursively using the following template paramters: +// * kSize is the length of the MatcherList. +// * Head is the type of the first matcher of the list. +// * Tail denotes the types of the remaining matchers of the list. +template <int kSize, typename Head, typename... Tail> +struct MatcherList { + typedef MatcherList<kSize - 1, Tail...> MatcherListTail; + typedef pair<Head, typename MatcherListTail::ListType> ListType; + + // BuildList stores variadic type values in a nested pair structure. + // Example: + // MatcherList<3, int, string, float>::BuildList(5, "foo", 2.0) will return + // the corresponding result of type pair<int, pair<string, float>>. + static ListType BuildList(const Head& matcher, const Tail&... tail) { + return ListType(matcher, MatcherListTail::BuildList(tail...)); + } + + // CreateMatcher<T> creates a Matcher<T> from a given list of matchers (built + // by BuildList()). CombiningMatcher<T> is used to combine the matchers of the + // list. CombiningMatcher<T> must implement MatcherInterface<T> and have a + // constructor taking two Matcher<T>s as input. + template <typename T, template <typename /* T */> class CombiningMatcher> + static Matcher<T> CreateMatcher(const ListType& matchers) { + return Matcher<T>(new CombiningMatcher<T>( + SafeMatcherCast<T>(matchers.first), + MatcherListTail::template CreateMatcher<T, CombiningMatcher>( + matchers.second))); + } +}; + +// The following defines the base case for the recursive definition of +// MatcherList. +template <typename Matcher1, typename Matcher2> +struct MatcherList<2, Matcher1, Matcher2> { + typedef pair<Matcher1, Matcher2> ListType; + + static ListType BuildList(const Matcher1& matcher1, + const Matcher2& matcher2) { + return pair<Matcher1, Matcher2>(matcher1, matcher2); + } + + template <typename T, template <typename /* T */> class CombiningMatcher> + static Matcher<T> CreateMatcher(const ListType& matchers) { + return Matcher<T>(new CombiningMatcher<T>( + SafeMatcherCast<T>(matchers.first), + SafeMatcherCast<T>(matchers.second))); + } +}; + +// VariadicMatcher is used for the variadic implementation of +// AllOf(m_1, m_2, ...) and AnyOf(m_1, m_2, ...). +// CombiningMatcher<T> is used to recursively combine the provided matchers +// (of type Args...). +template <template <typename T> class CombiningMatcher, typename... Args> +class VariadicMatcher { + public: + VariadicMatcher(const Args&... matchers) // NOLINT + : matchers_(MatcherListType::BuildList(matchers...)) {} + + // This template type conversion operator allows an + // VariadicMatcher<Matcher1, Matcher2...> object to match any type that + // all of the provided matchers (Matcher1, Matcher2, ...) can match. + template <typename T> + operator Matcher<T>() const { + return MatcherListType::template CreateMatcher<T, CombiningMatcher>( + matchers_); + } + + private: + typedef MatcherList<sizeof...(Args), Args...> MatcherListType; + + const typename MatcherListType::ListType matchers_; + + GTEST_DISALLOW_ASSIGN_(VariadicMatcher); +}; + +template <typename... Args> +using AllOfMatcher = VariadicMatcher<BothOfMatcherImpl, Args...>; + +#endif // GTEST_LANG_CXX11 + // Used for implementing the AllOf(m_1, ..., m_n) matcher, which // matches a value that matches all of the matchers m_1, ..., and m_n. template <typename Matcher1, typename Matcher2> @@ -1493,6 +1579,13 @@ class EitherOfMatcherImpl : public MatcherInterface<T> { GTEST_DISALLOW_ASSIGN_(EitherOfMatcherImpl); }; +#if GTEST_LANG_CXX11 +// AnyOfMatcher is used for the variadic implementation of AnyOf(m_1, m_2, ...). +template <typename... Args> +using AnyOfMatcher = VariadicMatcher<EitherOfMatcherImpl, Args...>; + +#endif // GTEST_LANG_CXX11 + // Used for implementing the AnyOf(m_1, ..., m_n) matcher, which // matches a value that matches at least one of the matchers m_1, ..., // and m_n. @@ -1646,37 +1739,60 @@ MakePredicateFormatterFromMatcher(const M& matcher) { return PredicateFormatterFromMatcher<M>(matcher); } -// Implements the polymorphic floating point equality matcher, which -// matches two float values using ULP-based approximation. The -// template is meant to be instantiated with FloatType being either -// float or double. +// Implements the polymorphic floating point equality matcher, which matches +// two float values using ULP-based approximation or, optionally, a +// user-specified epsilon. The template is meant to be instantiated with +// FloatType being either float or double. template <typename FloatType> class FloatingEqMatcher { public: // Constructor for FloatingEqMatcher. // The matcher's input will be compared with rhs. The matcher treats two // NANs as equal if nan_eq_nan is true. Otherwise, under IEEE standards, - // equality comparisons between NANs will always return false. + // equality comparisons between NANs will always return false. We specify a + // negative max_abs_error_ term to indicate that ULP-based approximation will + // be used for comparison. FloatingEqMatcher(FloatType rhs, bool nan_eq_nan) : - rhs_(rhs), nan_eq_nan_(nan_eq_nan) {} + rhs_(rhs), nan_eq_nan_(nan_eq_nan), max_abs_error_(-1) { + } + + // Constructor that supports a user-specified max_abs_error that will be used + // for comparison instead of ULP-based approximation. The max absolute + // should be non-negative. + FloatingEqMatcher(FloatType rhs, bool nan_eq_nan, FloatType max_abs_error) : + rhs_(rhs), nan_eq_nan_(nan_eq_nan), max_abs_error_(max_abs_error) { + GTEST_CHECK_(max_abs_error >= 0) + << ", where max_abs_error is" << max_abs_error; + } // Implements floating point equality matcher as a Matcher<T>. template <typename T> class Impl : public MatcherInterface<T> { public: - Impl(FloatType rhs, bool nan_eq_nan) : - rhs_(rhs), nan_eq_nan_(nan_eq_nan) {} + Impl(FloatType rhs, bool nan_eq_nan, FloatType max_abs_error) : + rhs_(rhs), nan_eq_nan_(nan_eq_nan), max_abs_error_(max_abs_error) {} virtual bool MatchAndExplain(T value, MatchResultListener* /* listener */) const { const FloatingPoint<FloatType> lhs(value), rhs(rhs_); // Compares NaNs first, if nan_eq_nan_ is true. - if (nan_eq_nan_ && lhs.is_nan()) { - return rhs.is_nan(); + if (lhs.is_nan() || rhs.is_nan()) { + if (lhs.is_nan() && rhs.is_nan()) { + return nan_eq_nan_; + } + // One is nan; the other is not nan. + return false; + } + if (HasMaxAbsError()) { + // We perform an equality check so that inf will match inf, regardless + // of error bounds. If the result of value - rhs_ would result in + // overflow or if either value is inf, the default result is infinity, + // which should only match if max_abs_error_ is also infinity. + return value == rhs_ || fabs(value - rhs_) <= max_abs_error_; + } else { + return lhs.AlmostEquals(rhs); } - - return lhs.AlmostEquals(rhs); } virtual void DescribeTo(::std::ostream* os) const { @@ -1693,6 +1809,9 @@ class FloatingEqMatcher { } } else { *os << "is approximately " << rhs_; + if (HasMaxAbsError()) { + *os << " (absolute error <= " << max_abs_error_ << ")"; + } } os->precision(old_precision); } @@ -1709,14 +1828,23 @@ class FloatingEqMatcher { } } else { *os << "isn't approximately " << rhs_; + if (HasMaxAbsError()) { + *os << " (absolute error > " << max_abs_error_ << ")"; + } } // Restore original precision. os->precision(old_precision); } private: + bool HasMaxAbsError() const { + return max_abs_error_ >= 0; + } + const FloatType rhs_; const bool nan_eq_nan_; + // max_abs_error will be used for value comparison when >= 0. + const FloatType max_abs_error_; GTEST_DISALLOW_ASSIGN_(Impl); }; @@ -1728,20 +1856,23 @@ class FloatingEqMatcher { // by non-const reference, we may see them in code not conforming to // the style. Therefore Google Mock needs to support them.) operator Matcher<FloatType>() const { - return MakeMatcher(new Impl<FloatType>(rhs_, nan_eq_nan_)); + return MakeMatcher(new Impl<FloatType>(rhs_, nan_eq_nan_, max_abs_error_)); } operator Matcher<const FloatType&>() const { - return MakeMatcher(new Impl<const FloatType&>(rhs_, nan_eq_nan_)); + return MakeMatcher( + new Impl<const FloatType&>(rhs_, nan_eq_nan_, max_abs_error_)); } operator Matcher<FloatType&>() const { - return MakeMatcher(new Impl<FloatType&>(rhs_, nan_eq_nan_)); + return MakeMatcher(new Impl<FloatType&>(rhs_, nan_eq_nan_, max_abs_error_)); } private: const FloatType rhs_; const bool nan_eq_nan_; + // max_abs_error will be used for value comparison when >= 0. + const FloatType max_abs_error_; GTEST_DISALLOW_ASSIGN_(FloatingEqMatcher); }; @@ -2931,18 +3062,50 @@ inline internal::FloatingEqMatcher<double> NanSensitiveDoubleEq(double rhs) { return internal::FloatingEqMatcher<double>(rhs, true); } +// Creates a matcher that matches any double argument approximately equal to +// rhs, up to the specified max absolute error bound, where two NANs are +// considered unequal. The max absolute error bound must be non-negative. +inline internal::FloatingEqMatcher<double> DoubleNear( + double rhs, double max_abs_error) { + return internal::FloatingEqMatcher<double>(rhs, false, max_abs_error); +} + +// 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 is NaN. The max absolute error bound must be non-negative. +inline internal::FloatingEqMatcher<double> NanSensitiveDoubleNear( + double rhs, double max_abs_error) { + return internal::FloatingEqMatcher<double>(rhs, true, max_abs_error); +} + // Creates a matcher that matches any float argument approximately // equal to rhs, where two NANs are considered unequal. inline internal::FloatingEqMatcher<float> FloatEq(float rhs) { return internal::FloatingEqMatcher<float>(rhs, false); } -// Creates a matcher that matches any double argument approximately +// Creates a matcher that matches any float argument approximately // equal to rhs, including NaN values when rhs is NaN. inline internal::FloatingEqMatcher<float> NanSensitiveFloatEq(float rhs) { return internal::FloatingEqMatcher<float>(rhs, true); } +// Creates a matcher that matches any float argument approximately equal to +// rhs, up to the specified max absolute error bound, where two NANs are +// considered unequal. The max absolute error bound must be non-negative. +inline internal::FloatingEqMatcher<float> FloatNear( + float rhs, float max_abs_error) { + return internal::FloatingEqMatcher<float>(rhs, false, max_abs_error); +} + +// 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 is NaN. The max absolute error bound must be non-negative. +inline internal::FloatingEqMatcher<float> NanSensitiveFloatNear( + float rhs, float max_abs_error) { + return internal::FloatingEqMatcher<float>(rhs, true, max_abs_error); +} + // Creates a matcher that matches a pointer (raw or smart) that points // to a value that matches inner_matcher. template <typename InnerMatcher> @@ -3341,6 +3504,21 @@ inline bool ExplainMatchResult( return SafeMatcherCast<const T&>(matcher).MatchAndExplain(value, listener); } +#if GTEST_LANG_CXX11 +// Define variadic matcher versions. They are overloaded in +// gmock-generated-matchers.h for the cases supported by pre C++11 compilers. +template <typename... Args> +inline internal::AllOfMatcher<Args...> AllOf(const Args&... matchers) { + return internal::AllOfMatcher<Args...>(matchers...); +} + +template <typename... Args> +inline internal::AnyOfMatcher<Args...> AnyOf(const Args&... matchers) { + return internal::AnyOfMatcher<Args...>(matchers...); +} + +#endif // GTEST_LANG_CXX11 + // AllArgs(m) is a synonym of m. This is useful in // // EXPECT_CALL(foo, Bar(_, _)).With(AllArgs(Eq())); |