Googletest export
Improve DoubleNearPredFormat output on bad epsilons DoubleNearPredFormat will happily accept epsilon values (abs_error) that are so small that they are meaningless. This turns EXPECT_NEAR into a complicated and non-obvious version of EXPECT_EQ. This change modifies DoubleNearPredFormat) so that when there is a failure it calculates the smallest meaningful epsilon value, given the input values, and then prints a message which explains what happened. If a true equality test is wanted either pass a literal 0.0 as abs_error or use EXPECT_EQ. If a check for being almost equal is wanted consider using EXPECT_DOUBLE_EQ which, contrary to its name, verifies that the two numbers are *almost* equal (within four ULPs). With this change the flaky test mentioned in crbug.com/786046 gives this output: The difference between 4.2934311416234112e+18 and 4.2934311416234107e+18 is 512, where 4.2934311416234112e+18 evaluates to 4.2934311416234112e+18, 4.2934311416234107e+18 evaluates to 4.2934311416234107e+18. The abs_error parameter 1.0 evaluates to 1 which is smaller than the minimum distance between doubles for numbers of this magnitude which is 512, thus making this EXPECT_NEAR check equivalent to EXPECT_EQUAL. Consider using EXPECT_DOUBLE_EQ instead. Tested: I confirmed that this change detects the bad epsilon value that caused crbug.com/786046 in Chromium and added a test for the desired output. PiperOrigin-RevId: 332946880
This commit is contained in:
parent
7aca84427f
commit
b5687db554
@ -1516,6 +1516,30 @@ AssertionResult DoubleNearPredFormat(const char* expr1,
|
|||||||
const double diff = fabs(val1 - val2);
|
const double diff = fabs(val1 - val2);
|
||||||
if (diff <= abs_error) return AssertionSuccess();
|
if (diff <= abs_error) return AssertionSuccess();
|
||||||
|
|
||||||
|
// Find the value which is closest to zero.
|
||||||
|
const double min_abs = std::min(fabs(val1), fabs(val2));
|
||||||
|
// Find the distance to the next double from that value.
|
||||||
|
const double epsilon =
|
||||||
|
nextafter(min_abs, std::numeric_limits<double>::infinity()) - min_abs;
|
||||||
|
// Detect the case where abs_error is so small that EXPECT_NEAR is
|
||||||
|
// effectively the same as EXPECT_EQUAL, and give an informative error
|
||||||
|
// message so that the situation can be more easily understood without
|
||||||
|
// requiring exotic floating-point knowledge.
|
||||||
|
// Don't do an epsilon check if abs_error is zero because that implies
|
||||||
|
// that an equality check was actually intended.
|
||||||
|
if (!isnan(val1) && !isnan(val2) && abs_error > 0 && abs_error < epsilon) {
|
||||||
|
return AssertionFailure()
|
||||||
|
<< "The difference between " << expr1 << " and " << expr2 << " is "
|
||||||
|
<< diff << ", where\n"
|
||||||
|
<< expr1 << " evaluates to " << val1 << ",\n"
|
||||||
|
<< expr2 << " evaluates to " << val2 << ".\nThe abs_error parameter "
|
||||||
|
<< abs_error_expr << " evaluates to " << abs_error
|
||||||
|
<< " which is smaller than the minimum distance between doubles for "
|
||||||
|
"numbers of this magnitude which is "
|
||||||
|
<< epsilon
|
||||||
|
<< ", thus making this EXPECT_NEAR check equivalent to "
|
||||||
|
"EXPECT_EQUAL. Consider using EXPECT_DOUBLE_EQ instead.";
|
||||||
|
}
|
||||||
return AssertionFailure()
|
return AssertionFailure()
|
||||||
<< "The difference between " << expr1 << " and " << expr2
|
<< "The difference between " << expr1 << " and " << expr2
|
||||||
<< " is " << diff << ", which exceeds " << abs_error_expr << ", where\n"
|
<< " is " << diff << ", which exceeds " << abs_error_expr << ", where\n"
|
||||||
|
@ -3084,6 +3084,13 @@ TEST_F(DoubleTest, EXPECT_NEAR) {
|
|||||||
EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(1.0, 1.5, 0.25), // NOLINT
|
EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(1.0, 1.5, 0.25), // NOLINT
|
||||||
"The difference between 1.0 and 1.5 is 0.5, "
|
"The difference between 1.0 and 1.5 is 0.5, "
|
||||||
"which exceeds 0.25");
|
"which exceeds 0.25");
|
||||||
|
// At this magnitude adjacent doubles are 512.0 apart, so this triggers a
|
||||||
|
// slightly different failure reporting path.
|
||||||
|
EXPECT_NONFATAL_FAILURE(
|
||||||
|
EXPECT_NEAR(4.2934311416234112e+18, 4.2934311416234107e+18, 1.0),
|
||||||
|
"The abs_error parameter 1.0 evaluates to 1 which is smaller than the "
|
||||||
|
"minimum distance between doubles for numbers of this magnitude which is "
|
||||||
|
"512");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests ASSERT_NEAR.
|
// Tests ASSERT_NEAR.
|
||||||
|
Loading…
Reference in New Issue
Block a user