I'm trying to property test a binary serialization...
# kotest
b
I'm trying to property test a binary serialization format and I've run into a fun situation when testing that values remain unchanged when round-trip serializing them. With floats for example, I caught
0f shouldBe -0f
failing like I expect, but
NaN shouldBe NaN
failing when I'd want it to pass. (also worth noting,
0f shouldBeExactly -0f
does fail, and so does
0f shouldBeEqualComparingTo -0f
) I saw several discussions in the issue tracker which conclude that "IEEE says they're equal". Which I do understand, but I would've expected
shouldBeExactly
to work like I expect here (failing for
±0
and passing for
NaN
), and maybe a similar
shouldEqual
that's the opposite for these cases (passing for
±0
and failing for
NaN
) going off
==
behind the scenes, in turn following the IEEE spec. I couldn't find one, but is there a function out there to accomplish this? Something that confirms values are "the same", e.g. for an identity function that should work for any/all values thrown at it. I'll probably write my own Float/Double
shouldBinaryEqual
functions but I would be curious what others think
I know there's a slight inconsistency with equality between boxed type comparison and the analogous value type comparisons. That might be why I'm seeing different results there since shouldBe is generic. I do also know that there are whole ranges in the binary representation of floating point numbers dedicated to different NaN values, so to those none the wiser a shouldBe that sometimes says NaN is equal to NaN and sometimes not could be confusing
d
By design, NaN does not equal anything, not even itself. The proper way to test for NaN is to use isNaN I think
b
The thing is that I'm not testing for NaN or equality, though. Just that the value is the "same", whatever the value may be. I did some research and found that other libraries do consider NaN to be the same in assertions (kotlin.test, junit, testng, and likely others), and posted an issue here if you're interested
d
I think it just defers to equals in the end and then you get
Double.NaN == Double.NaN
which yields false by design, it says so in the JDK docs for Double:
If
v1
and
v2
are both NaN, then
v1
== v2
has the value
false
. Therefore, for two NaN arguments the reflexive property of an equivalence relation is not satisfied by the
==
operator.
So it boils down to whether shouldBe should exactly mean "equal to" (using equality check) or not
This is not just like this in the JVM, in JavaScript NaN == NaN also yields false
b
Yeah we're on the same page. And interestingly
NaN shouldBe NaN
passes because boxed equals has slightly different behavior
In the issue I also go over all that, and into the pragmatism of handling the NaN case in tests, plus how Kotest is sort of the odd one out with the way it's handled compared to other libraries
d
I mean, you could treat it specially, like null, but you'd have to document it. To me, the weirdness is that a thing does not equal itself in the RFC/ JVM