gh-130317: Fix test_pack_unpack_roundtrip() and add docs (#133204)

* Skip sNaN's testing in 32-bit mode.
* Drop float_set_snan() helper.
* Use memcpy() workaround for sNaN's in PyFloat_Unpack4().
* Document, that sNaN's may not be preserved by PyFloat_Pack/Unpack API.
This commit is contained in:
Sergey B Kirpichev 2025-05-01 17:20:36 +03:00 committed by GitHub
parent ed039b801d
commit ad2f0884b1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 18 additions and 62 deletions

View file

@ -180,12 +180,6 @@ class CAPIFloatTest(unittest.TestCase):
self.assertEqual(value2, value)
@unittest.skipUnless(HAVE_IEEE_754, "requires IEEE 754")
# Skip on x86 (32-bit), since these tests fail. The problem is that sNaN
# doubles become qNaN doubles just by the C calling convention, there is no
# way to preserve sNaN doubles between C function calls. But tests pass
# on Windows x86.
@unittest.skipIf((sys.maxsize == 2147483647) and not(sys.platform == 'win32'),
'test fails on x86 (32-bit)')
def test_pack_unpack_roundtrip_for_nans(self):
pack = _testcapi.float_pack
unpack = _testcapi.float_unpack
@ -193,7 +187,16 @@ class CAPIFloatTest(unittest.TestCase):
for _ in range(10):
for size in (2, 4, 8):
sign = random.randint(0, 1)
signaling = random.randint(0, 1)
if sys.maxsize != 2147483647: # not it 32-bit mode
signaling = random.randint(0, 1)
else:
# Skip sNaN's on x86 (32-bit). The problem is that sNaN
# doubles become qNaN doubles just by the C calling
# convention, there is no way to preserve sNaN doubles
# between C function calls with the current
# PyFloat_Pack/Unpack*() API. See also gh-130317 and
# e.g. https://developercommunity.visualstudio.com/t/155064
signaling = 0
quiet = int(not signaling)
if size == 8:
payload = random.randint(signaling, 1 << 50)
@ -209,12 +212,6 @@ class CAPIFloatTest(unittest.TestCase):
with self.subTest(data=data, size=size, endian=endian):
data1 = data if endian == BIG_ENDIAN else data[::-1]
value = unpack(data1, endian)
if signaling and sys.platform == 'win32':
# On Windows x86, sNaN becomes qNaN when returned
# from function. That's a known bug, e.g.
# https://developercommunity.visualstudio.com/t/155064
# (see also gh-130317).
value = _testcapi.float_set_snan(value)
data2 = pack(size, value, endian)
self.assertTrue(math.isnan(value))
self.assertEqual(data1, data2)