[Cppunit-devel] CPPUNIT_ASSERT_DOUBLES_EQUAL() with non-finite numbers
Brought to you by:
blep
From: CppUnit d. m. l. <cpp...@li...> - 2006-11-16 06:18:39
|
Howdy, I recently received a Debian bug report for CppUnit = (http://bugs.debian.org/396865) that CPPUNIT_ASSERT_DOUBLES_EQUAL() does = not work as expected if one value is NaN. This bug has previously been reported to CppUnit at least twice: = http://sourceforge.net/tracker/index.php?func=3Ddetail&aid=3D1179131&grou= p_id=3D11795&atid=3D111795 = http://sourceforge.net/tracker/index.php?func=3Ddetail&aid=3D754638&group= _id=3D11795&atid=3D111795 In addition, there have been at least two patches for the problem: = http://sourceforge.net/tracker/index.php?func=3Ddetail&aid=3D1591244&grou= p_id=3D11795&atid=3D311795 = http://sourceforge.net/tracker/index.php?func=3Ddetail&aid=3D756340&group= _id=3D11795&atid=3D311795 Contrary to the claim of Baptiste in the latter patch, isnan() is = standard: it is part of C99. Hopefully we can assume it is portable by = now. My patch (below) uses isfinite() instead, which is also from C99. First, here are additional test cases to nail down the semantics of = CPPUNIT_ASSERT_DOUBLES: - NaN is not equal to anything, not even to another NaN - infinity is equal to infinity This patch is against CVS. Index: examples/cppunittest/TestAssertTest.cpp =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: = /cvsroot/cppunit/cppunit/examples/cppunittest/TestAssertTest.cpp,v retrieving revision 1.9 diff -u -b -B -r1.9 TestAssertTest.cpp --- examples/cppunittest/TestAssertTest.cpp 5 Nov 2004 22:47:21 = -0000 1.9 +++ examples/cppunittest/TestAssertTest.cpp 11 Nov 2006 03:57:43 = -0000 @@ -167,6 +167,17 @@ =20 CPPUNIT_ASSERT_ASSERTION_FAIL( CPPUNIT_ASSERT_DOUBLES_EQUAL( 1.1, = 1.2, 0.09 ) ); CPPUNIT_ASSERT_ASSERTION_FAIL( CPPUNIT_ASSERT_DOUBLES_EQUAL( 1.2, = 1.1, 0.09 ) ); + + double inf =3D std::numeric_limits<double>::infinity(); + CPPUNIT_ASSERT_ASSERTION_FAIL( CPPUNIT_ASSERT_DOUBLES_EQUAL( inf, = 0.0, 1.0 ) ); + CPPUNIT_ASSERT_ASSERTION_FAIL( CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.0, = inf, 1.0 ) ); + CPPUNIT_ASSERT_ASSERTION_PASS( CPPUNIT_ASSERT_DOUBLES_EQUAL( inf, = inf, 1.0 ) ); + + double nan =3D std::numeric_limits<double>::quiet_NaN(); + CPPUNIT_ASSERT_ASSERTION_FAIL( CPPUNIT_ASSERT_DOUBLES_EQUAL( nan, = 0.0, 1.0 ) ); + CPPUNIT_ASSERT_ASSERTION_FAIL( CPPUNIT_ASSERT_DOUBLES_EQUAL( nan, = nan, 1.0 ) ); + CPPUNIT_ASSERT_ASSERTION_FAIL( CPPUNIT_ASSERT_DOUBLES_EQUAL( nan, = inf, 1.0 ) ); + CPPUNIT_ASSERT_ASSERTION_FAIL( CPPUNIT_ASSERT_DOUBLES_EQUAL( inf, = nan, 1.0 ) ); } =20 =20 Now, here is my proposed fix. I'm applying this to Debian's CppUnit = package. Index: src/cppunit/TestAssert.cpp =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /cvsroot/cppunit/cppunit/src/cppunit/TestAssert.cpp,v retrieving revision 1.12 diff -u -b -B -r1.12 TestAssert.cpp --- src/cppunit/TestAssert.cpp 5 Nov 2004 22:47:20 -0000 1.12 +++ src/cppunit/TestAssert.cpp 11 Nov 2006 03:57:56 -0000 @@ -21,7 +21,13 @@ assertion_traits<double>::toString(delta) ); msg.addDetail( AdditionalMessage(message) ); =20 - Asserter::failNotEqualIf( fabs( expected - actual ) > delta, + bool equal; + if ( isfinite(expected) && isfinite(actual) ) + equal =3D fabs( expected - actual ) <=3D delta; + else + equal =3D expected =3D=3D actual; + + Asserter::failNotEqualIf( !equal, = assertion_traits<double>::toString(expected), assertion_traits<double>::toString(actual), sourceLine,=20 Cheers, -Steve |