Handling of double.NaNs is inconsistent
bacar opened this issue · 4 comments
Bug Type
Please pick one:
- a check failed to detect an error (false negative), i.e. a test is green while it should be red.
- a check raised a non existing error (false positive), i.e a test is red while it should be green.
- an error message is invalid/incomplete (please provide samples)
- a ran into an exception.
- other.
Describe the bug
Consider the test below with failures described in comments.
It is confounding that:
- 5 passes while 1 and 6 do not (IsEqualTo does not behave like Equals)
- 1 & 6 fail while 2 and 8 do not (
double
anddouble?
comparison ofNaN
is inconsistent) - 6 fails while 7 passes. (inconsistent behaviour across ostensibly simliar NFluent overloads / it is not obvious or discoverable how the behaviour should differ). I am using this as a workaround for the above issues now.
To Reproduce
[Test]
public void Check_NaNs()
{
CheckIt(double.NaN); // succeeds 2.7.2, fails 3.0.2 -- 1
CheckIt((double?)Double.NaN); // 2
CheckIt2(double.NaN); // 3
CheckIt2((double?)Double.NaN); // 4
Check.That(double.NaN.Equals(double.NaN)).IsTrue(); // 5
Check.That(double.NaN).IsEqualTo(double.NaN); // fails in both 2.7.2 and 3.0.2 - 6
Check.That(double.NaN).IsEqualTo<double>(double.NaN); // 7
Check.That((double?)double.NaN).IsEqualTo((double?)double.NaN); // 8
Check.That((double?)double.NaN).IsEqualTo<double?>(double.NaN); // 9
}
private static void CheckIt<T>(T t) => Check.That(t).IsEqualTo(t);
private static void CheckIt2<T>(T t) => Check.That(t).IsEqualTo<T>(t);
Expected behavior
IMO all the cases above should pass, given double.NaN.Equals(double.NaN)
. No other doubles for which Equals
passes fails IsEqualTo
.
IsNan()
is a useful standalone check for explicit NaN checks in test, but not ideal for a parameterized test (e.g.: to test your serialisation library can round trip doubles, including NaN).
Desktop (please complete the following information):
- NFluent version: 3.0.2
- Net Version: Net Fwmk 4.8
I need to dig to understand why : double.Nan != double.Nan
while double.Nan.Equals(double.Nan)
. But the BCL code is pretty explicit about ensuring NaN == NaN
.
So I assume this should be the default behavior.
NaN != NaN per the IEEE 754 floating point spec - which .net respects for == (but does its own thing for Equals)
Given NFluent's IsEqualTo seems to be a more generous "are these things equivalent in sense" check, I think it's more meaningful to follow Equals?
Net behavior is documented here, but not justified: https://learn.microsoft.com/fr-fr/dotnet/api/system.double.nan?view=net-8.0
Especially why Equals and Compare consider NaN as equals.
https://stackoverflow.com/a/4934316 is fairly informative on why