diff options
author | kosak <kosak@google.com> | 2015-01-08 02:38:14 (GMT) |
---|---|---|
committer | kosak <kosak@google.com> | 2015-01-08 02:38:14 (GMT) |
commit | 6b817803104b30d5951c652a1427492db116a490 (patch) | |
tree | eed0ecd43dfc84fafd59b95cd34584f6e0b24def | |
parent | 61adbcc5c6b8e0385e3e2bf4262771d20a375002 (diff) | |
download | googletest-6b817803104b30d5951c652a1427492db116a490.zip googletest-6b817803104b30d5951c652a1427492db116a490.tar.gz googletest-6b817803104b30d5951c652a1427492db116a490.tar.bz2 |
Makes DoubleNear() print the diff between the actual and the expected value when the match fails.
Also fix bogus MSVC warning about "alignment of a member was sensitive to packing".
Also bring in gtest 701.
-rw-r--r-- | include/gmock/gmock-matchers.h | 90 | ||||
-rw-r--r-- | include/gmock/gmock-more-actions.h | 7 | ||||
-rw-r--r-- | test/gmock-matchers_test.cc | 13 |
3 files changed, 73 insertions, 37 deletions
diff --git a/include/gmock/gmock-matchers.h b/include/gmock/gmock-matchers.h index 75432bd..ca09756 100644 --- a/include/gmock/gmock-matchers.h +++ b/include/gmock/gmock-matchers.h @@ -1879,20 +1879,23 @@ template <typename FloatType> class FloatingEqMatcher { public: // Constructor for FloatingEqMatcher. - // The matcher's input will be compared with rhs. 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, // 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), max_abs_error_(-1) { + FloatingEqMatcher(FloatType expected, bool nan_eq_nan) : + 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 // 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) { + FloatingEqMatcher(FloatType expected, bool nan_eq_nan, + FloatType max_abs_error) + : expected_(expected), + 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; } @@ -1901,16 +1904,18 @@ class FloatingEqMatcher { template <typename T> class Impl : public MatcherInterface<T> { public: - 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) {} + Impl(FloatType expected, bool nan_eq_nan, FloatType max_abs_error) + : expected_(expected), + 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_); + MatchResultListener* listener) const { + const FloatingPoint<FloatType> actual(value), expected(expected_); // Compares NaNs first, if nan_eq_nan_ is true. - if (lhs.is_nan() || rhs.is_nan()) { - if (lhs.is_nan() && rhs.is_nan()) { + if (actual.is_nan() || expected.is_nan()) { + if (actual.is_nan() && expected.is_nan()) { return nan_eq_nan_; } // One is nan; the other is not nan. @@ -1918,12 +1923,24 @@ class FloatingEqMatcher { } 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 + // of error bounds. If the result of value - expected_ 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_; + if (value == expected_) { + return true; + } + + const FloatType diff = value - expected_; + if (fabs(diff) <= max_abs_error_) { + return true; + } + + if (listener->IsInterested()) { + *listener << "which is " << diff << " from " << expected_; + } + return false; } else { - return lhs.AlmostEquals(rhs); + return actual.AlmostEquals(expected); } } @@ -1933,14 +1950,14 @@ class FloatingEqMatcher { // after outputting. const ::std::streamsize old_precision = os->precision( ::std::numeric_limits<FloatType>::digits10 + 2); - if (FloatingPoint<FloatType>(rhs_).is_nan()) { + if (FloatingPoint<FloatType>(expected_).is_nan()) { if (nan_eq_nan_) { *os << "is NaN"; } else { *os << "never matches"; } } else { - *os << "is approximately " << rhs_; + *os << "is approximately " << expected_; if (HasMaxAbsError()) { *os << " (absolute error <= " << max_abs_error_ << ")"; } @@ -1952,14 +1969,14 @@ class FloatingEqMatcher { // As before, get original precision. const ::std::streamsize old_precision = os->precision( ::std::numeric_limits<FloatType>::digits10 + 2); - if (FloatingPoint<FloatType>(rhs_).is_nan()) { + if (FloatingPoint<FloatType>(expected_).is_nan()) { if (nan_eq_nan_) { *os << "isn't NaN"; } else { *os << "is anything"; } } else { - *os << "isn't approximately " << rhs_; + *os << "isn't approximately " << expected_; if (HasMaxAbsError()) { *os << " (absolute error > " << max_abs_error_ << ")"; } @@ -1973,7 +1990,7 @@ class FloatingEqMatcher { return max_abs_error_ >= 0; } - const FloatType rhs_; + const FloatType expected_; const bool nan_eq_nan_; // max_abs_error will be used for value comparison when >= 0. const FloatType max_abs_error_; @@ -1981,27 +1998,29 @@ class FloatingEqMatcher { GTEST_DISALLOW_ASSIGN_(Impl); }; - // The following 3 type conversion operators allow FloatEq(rhs) and - // NanSensitiveFloatEq(rhs) to be used as a Matcher<float>, a + // The following 3 type conversion operators allow FloatEq(expected) and + // NanSensitiveFloatEq(expected) to be used as a Matcher<float>, a // Matcher<const float&>, or a Matcher<float&>, but nothing else. // (While Google's C++ coding style doesn't allow arguments passed // 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_, max_abs_error_)); + return MakeMatcher( + new Impl<FloatType>(expected_, nan_eq_nan_, max_abs_error_)); } operator Matcher<const FloatType&>() const { return MakeMatcher( - new Impl<const FloatType&>(rhs_, nan_eq_nan_, max_abs_error_)); + new Impl<const FloatType&>(expected_, nan_eq_nan_, max_abs_error_)); } operator Matcher<FloatType&>() const { - return MakeMatcher(new Impl<FloatType&>(rhs_, nan_eq_nan_, max_abs_error_)); + return MakeMatcher( + new Impl<FloatType&>(expected_, nan_eq_nan_, max_abs_error_)); } private: - const FloatType rhs_; + const FloatType expected_; const bool nan_eq_nan_; // max_abs_error will be used for value comparison when >= 0. const FloatType max_abs_error_; @@ -2489,9 +2508,10 @@ class ContainerEqMatcher { typedef typename View::type StlContainer; typedef typename View::const_reference StlContainerReference; - // We make a copy of rhs in case the elements in it are modified + // We make a copy of expected in case the elements in it are modified // after this matcher is created. - explicit ContainerEqMatcher(const Container& rhs) : rhs_(View::Copy(rhs)) { + explicit ContainerEqMatcher(const Container& expected) + : expected_(View::Copy(expected)) { // Makes sure the user doesn't instantiate this class template // with a const or reference type. (void)testing::StaticAssertTypeEq<Container, @@ -2500,11 +2520,11 @@ class ContainerEqMatcher { void DescribeTo(::std::ostream* os) const { *os << "equals "; - UniversalPrint(rhs_, os); + UniversalPrint(expected_, os); } void DescribeNegationTo(::std::ostream* os) const { *os << "does not equal "; - UniversalPrint(rhs_, os); + UniversalPrint(expected_, os); } template <typename LhsContainer> @@ -2516,7 +2536,7 @@ class ContainerEqMatcher { LhsView; typedef typename LhsView::type LhsStlContainer; StlContainerReference lhs_stl_container = LhsView::ConstReference(lhs); - if (lhs_stl_container == rhs_) + if (lhs_stl_container == expected_) return true; ::std::ostream* const os = listener->stream(); @@ -2526,8 +2546,8 @@ class ContainerEqMatcher { for (typename LhsStlContainer::const_iterator it = lhs_stl_container.begin(); it != lhs_stl_container.end(); ++it) { - if (internal::ArrayAwareFind(rhs_.begin(), rhs_.end(), *it) == - rhs_.end()) { + if (internal::ArrayAwareFind(expected_.begin(), expected_.end(), *it) == + expected_.end()) { if (printed_header) { *os << ", "; } else { @@ -2540,8 +2560,8 @@ class ContainerEqMatcher { // Now check for missing values. bool printed_header2 = false; - for (typename StlContainer::const_iterator it = rhs_.begin(); - it != rhs_.end(); ++it) { + for (typename StlContainer::const_iterator it = expected_.begin(); + it != expected_.end(); ++it) { if (internal::ArrayAwareFind( lhs_stl_container.begin(), lhs_stl_container.end(), *it) == lhs_stl_container.end()) { @@ -2561,7 +2581,7 @@ class ContainerEqMatcher { } private: - const StlContainer rhs_; + const StlContainer expected_; GTEST_DISALLOW_ASSIGN_(ContainerEqMatcher); }; diff --git a/include/gmock/gmock-more-actions.h b/include/gmock/gmock-more-actions.h index c754440..3d387b6 100644 --- a/include/gmock/gmock-more-actions.h +++ b/include/gmock/gmock-more-actions.h @@ -72,7 +72,7 @@ template <class Class, typename MethodPtr> class InvokeMethodAction { public: InvokeMethodAction(Class* obj_ptr, MethodPtr method_ptr) - : obj_ptr_(obj_ptr), method_ptr_(method_ptr) {} + : method_ptr_(method_ptr), obj_ptr_(obj_ptr) {} template <typename Result, typename ArgumentTuple> Result Perform(const ArgumentTuple& args) const { @@ -81,8 +81,11 @@ class InvokeMethodAction { } private: - Class* const obj_ptr_; + // The order of these members matters. Reversing the order can trigger + // warning C4121 in MSVC (see + // http://computer-programming-forum.com/7-vc.net/6fbc30265f860ad1.htm ). const MethodPtr method_ptr_; + Class* const obj_ptr_; GTEST_DISALLOW_ASSIGN_(InvokeMethodAction); }; diff --git a/test/gmock-matchers_test.cc b/test/gmock-matchers_test.cc index f5eff5f..be2e900 100644 --- a/test/gmock-matchers_test.cc +++ b/test/gmock-matchers_test.cc @@ -3071,6 +3071,19 @@ TEST_F(DoubleNearTest, DoubleNearCanDescribeSelf) { EXPECT_EQ("is anything", DescribeNegation(m3)); } +TEST_F(DoubleNearTest, ExplainsResultWhenMatchFails) { + EXPECT_EQ("", Explain(DoubleNear(2.0, 0.1), 2.05)); + EXPECT_EQ("which is 0.2 from 2", Explain(DoubleNear(2.0, 0.1), 2.2)); + EXPECT_EQ("which is -0.3 from 2", Explain(DoubleNear(2.0, 0.1), 1.7)); + + const string explanation = Explain(DoubleNear(2.1, 1e-10), 2.1 + 1.2e-10); + // Different C++ implementations may print floating-point numbers + // slightly differently. + EXPECT_TRUE(explanation == "which is 1.2e-10 from 2.1" || // GCC + explanation == "which is 1.2e-010 from 2.1") // MSVC + << " where explanation is \"" << explanation << "\"."; +} + TEST_F(DoubleNearTest, NanSensitiveDoubleNearCanDescribeSelf) { Matcher<double> m1 = NanSensitiveDoubleNear(2.0, 0.5); EXPECT_EQ("is approximately 2 (absolute error <= 0.5)", Describe(m1)); |