diff options
author | zhanyong.wan <zhanyong.wan@8415998a-534a-0410-bf83-d39667b30386> | 2013-06-18 18:49:51 +0000 |
---|---|---|
committer | zhanyong.wan <zhanyong.wan@8415998a-534a-0410-bf83-d39667b30386> | 2013-06-18 18:49:51 +0000 |
commit | 616180e6847dd3cc6517a59ff2d24e9fd5c8052c (patch) | |
tree | f1470b135e8587cd71b5942944be9ae9d6e740a8 | |
parent | f4274520da256a3e8dd4fe2aa2e714f44ad89d18 (diff) | |
download | googletest-616180e6847dd3cc6517a59ff2d24e9fd5c8052c.tar.gz googletest-616180e6847dd3cc6517a59ff2d24e9fd5c8052c.tar.bz2 googletest-616180e6847dd3cc6517a59ff2d24e9fd5c8052c.zip |
New floating-point matchers: DoubleNear() and friends;
AllOf() and AnyOf() can accept any number of arguments now in C++11 mode.
-rw-r--r-- | CHANGES | 7 | ||||
-rw-r--r-- | include/gmock/gmock-matchers.h | 210 | ||||
-rw-r--r-- | test/gmock-generated-actions_test.cc | 2 | ||||
-rw-r--r-- | test/gmock-matchers_test.cc | 254 | ||||
-rw-r--r-- | test/gmock-more-actions_test.cc | 2 |
5 files changed, 455 insertions, 20 deletions
@@ -1,9 +1,12 @@ Changes for 1.7.0: * All new improvements in Google Test 1.7.0. -* New feature: matchers WhenSorted(), WhenSortedBy(), IsEmpty(), and - SizeIs(). +* New feature: matchers DoubleNear(), FloatNear(), + NanSensitiveDoubleNear(), NanSensitiveFloatNear(), WhenSorted(), + WhenSortedBy(), IsEmpty(), and SizeIs(). * Improvement: Google Mock can now be built as a DLL. +* Improvement: when compiled by a C++11 compiler, matchers AllOf() + and AnyOf() can accept an arbitrary number of matchers. * Improvement: when exceptions are enabled, a mock method with no default action now throws instead crashing the test. * Improvement: function return types used in MOCK_METHOD*() macros can 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())); diff --git a/test/gmock-generated-actions_test.cc b/test/gmock-generated-actions_test.cc index 23f8c8b0..31812716 100644 --- a/test/gmock-generated-actions_test.cc +++ b/test/gmock-generated-actions_test.cc @@ -376,7 +376,7 @@ class SubstractAction : public ActionInterface<int(int, int)> { // NOLINT TEST(WithArgsTest, NonInvokeAction) { Action<int(const string&, int, int)> a = // NOLINT WithArgs<2, 1>(MakeAction(new SubstractAction)); - EXPECT_EQ(8, a.Perform(make_tuple(CharPtr("hi"), 2, 10))); + EXPECT_EQ(8, a.Perform(make_tuple(string("hi"), 2, 10))); } // Tests using WithArgs to pass all original arguments in the original order. diff --git a/test/gmock-matchers_test.cc b/test/gmock-matchers_test.cc index 3ec2989e..29d9ed04 100644 --- a/test/gmock-matchers_test.cc +++ b/test/gmock-matchers_test.cc @@ -41,6 +41,7 @@ #include <functional> #include <iostream> #include <iterator> +#include <limits> #include <list> #include <map> #include <set> @@ -83,11 +84,13 @@ using testing::AnyOf; using testing::ByRef; using testing::ContainsRegex; using testing::DoubleEq; +using testing::DoubleNear; using testing::EndsWith; using testing::Eq; using testing::ExplainMatchResult; using testing::Field; using testing::FloatEq; +using testing::FloatNear; using testing::Ge; using testing::Gt; using testing::HasSubstr; @@ -105,7 +108,9 @@ using testing::MatcherInterface; using testing::Matches; using testing::MatchesRegex; using testing::NanSensitiveDoubleEq; +using testing::NanSensitiveDoubleNear; using testing::NanSensitiveFloatEq; +using testing::NanSensitiveFloatNear; using testing::Ne; using testing::Not; using testing::NotNull; @@ -2021,6 +2026,28 @@ TEST(AllOfTest, MatchesWhenAllMatch) { Ne(9), Ne(10))); } +#if GTEST_LANG_CXX11 +// Tests the variadic version of the AllOfMatcher. +TEST(AllOfTest, VariadicMatchesWhenAllMatch) { + // Make sure AllOf is defined in the right namespace and does not depend on + // ADL. + ::testing::AllOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11); + Matcher<int> m = AllOf(Ne(1), Ne(2), Ne(3), Ne(4), Ne(5), Ne(6), Ne(7), Ne(8), + Ne(9), Ne(10), Ne(11)); + EXPECT_THAT(Describe(m), EndsWith("and (isn't equal to 11))))))))))")); + AllOfMatches(11, m); + AllOfMatches(50, AllOf(Ne(1), Ne(2), Ne(3), Ne(4), Ne(5), Ne(6), Ne(7), Ne(8), + Ne(9), Ne(10), Ne(11), Ne(12), Ne(13), Ne(14), Ne(15), + Ne(16), Ne(17), Ne(18), Ne(19), Ne(20), Ne(21), Ne(22), + Ne(23), Ne(24), Ne(25), Ne(26), Ne(27), Ne(28), Ne(29), + Ne(30), Ne(31), Ne(32), Ne(33), Ne(34), Ne(35), Ne(36), + Ne(37), Ne(38), Ne(39), Ne(40), Ne(41), Ne(42), Ne(43), + Ne(44), Ne(45), Ne(46), Ne(47), Ne(48), Ne(49), + Ne(50))); +} + +#endif // GTEST_LANG_CXX11 + // Tests that AllOf(m1, ..., mn) describes itself properly. TEST(AllOfTest, CanDescribeSelf) { Matcher<int> m; @@ -2194,6 +2221,24 @@ TEST(AnyOfTest, MatchesWhenAnyMatches) { AnyOfMatches(10, AnyOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)); } +#if GTEST_LANG_CXX11 +// Tests the variadic version of the AnyOfMatcher. +TEST(AnyOfTest, VariadicMatchesWhenAnyMatches) { + // Also make sure AnyOf is defined in the right namespace and does not depend + // on ADL. + Matcher<int> m = ::testing::AnyOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11); + + EXPECT_THAT(Describe(m), EndsWith("or (is equal to 11))))))))))")); + AnyOfMatches(11, m); + AnyOfMatches(50, AnyOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50)); +} + +#endif // GTEST_LANG_CXX11 + // Tests that AnyOf(m1, ..., mn) describes itself properly. TEST(AnyOfTest, CanDescribeSelf) { Matcher<int> m; @@ -2723,6 +2768,95 @@ RawType FloatingPointTest<RawType>::nan1_; template <typename RawType> RawType FloatingPointTest<RawType>::nan2_; +// Tests floating-point matchers with fixed epsilons. +template <typename RawType> +class FloatingPointNearTest : public FloatingPointTest<RawType> { + protected: + typedef FloatingPointTest<RawType> ParentType; + + // A battery of tests for FloatingEqMatcher::Matches with a fixed epsilon. + // matcher_maker is a pointer to a function which creates a FloatingEqMatcher. + void TestNearMatches( + testing::internal::FloatingEqMatcher<RawType> + (*matcher_maker)(RawType, RawType)) { + Matcher<RawType> m1 = matcher_maker(0.0, 0.0); + EXPECT_TRUE(m1.Matches(0.0)); + EXPECT_TRUE(m1.Matches(-0.0)); + EXPECT_FALSE(m1.Matches(ParentType::close_to_positive_zero_)); + EXPECT_FALSE(m1.Matches(ParentType::close_to_negative_zero_)); + EXPECT_FALSE(m1.Matches(1.0)); + + Matcher<RawType> m2 = matcher_maker(0.0, 1.0); + EXPECT_TRUE(m2.Matches(0.0)); + EXPECT_TRUE(m2.Matches(-0.0)); + EXPECT_TRUE(m2.Matches(1.0)); + EXPECT_TRUE(m2.Matches(-1.0)); + EXPECT_FALSE(m2.Matches(ParentType::close_to_one_)); + EXPECT_FALSE(m2.Matches(-ParentType::close_to_one_)); + + // Check that inf matches inf, regardless of the of the specified max + // absolute error. + Matcher<RawType> m3 = matcher_maker(ParentType::infinity_, 0.0); + EXPECT_TRUE(m3.Matches(ParentType::infinity_)); + EXPECT_FALSE(m3.Matches(ParentType::close_to_infinity_)); + EXPECT_FALSE(m3.Matches(-ParentType::infinity_)); + + Matcher<RawType> m4 = matcher_maker(-ParentType::infinity_, 0.0); + EXPECT_TRUE(m4.Matches(-ParentType::infinity_)); + EXPECT_FALSE(m4.Matches(-ParentType::close_to_infinity_)); + EXPECT_FALSE(m4.Matches(ParentType::infinity_)); + + // Test various overflow scenarios. + Matcher<RawType> m5 = matcher_maker( + std::numeric_limits<RawType>::max(), + std::numeric_limits<RawType>::max()); + EXPECT_TRUE(m5.Matches(std::numeric_limits<RawType>::max())); + EXPECT_FALSE(m5.Matches(-std::numeric_limits<RawType>::max())); + + Matcher<RawType> m6 = matcher_maker( + -std::numeric_limits<RawType>::max(), + std::numeric_limits<RawType>::max()); + EXPECT_FALSE(m6.Matches(std::numeric_limits<RawType>::max())); + EXPECT_TRUE(m6.Matches(-std::numeric_limits<RawType>::max())); + + Matcher<RawType> m7 = matcher_maker(std::numeric_limits<RawType>::max(), 0); + EXPECT_TRUE(m7.Matches(std::numeric_limits<RawType>::max())); + EXPECT_FALSE(m7.Matches(-std::numeric_limits<RawType>::max())); + + Matcher<RawType> m8 = matcher_maker( + -std::numeric_limits<RawType>::max(), 0); + EXPECT_FALSE(m8.Matches(std::numeric_limits<RawType>::max())); + EXPECT_TRUE(m8.Matches(-std::numeric_limits<RawType>::max())); + + // The difference between max() and -max() normally overflows to infinity, + // but it should still match if the max_abs_error is also infinity. + Matcher<RawType> m9 = matcher_maker( + std::numeric_limits<RawType>::max(), ParentType::infinity_); + EXPECT_TRUE(m8.Matches(-std::numeric_limits<RawType>::max())); + + // matcher_maker can produce a Matcher<const RawType&>, which is needed in + // some cases. + Matcher<const RawType&> m10 = matcher_maker(0.0, 1.0); + EXPECT_TRUE(m10.Matches(-0.0)); + EXPECT_TRUE(m10.Matches(ParentType::close_to_positive_zero_)); + EXPECT_FALSE(m10.Matches(ParentType::close_to_one_)); + + // matcher_maker can produce a Matcher<RawType&>, which is needed in some + // cases. + Matcher<RawType&> m11 = matcher_maker(0.0, 1.0); + RawType x = 0.0; + EXPECT_TRUE(m11.Matches(x)); + x = 1.0f; + EXPECT_TRUE(m11.Matches(x)); + x = -1.0f; + EXPECT_TRUE(m11.Matches(x)); + x = 1.1f; + EXPECT_FALSE(m11.Matches(x)); + x = -1.1f; + EXPECT_FALSE(m11.Matches(x)); + } +}; + // Instantiate FloatingPointTest for testing floats. typedef FloatingPointTest<float> FloatTest; @@ -2778,6 +2912,66 @@ TEST_F(FloatTest, NanSensitiveFloatEqCanDescribeSelf) { EXPECT_EQ("isn't NaN", DescribeNegation(m3)); } +// Instantiate FloatingPointTest for testing floats with a user-specified +// max absolute error. +typedef FloatingPointNearTest<float> FloatNearTest; + +TEST_F(FloatNearTest, FloatNearMatches) { + TestNearMatches(&FloatNear); +} + +TEST_F(FloatNearTest, NanSensitiveFloatNearApproximatelyMatchesFloats) { + TestNearMatches(&NanSensitiveFloatNear); +} + +TEST_F(FloatNearTest, FloatNearCanDescribeSelf) { + Matcher<float> m1 = FloatNear(2.0f, 0.5f); + EXPECT_EQ("is approximately 2 (absolute error <= 0.5)", Describe(m1)); + EXPECT_EQ( + "isn't approximately 2 (absolute error > 0.5)", DescribeNegation(m1)); + + Matcher<float> m2 = FloatNear(0.5f, 0.5f); + EXPECT_EQ("is approximately 0.5 (absolute error <= 0.5)", Describe(m2)); + EXPECT_EQ( + "isn't approximately 0.5 (absolute error > 0.5)", DescribeNegation(m2)); + + Matcher<float> m3 = FloatNear(nan1_, 0.0); + EXPECT_EQ("never matches", Describe(m3)); + EXPECT_EQ("is anything", DescribeNegation(m3)); +} + +TEST_F(FloatNearTest, NanSensitiveFloatNearCanDescribeSelf) { + Matcher<float> m1 = NanSensitiveFloatNear(2.0f, 0.5f); + EXPECT_EQ("is approximately 2 (absolute error <= 0.5)", Describe(m1)); + EXPECT_EQ( + "isn't approximately 2 (absolute error > 0.5)", DescribeNegation(m1)); + + Matcher<float> m2 = NanSensitiveFloatNear(0.5f, 0.5f); + EXPECT_EQ("is approximately 0.5 (absolute error <= 0.5)", Describe(m2)); + EXPECT_EQ( + "isn't approximately 0.5 (absolute error > 0.5)", DescribeNegation(m2)); + + Matcher<float> m3 = NanSensitiveFloatNear(nan1_, 0.1f); + EXPECT_EQ("is NaN", Describe(m3)); + EXPECT_EQ("isn't NaN", DescribeNegation(m3)); +} + +TEST_F(FloatNearTest, FloatNearCannotMatchNaN) { + // FloatNear never matches NaN. + Matcher<float> m = FloatNear(ParentType::nan1_, 0.1f); + EXPECT_FALSE(m.Matches(nan1_)); + EXPECT_FALSE(m.Matches(nan2_)); + EXPECT_FALSE(m.Matches(1.0)); +} + +TEST_F(FloatNearTest, NanSensitiveFloatNearCanMatchNaN) { + // NanSensitiveFloatNear will match NaN. + Matcher<float> m = NanSensitiveFloatNear(nan1_, 0.1f); + EXPECT_TRUE(m.Matches(nan1_)); + EXPECT_TRUE(m.Matches(nan2_)); + EXPECT_FALSE(m.Matches(1.0)); +} + // Instantiate FloatingPointTest for testing doubles. typedef FloatingPointTest<double> DoubleTest; @@ -2833,6 +3027,66 @@ TEST_F(DoubleTest, NanSensitiveDoubleEqCanDescribeSelf) { EXPECT_EQ("isn't NaN", DescribeNegation(m3)); } +// Instantiate FloatingPointTest for testing floats with a user-specified +// max absolute error. +typedef FloatingPointNearTest<double> DoubleNearTest; + +TEST_F(DoubleNearTest, DoubleNearMatches) { + TestNearMatches(&DoubleNear); +} + +TEST_F(DoubleNearTest, NanSensitiveDoubleNearApproximatelyMatchesDoubles) { + TestNearMatches(&NanSensitiveDoubleNear); +} + +TEST_F(DoubleNearTest, DoubleNearCanDescribeSelf) { + Matcher<double> m1 = DoubleNear(2.0, 0.5); + EXPECT_EQ("is approximately 2 (absolute error <= 0.5)", Describe(m1)); + EXPECT_EQ( + "isn't approximately 2 (absolute error > 0.5)", DescribeNegation(m1)); + + Matcher<double> m2 = DoubleNear(0.5, 0.5); + EXPECT_EQ("is approximately 0.5 (absolute error <= 0.5)", Describe(m2)); + EXPECT_EQ( + "isn't approximately 0.5 (absolute error > 0.5)", DescribeNegation(m2)); + + Matcher<double> m3 = DoubleNear(nan1_, 0.0); + EXPECT_EQ("never matches", Describe(m3)); + EXPECT_EQ("is anything", DescribeNegation(m3)); +} + +TEST_F(DoubleNearTest, NanSensitiveDoubleNearCanDescribeSelf) { + Matcher<double> m1 = NanSensitiveDoubleNear(2.0, 0.5); + EXPECT_EQ("is approximately 2 (absolute error <= 0.5)", Describe(m1)); + EXPECT_EQ( + "isn't approximately 2 (absolute error > 0.5)", DescribeNegation(m1)); + + Matcher<double> m2 = NanSensitiveDoubleNear(0.5, 0.5); + EXPECT_EQ("is approximately 0.5 (absolute error <= 0.5)", Describe(m2)); + EXPECT_EQ( + "isn't approximately 0.5 (absolute error > 0.5)", DescribeNegation(m2)); + + Matcher<double> m3 = NanSensitiveDoubleNear(nan1_, 0.1); + EXPECT_EQ("is NaN", Describe(m3)); + EXPECT_EQ("isn't NaN", DescribeNegation(m3)); +} + +TEST_F(DoubleNearTest, DoubleNearCannotMatchNaN) { + // DoubleNear never matches NaN. + Matcher<double> m = DoubleNear(ParentType::nan1_, 0.1); + EXPECT_FALSE(m.Matches(nan1_)); + EXPECT_FALSE(m.Matches(nan2_)); + EXPECT_FALSE(m.Matches(1.0)); +} + +TEST_F(DoubleNearTest, NanSensitiveDoubleNearCanMatchNaN) { + // NanSensitiveDoubleNear will match NaN. + Matcher<double> m = NanSensitiveDoubleNear(nan1_, 0.1); + EXPECT_TRUE(m.Matches(nan1_)); + EXPECT_TRUE(m.Matches(nan2_)); + EXPECT_FALSE(m.Matches(1.0)); +} + TEST(PointeeTest, RawPointer) { const Matcher<int*> m = Pointee(Ge(0)); diff --git a/test/gmock-more-actions_test.cc b/test/gmock-more-actions_test.cc index 9fa9e2ec..9dde5ebb 100644 --- a/test/gmock-more-actions_test.cc +++ b/test/gmock-more-actions_test.cc @@ -327,7 +327,7 @@ TEST(InvokeTest, FunctionThatTakes10Arguments) { TEST(InvokeTest, FunctionWithUnusedParameters) { Action<int(int, int, double, const string&)> a1 = Invoke(SumOfFirst2); - EXPECT_EQ(12, a1.Perform(make_tuple(10, 2, 5.6, CharPtr("hi")))); + EXPECT_EQ(12, a1.Perform(make_tuple(10, 2, 5.6, string("hi")))); Action<int(int, int, bool, int*)> a2 = Invoke(SumOfFirst2); |