diff --git a/googletest/include/gtest/gtest.h b/googletest/include/gtest/gtest.h index bcea14507e..135dcdb2a8 100644 --- a/googletest/include/gtest/gtest.h +++ b/googletest/include/gtest/gtest.h @@ -1781,12 +1781,24 @@ AssertionResult CmpHelperFloatingPointEQ(const char* lhs_expression, // Helper function for implementing ASSERT_NEAR. // // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. -GTEST_API_ AssertionResult DoubleNearPredFormat(const char* expr1, - const char* expr2, - const char* abs_error_expr, - double val1, - double val2, - double abs_error); +template +AssertionResult FPNearPredFormat(const char* expr1, const char* expr2, + const char* abs_error_expr, const R1& val1, + const R2& val2, const T& abs_error) { + auto diff = val1 > val2 ? val1 - val2 : val2 - val1; + if (diff <= abs_error) { + return AssertionSuccess(); + } + return AssertionFailure() + << std::setprecision(std::numeric_limits< + typename std::decay::type>::max_digits10 + + 2) + << "The difference between " << expr1 << " and " << expr2 << " is " + << diff << ", which exceeds " << abs_error_expr << ", where\n" + << expr1 << " evaluates to " << val1 << ",\n" + << expr2 << " evaluates to " << val2 << ", and\n" + << abs_error_expr << " evaluates to " << abs_error << "."; +} // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. // A class that enables one to stream messages to assertion macros @@ -2167,11 +2179,11 @@ class TestWithParam : public Test, public WithParamInterface { val1, val2) #define EXPECT_NEAR(val1, val2, abs_error)\ - EXPECT_PRED_FORMAT3(::testing::internal::DoubleNearPredFormat, \ + EXPECT_PRED_FORMAT3(::testing::internal::FPNearPredFormat, \ val1, val2, abs_error) #define ASSERT_NEAR(val1, val2, abs_error)\ - ASSERT_PRED_FORMAT3(::testing::internal::DoubleNearPredFormat, \ + ASSERT_PRED_FORMAT3(::testing::internal::FPNearPredFormat, \ val1, val2, abs_error) // These predicate format functions work on floating-point values, and diff --git a/googletest/src/gtest.cc b/googletest/src/gtest.cc index d1cfb535f5..8270228fb1 100644 --- a/googletest/src/gtest.cc +++ b/googletest/src/gtest.cc @@ -1380,25 +1380,6 @@ std::string GetBoolAssertionFailureMessage( return msg.GetString(); } -// Helper function for implementing ASSERT_NEAR. -AssertionResult DoubleNearPredFormat(const char* expr1, - const char* expr2, - const char* abs_error_expr, - double val1, - double val2, - double abs_error) { - const double diff = fabs(val1 - val2); - if (diff <= abs_error) return AssertionSuccess(); - - return AssertionFailure() - << "The difference between " << expr1 << " and " << expr2 - << " is " << diff << ", which exceeds " << abs_error_expr << ", where\n" - << expr1 << " evaluates to " << val1 << ",\n" - << expr2 << " evaluates to " << val2 << ", and\n" - << abs_error_expr << " evaluates to " << abs_error << "."; -} - - // Helper template for implementing FloatLE() and DoubleLE(). template AssertionResult FloatingPointLE(const char* expr1, diff --git a/googletest/test/gtest_unittest.cc b/googletest/test/gtest_unittest.cc index 4ab298c411..eed451bc6b 100644 --- a/googletest/test/gtest_unittest.cc +++ b/googletest/test/gtest_unittest.cc @@ -3103,6 +3103,100 @@ TEST_F(DoubleTest, DoubleLEFails) { } +TEST(LongDoubleTest, EXPECT_NEAR) { + { + long double a = -1.0; + long double b = -1.1; + EXPECT_NEAR(a, b, 0.2); + } + { + long double a = -1.0; + long double b = -1.5; + EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(a, b, 0.25), // NOLINT + "The difference between a and b is 0.5, " + "which exceeds 0.25, where\na evaluates to -1,\nb " + "evaluates to -1.5, and\n0.25 evaluates to 0.25."); + } +} + +TEST(LongDoubleTest, ASSERT_NEAR) { + { + long double a = -1.0; + long double b = -1.1; + ASSERT_NEAR(a, b, 0.2); + } + { + EXPECT_FATAL_FAILURE(long double a = -1.0; long double b = -1.5; + ASSERT_NEAR(a, b, 0.25), // NOLINT + "The difference between a and b is 0.5, " + "which exceeds 0.25, where\na evaluates to -1,\nb " + "evaluates to -1.5, and\n0.25 evaluates to 0.25."); + } +} + +namespace custom_real_ns { +// a custom floating-point like type which implements the minimal interface +// required to test EXPECT_NEAR on a custom type +class custom_real { + // internally stores as a double to prevent having to implement an actual + // custom real-like type + double value_; + + public: + explicit custom_real(double value) : value_(value) {} + friend custom_real operator-(custom_real l, custom_real r) { + return custom_real(l.value_ - r.value_); + } + friend bool operator>(custom_real l, custom_real r) { + return l.value_ > r.value_; + } + friend bool operator<=(custom_real l, custom_real r) { + return l.value_ <= r.value_; + } + friend std::ostream& operator<<(std::ostream& out, custom_real v) { + out << v.value_; + return out; + } +}; +} // namespace custom_real_ns + +TEST(CustomRealTest, EXPECT_NEAR) { + { + custom_real_ns::custom_real a(-1.0); + custom_real_ns::custom_real b(-1.1); + EXPECT_NEAR(a, b, custom_real_ns::custom_real(0.2)); + } + { + custom_real_ns::custom_real a(-1.0); + custom_real_ns::custom_real b(-1.5); + EXPECT_NONFATAL_FAILURE( + EXPECT_NEAR(a, b, custom_real_ns::custom_real(0.25)), // NOLINT + "The difference between a and b is 0.5, " + "which exceeds custom_real_ns::custom_real(0.25), where\na evaluates " + "to -1,\nb " + "evaluates to -1.5, and\ncustom_real_ns::custom_real(0.25) evaluates " + "to 0.25."); + } +} +TEST(CustomRealTest, ASSERT_NEAR) { + { + custom_real_ns::custom_real a(-1.0); + custom_real_ns::custom_real b(-1.1); + ASSERT_NEAR(a, b, custom_real_ns::custom_real(0.2)); + } + { + EXPECT_FATAL_FAILURE( + custom_real_ns::custom_real a(-1.0); + custom_real_ns::custom_real b(-1.5); + ASSERT_NEAR(a, b, custom_real_ns::custom_real(0.25)), // NOLINT + "The difference between a and b is 0.5, " + "which exceeds custom_real_ns::custom_real(0.25), where\na evaluates " + "to -1,\nb " + "evaluates to -1.5, and\ncustom_real_ns::custom_real(0.25) evaluates " + "to 0.25."); + } +} + // Verifies that a test or test case whose name starts with DISABLED_ is // not run.