mirror of
				https://github.com/python/cpython.git
				synced 2025-11-03 19:34:08 +00:00 
			
		
		
		
	Split abstract.c and float.c tests of _testcapi into two parts: limited C API tests in _testlimitedcapi and non-limited C API tests in _testcapi. Update test_bytes and test_class.
		
			
				
	
	
		
			183 lines
		
	
	
	
		
			6.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			183 lines
		
	
	
	
		
			6.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
import math
 | 
						|
import sys
 | 
						|
import unittest
 | 
						|
import warnings
 | 
						|
 | 
						|
from test.test_capi.test_getargs import (Float, FloatSubclass, FloatSubclass2,
 | 
						|
                                         BadIndex2, BadFloat2, Index, BadIndex,
 | 
						|
                                         BadFloat)
 | 
						|
from test.support import import_helper
 | 
						|
 | 
						|
_testcapi = import_helper.import_module('_testcapi')
 | 
						|
_testlimitedcapi = import_helper.import_module('_testlimitedcapi')
 | 
						|
 | 
						|
NULL = None
 | 
						|
 | 
						|
# For PyFloat_Pack/Unpack*
 | 
						|
BIG_ENDIAN = 0
 | 
						|
LITTLE_ENDIAN = 1
 | 
						|
EPSILON = {
 | 
						|
    2: 2.0 ** -11,  # binary16
 | 
						|
    4: 2.0 ** -24,  # binary32
 | 
						|
    8: 2.0 ** -53,  # binary64
 | 
						|
}
 | 
						|
 | 
						|
HAVE_IEEE_754 = float.__getformat__("double").startswith("IEEE")
 | 
						|
INF = float("inf")
 | 
						|
NAN = float("nan")
 | 
						|
 | 
						|
 | 
						|
class CAPIFloatTest(unittest.TestCase):
 | 
						|
    def test_check(self):
 | 
						|
        # Test PyFloat_Check()
 | 
						|
        check = _testlimitedcapi.float_check
 | 
						|
 | 
						|
        self.assertTrue(check(4.25))
 | 
						|
        self.assertTrue(check(FloatSubclass(4.25)))
 | 
						|
        self.assertFalse(check(Float()))
 | 
						|
        self.assertFalse(check(3))
 | 
						|
        self.assertFalse(check(object()))
 | 
						|
 | 
						|
        # CRASHES check(NULL)
 | 
						|
 | 
						|
    def test_checkexact(self):
 | 
						|
        # Test PyFloat_CheckExact()
 | 
						|
        checkexact = _testlimitedcapi.float_checkexact
 | 
						|
 | 
						|
        self.assertTrue(checkexact(4.25))
 | 
						|
        self.assertFalse(checkexact(FloatSubclass(4.25)))
 | 
						|
        self.assertFalse(checkexact(Float()))
 | 
						|
        self.assertFalse(checkexact(3))
 | 
						|
        self.assertFalse(checkexact(object()))
 | 
						|
 | 
						|
        # CRASHES checkexact(NULL)
 | 
						|
 | 
						|
    def test_fromstring(self):
 | 
						|
        # Test PyFloat_FromString()
 | 
						|
        fromstring = _testlimitedcapi.float_fromstring
 | 
						|
 | 
						|
        self.assertEqual(fromstring("4.25"), 4.25)
 | 
						|
        self.assertEqual(fromstring(b"4.25"), 4.25)
 | 
						|
        self.assertRaises(ValueError, fromstring, "4.25\0")
 | 
						|
        self.assertRaises(ValueError, fromstring, b"4.25\0")
 | 
						|
 | 
						|
        self.assertEqual(fromstring(bytearray(b"4.25")), 4.25)
 | 
						|
 | 
						|
        self.assertEqual(fromstring(memoryview(b"4.25")), 4.25)
 | 
						|
        self.assertEqual(fromstring(memoryview(b"4.255")[:-1]), 4.25)
 | 
						|
        self.assertRaises(TypeError, fromstring, memoryview(b"4.25")[::2])
 | 
						|
 | 
						|
        self.assertRaises(TypeError, fromstring, 4.25)
 | 
						|
 | 
						|
        # CRASHES fromstring(NULL)
 | 
						|
 | 
						|
    def test_fromdouble(self):
 | 
						|
        # Test PyFloat_FromDouble()
 | 
						|
        fromdouble = _testlimitedcapi.float_fromdouble
 | 
						|
 | 
						|
        self.assertEqual(fromdouble(4.25), 4.25)
 | 
						|
 | 
						|
    def test_asdouble(self):
 | 
						|
        # Test PyFloat_AsDouble()
 | 
						|
        asdouble = _testlimitedcapi.float_asdouble
 | 
						|
 | 
						|
        class BadFloat3:
 | 
						|
            def __float__(self):
 | 
						|
                raise RuntimeError
 | 
						|
 | 
						|
        self.assertEqual(asdouble(4.25), 4.25)
 | 
						|
        self.assertEqual(asdouble(-1.0), -1.0)
 | 
						|
        self.assertEqual(asdouble(42), 42.0)
 | 
						|
        self.assertEqual(asdouble(-1), -1.0)
 | 
						|
        self.assertEqual(asdouble(2**1000), float(2**1000))
 | 
						|
 | 
						|
        self.assertEqual(asdouble(FloatSubclass(4.25)), 4.25)
 | 
						|
        self.assertEqual(asdouble(FloatSubclass2(4.25)), 4.25)
 | 
						|
        self.assertEqual(asdouble(Index()), 99.)
 | 
						|
 | 
						|
        self.assertRaises(TypeError, asdouble, BadIndex())
 | 
						|
        self.assertRaises(TypeError, asdouble, BadFloat())
 | 
						|
        self.assertRaises(RuntimeError, asdouble, BadFloat3())
 | 
						|
        with self.assertWarns(DeprecationWarning):
 | 
						|
            self.assertEqual(asdouble(BadIndex2()), 1.)
 | 
						|
        with self.assertWarns(DeprecationWarning):
 | 
						|
            self.assertEqual(asdouble(BadFloat2()), 4.25)
 | 
						|
        with warnings.catch_warnings():
 | 
						|
            warnings.simplefilter("error", DeprecationWarning)
 | 
						|
            self.assertRaises(DeprecationWarning, asdouble, BadFloat2())
 | 
						|
        self.assertRaises(TypeError, asdouble, object())
 | 
						|
        self.assertRaises(TypeError, asdouble, NULL)
 | 
						|
 | 
						|
    def test_getinfo(self):
 | 
						|
        # Test PyFloat_GetInfo()
 | 
						|
        getinfo = _testlimitedcapi.float_getinfo
 | 
						|
 | 
						|
        self.assertEqual(getinfo(), sys.float_info)
 | 
						|
 | 
						|
    def test_getmax(self):
 | 
						|
        # Test PyFloat_GetMax()
 | 
						|
        getmax = _testlimitedcapi.float_getmax
 | 
						|
 | 
						|
        self.assertEqual(getmax(), sys.float_info.max)
 | 
						|
 | 
						|
    def test_getmin(self):
 | 
						|
        # Test PyFloat_GetMax()
 | 
						|
        getmin = _testlimitedcapi.float_getmin
 | 
						|
 | 
						|
        self.assertEqual(getmin(), sys.float_info.min)
 | 
						|
 | 
						|
    def test_pack(self):
 | 
						|
        # Test PyFloat_Pack2(), PyFloat_Pack4() and PyFloat_Pack8()
 | 
						|
        pack = _testcapi.float_pack
 | 
						|
 | 
						|
        self.assertEqual(pack(2, 1.5, BIG_ENDIAN), b'>\x00')
 | 
						|
        self.assertEqual(pack(4, 1.5, BIG_ENDIAN), b'?\xc0\x00\x00')
 | 
						|
        self.assertEqual(pack(8, 1.5, BIG_ENDIAN),
 | 
						|
                         b'?\xf8\x00\x00\x00\x00\x00\x00')
 | 
						|
        self.assertEqual(pack(2, 1.5, LITTLE_ENDIAN), b'\x00>')
 | 
						|
        self.assertEqual(pack(4, 1.5, LITTLE_ENDIAN), b'\x00\x00\xc0?')
 | 
						|
        self.assertEqual(pack(8, 1.5, LITTLE_ENDIAN),
 | 
						|
                         b'\x00\x00\x00\x00\x00\x00\xf8?')
 | 
						|
 | 
						|
    def test_unpack(self):
 | 
						|
        # Test PyFloat_Unpack2(), PyFloat_Unpack4() and PyFloat_Unpack8()
 | 
						|
        unpack = _testcapi.float_unpack
 | 
						|
 | 
						|
        self.assertEqual(unpack(b'>\x00', BIG_ENDIAN), 1.5)
 | 
						|
        self.assertEqual(unpack(b'?\xc0\x00\x00', BIG_ENDIAN), 1.5)
 | 
						|
        self.assertEqual(unpack(b'?\xf8\x00\x00\x00\x00\x00\x00', BIG_ENDIAN),
 | 
						|
                         1.5)
 | 
						|
        self.assertEqual(unpack(b'\x00>', LITTLE_ENDIAN), 1.5)
 | 
						|
        self.assertEqual(unpack(b'\x00\x00\xc0?', LITTLE_ENDIAN), 1.5)
 | 
						|
        self.assertEqual(unpack(b'\x00\x00\x00\x00\x00\x00\xf8?', LITTLE_ENDIAN),
 | 
						|
                         1.5)
 | 
						|
 | 
						|
    def test_pack_unpack_roundtrip(self):
 | 
						|
        pack = _testcapi.float_pack
 | 
						|
        unpack = _testcapi.float_unpack
 | 
						|
 | 
						|
        large = 2.0 ** 100
 | 
						|
        values = [1.0, 1.5, large, 1.0/7, math.pi]
 | 
						|
        if HAVE_IEEE_754:
 | 
						|
            values.extend((INF, NAN))
 | 
						|
        for value in values:
 | 
						|
            for size in (2, 4, 8,):
 | 
						|
                if size == 2 and value == large:
 | 
						|
                    # too large for 16-bit float
 | 
						|
                    continue
 | 
						|
                rel_tol = EPSILON[size]
 | 
						|
                for endian in (BIG_ENDIAN, LITTLE_ENDIAN):
 | 
						|
                    with self.subTest(value=value, size=size, endian=endian):
 | 
						|
                        data = pack(size, value, endian)
 | 
						|
                        value2 = unpack(data, endian)
 | 
						|
                        if math.isnan(value):
 | 
						|
                            self.assertTrue(math.isnan(value2), (value, value2))
 | 
						|
                        elif size < 8:
 | 
						|
                            self.assertTrue(math.isclose(value2, value, rel_tol=rel_tol),
 | 
						|
                                            (value, value2))
 | 
						|
                        else:
 | 
						|
                            self.assertEqual(value2, value)
 | 
						|
 | 
						|
 | 
						|
if __name__ == "__main__":
 | 
						|
    unittest.main()
 |