Removed the Requirement to Install Python and NodeJS (Now Bundled with Borealis)
This commit is contained in:
12
Dependencies/Python/Lib/test/test_capi/__init__.py
vendored
Normal file
12
Dependencies/Python/Lib/test/test_capi/__init__.py
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
import os
|
||||
import unittest
|
||||
from test.support import load_package_tests
|
||||
from test.support import TEST_MODULES_ENABLED
|
||||
|
||||
|
||||
if not TEST_MODULES_ENABLED:
|
||||
raise unittest.SkipTest("requires test modules")
|
||||
|
||||
|
||||
def load_tests(*args):
|
||||
return load_package_tests(os.path.dirname(__file__), *args)
|
3
Dependencies/Python/Lib/test/test_capi/__main__.py
vendored
Normal file
3
Dependencies/Python/Lib/test/test_capi/__main__.py
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
import unittest
|
||||
|
||||
unittest.main('test.test_capi')
|
77
Dependencies/Python/Lib/test/test_capi/check_config.py
vendored
Normal file
77
Dependencies/Python/Lib/test/test_capi/check_config.py
vendored
Normal file
@ -0,0 +1,77 @@
|
||||
# This script is used by test_misc.
|
||||
|
||||
import _imp
|
||||
import _testinternalcapi
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
|
||||
|
||||
def import_singlephase():
|
||||
assert '_testsinglephase' not in sys.modules
|
||||
try:
|
||||
import _testsinglephase
|
||||
except ImportError:
|
||||
sys.modules.pop('_testsinglephase', None)
|
||||
return False
|
||||
else:
|
||||
del sys.modules['_testsinglephase']
|
||||
return True
|
||||
|
||||
|
||||
def check_singlephase(override):
|
||||
# Check using the default setting.
|
||||
settings_initial = _testinternalcapi.get_interp_settings()
|
||||
allowed_initial = import_singlephase()
|
||||
assert(_testinternalcapi.get_interp_settings() == settings_initial)
|
||||
|
||||
# Apply the override and check.
|
||||
override_initial = _imp._override_multi_interp_extensions_check(override)
|
||||
settings_after = _testinternalcapi.get_interp_settings()
|
||||
allowed_after = import_singlephase()
|
||||
|
||||
# Apply the override again and check.
|
||||
noop = {}
|
||||
override_after = _imp._override_multi_interp_extensions_check(override)
|
||||
settings_noop = _testinternalcapi.get_interp_settings()
|
||||
if settings_noop != settings_after:
|
||||
noop['settings_noop'] = settings_noop
|
||||
allowed_noop = import_singlephase()
|
||||
if allowed_noop != allowed_after:
|
||||
noop['allowed_noop'] = allowed_noop
|
||||
|
||||
# Restore the original setting and check.
|
||||
override_noop = _imp._override_multi_interp_extensions_check(override_initial)
|
||||
if override_noop != override_after:
|
||||
noop['override_noop'] = override_noop
|
||||
settings_restored = _testinternalcapi.get_interp_settings()
|
||||
allowed_restored = import_singlephase()
|
||||
|
||||
# Restore the original setting again.
|
||||
override_restored = _imp._override_multi_interp_extensions_check(override_initial)
|
||||
assert(_testinternalcapi.get_interp_settings() == settings_restored)
|
||||
|
||||
return dict({
|
||||
'requested': override,
|
||||
'override__initial': override_initial,
|
||||
'override_after': override_after,
|
||||
'override_restored': override_restored,
|
||||
'settings__initial': settings_initial,
|
||||
'settings_after': settings_after,
|
||||
'settings_restored': settings_restored,
|
||||
'allowed__initial': allowed_initial,
|
||||
'allowed_after': allowed_after,
|
||||
'allowed_restored': allowed_restored,
|
||||
}, **noop)
|
||||
|
||||
|
||||
def run_singlephase_check(override, outfd):
|
||||
with os.fdopen(outfd, 'w') as outfile:
|
||||
sys.stdout = outfile
|
||||
sys.stderr = outfile
|
||||
try:
|
||||
results = check_singlephase(override)
|
||||
json.dump(results, outfile)
|
||||
finally:
|
||||
sys.stdout = sys.__stdout__
|
||||
sys.stderr = sys.__stderr__
|
1005
Dependencies/Python/Lib/test/test_capi/test_abstract.py
vendored
Normal file
1005
Dependencies/Python/Lib/test/test_capi/test_abstract.py
vendored
Normal file
File diff suppressed because it is too large
Load Diff
167
Dependencies/Python/Lib/test/test_capi/test_bytearray.py
vendored
Normal file
167
Dependencies/Python/Lib/test/test_capi/test_bytearray.py
vendored
Normal file
@ -0,0 +1,167 @@
|
||||
import unittest
|
||||
from test.support import import_helper
|
||||
|
||||
_testlimitedcapi = import_helper.import_module('_testlimitedcapi')
|
||||
from _testcapi import PY_SSIZE_T_MIN, PY_SSIZE_T_MAX
|
||||
|
||||
NULL = None
|
||||
|
||||
class ByteArraySubclass(bytearray):
|
||||
pass
|
||||
|
||||
class BytesLike:
|
||||
def __init__(self, value):
|
||||
self.value = value
|
||||
def __bytes__(self):
|
||||
return self.value
|
||||
|
||||
|
||||
class CAPITest(unittest.TestCase):
|
||||
def test_check(self):
|
||||
# Test PyByteArray_Check()
|
||||
check = _testlimitedcapi.bytearray_check
|
||||
self.assertTrue(check(bytearray(b'')))
|
||||
self.assertTrue(check(bytearray(b'abc')))
|
||||
self.assertFalse(check(b'abc'))
|
||||
self.assertTrue(check(ByteArraySubclass(b'abc')))
|
||||
self.assertFalse(check(BytesLike(b'abc')))
|
||||
self.assertFalse(check(3))
|
||||
self.assertFalse(check([]))
|
||||
self.assertFalse(check(object()))
|
||||
|
||||
# CRASHES check(NULL)
|
||||
|
||||
def test_checkexact(self):
|
||||
# Test PyByteArray_CheckExact()
|
||||
check = _testlimitedcapi.bytearray_checkexact
|
||||
self.assertTrue(check(bytearray(b'')))
|
||||
self.assertTrue(check(bytearray(b'abc')))
|
||||
self.assertFalse(check(b'abc'))
|
||||
self.assertFalse(check(ByteArraySubclass(b'abc')))
|
||||
self.assertFalse(check(BytesLike(b'abc')))
|
||||
self.assertFalse(check(3))
|
||||
self.assertFalse(check([]))
|
||||
self.assertFalse(check(object()))
|
||||
|
||||
# CRASHES check(NULL)
|
||||
|
||||
def test_fromstringandsize(self):
|
||||
# Test PyByteArray_FromStringAndSize()
|
||||
fromstringandsize = _testlimitedcapi.bytearray_fromstringandsize
|
||||
|
||||
self.assertEqual(fromstringandsize(b'abc'), bytearray(b'abc'))
|
||||
self.assertEqual(fromstringandsize(b'abc', 2), bytearray(b'ab'))
|
||||
self.assertEqual(fromstringandsize(b'abc\0def'), bytearray(b'abc\0def'))
|
||||
self.assertEqual(fromstringandsize(b'', 0), bytearray())
|
||||
self.assertEqual(fromstringandsize(NULL, 0), bytearray())
|
||||
self.assertEqual(len(fromstringandsize(NULL, 3)), 3)
|
||||
self.assertRaises(MemoryError, fromstringandsize, NULL, PY_SSIZE_T_MAX)
|
||||
|
||||
self.assertRaises(SystemError, fromstringandsize, b'abc', -1)
|
||||
self.assertRaises(SystemError, fromstringandsize, b'abc', PY_SSIZE_T_MIN)
|
||||
self.assertRaises(SystemError, fromstringandsize, NULL, -1)
|
||||
self.assertRaises(SystemError, fromstringandsize, NULL, PY_SSIZE_T_MIN)
|
||||
|
||||
def test_fromobject(self):
|
||||
# Test PyByteArray_FromObject()
|
||||
fromobject = _testlimitedcapi.bytearray_fromobject
|
||||
|
||||
self.assertEqual(fromobject(b'abc'), bytearray(b'abc'))
|
||||
self.assertEqual(fromobject(bytearray(b'abc')), bytearray(b'abc'))
|
||||
self.assertEqual(fromobject(ByteArraySubclass(b'abc')), bytearray(b'abc'))
|
||||
self.assertEqual(fromobject([97, 98, 99]), bytearray(b'abc'))
|
||||
self.assertEqual(fromobject(3), bytearray(b'\0\0\0'))
|
||||
self.assertRaises(TypeError, fromobject, BytesLike(b'abc'))
|
||||
self.assertRaises(TypeError, fromobject, 'abc')
|
||||
self.assertRaises(TypeError, fromobject, object())
|
||||
|
||||
# CRASHES fromobject(NULL)
|
||||
|
||||
def test_size(self):
|
||||
# Test PyByteArray_Size()
|
||||
size = _testlimitedcapi.bytearray_size
|
||||
self.assertEqual(size(bytearray(b'')), 0)
|
||||
self.assertEqual(size(bytearray(b'abc')), 3)
|
||||
self.assertEqual(size(ByteArraySubclass(b'abc')), 3)
|
||||
|
||||
# CRASHES size(b'abc')
|
||||
# CRASHES size(object())
|
||||
# CRASHES size(NULL)
|
||||
|
||||
def test_asstring(self):
|
||||
"""Test PyByteArray_AsString()"""
|
||||
asstring = _testlimitedcapi.bytearray_asstring
|
||||
self.assertEqual(asstring(bytearray(b''), 1), b'\0')
|
||||
self.assertEqual(asstring(bytearray(b'abc'), 4), b'abc\0')
|
||||
self.assertEqual(asstring(ByteArraySubclass(b'abc'), 4), b'abc\0')
|
||||
self.assertEqual(asstring(bytearray(b'abc\0def'), 8), b'abc\0def\0')
|
||||
|
||||
# CRASHES asstring(b'abc', 0)
|
||||
# CRASHES asstring(object()', 0)
|
||||
# CRASHES asstring(NULL, 0)
|
||||
|
||||
def test_concat(self):
|
||||
"""Test PyByteArray_Concat()"""
|
||||
concat = _testlimitedcapi.bytearray_concat
|
||||
|
||||
ba = bytearray(b'abc')
|
||||
self.assertEqual(concat(ba, b'def'), bytearray(b'abcdef'))
|
||||
self.assertEqual(ba, b'abc')
|
||||
self.assertEqual(concat(ba, ba), bytearray(b'abcabc'))
|
||||
|
||||
self.assertEqual(concat(b'abc', b'def'), bytearray(b'abcdef'))
|
||||
self.assertEqual(concat(b'a\0b', b'c\0d'), bytearray(b'a\0bc\0d'))
|
||||
self.assertEqual(concat(bytearray(b'abc'), b'def'), bytearray(b'abcdef'))
|
||||
self.assertEqual(concat(b'abc', bytearray(b'def')), bytearray(b'abcdef'))
|
||||
self.assertEqual(concat(bytearray(b'abc'), b''), bytearray(b'abc'))
|
||||
self.assertEqual(concat(b'', bytearray(b'def')), bytearray(b'def'))
|
||||
self.assertEqual(concat(memoryview(b'xabcy')[1:4], b'def'),
|
||||
bytearray(b'abcdef'))
|
||||
self.assertEqual(concat(b'abc', memoryview(b'xdefy')[1:4]),
|
||||
bytearray(b'abcdef'))
|
||||
|
||||
self.assertRaises(TypeError, concat, memoryview(b'axbycz')[::2], b'def')
|
||||
self.assertRaises(TypeError, concat, b'abc', memoryview(b'dxeyfz')[::2])
|
||||
self.assertRaises(TypeError, concat, b'abc', 'def')
|
||||
self.assertRaises(TypeError, concat, 'abc', b'def')
|
||||
self.assertRaises(TypeError, concat, 'abc', 'def')
|
||||
self.assertRaises(TypeError, concat, [], b'def')
|
||||
self.assertRaises(TypeError, concat, b'abc', [])
|
||||
self.assertRaises(TypeError, concat, [], [])
|
||||
|
||||
# CRASHES concat(NULL, bytearray(b'def'))
|
||||
# CRASHES concat(bytearray(b'abc'), NULL)
|
||||
# CRASHES concat(NULL, object())
|
||||
# CRASHES concat(object(), NULL)
|
||||
|
||||
def test_resize(self):
|
||||
"""Test PyByteArray_Resize()"""
|
||||
resize = _testlimitedcapi.bytearray_resize
|
||||
|
||||
ba = bytearray(b'abcdef')
|
||||
self.assertEqual(resize(ba, 3), 0)
|
||||
self.assertEqual(ba, bytearray(b'abc'))
|
||||
self.assertEqual(resize(ba, 10), 0)
|
||||
self.assertEqual(len(ba), 10)
|
||||
self.assertEqual(ba[:3], bytearray(b'abc'))
|
||||
self.assertEqual(resize(ba, 2**20), 0)
|
||||
self.assertEqual(len(ba), 2**20)
|
||||
self.assertEqual(ba[:3], bytearray(b'abc'))
|
||||
self.assertEqual(resize(ba, 0), 0)
|
||||
self.assertEqual(ba, bytearray())
|
||||
|
||||
ba = ByteArraySubclass(b'abcdef')
|
||||
self.assertEqual(resize(ba, 3), 0)
|
||||
self.assertEqual(ba, bytearray(b'abc'))
|
||||
|
||||
self.assertRaises(MemoryError, resize, bytearray(), PY_SSIZE_T_MAX)
|
||||
self.assertRaises(MemoryError, resize, bytearray(1000), PY_SSIZE_T_MAX)
|
||||
|
||||
# CRASHES resize(bytearray(b'abc'), -1)
|
||||
# CRASHES resize(b'abc', 0)
|
||||
# CRASHES resize(object(), 0)
|
||||
# CRASHES resize(NULL, 0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
255
Dependencies/Python/Lib/test/test_capi/test_bytes.py
vendored
Normal file
255
Dependencies/Python/Lib/test/test_capi/test_bytes.py
vendored
Normal file
@ -0,0 +1,255 @@
|
||||
import unittest
|
||||
from test.support import import_helper
|
||||
|
||||
_testlimitedcapi = import_helper.import_module('_testlimitedcapi')
|
||||
_testcapi = import_helper.import_module('_testcapi')
|
||||
from _testcapi import PY_SSIZE_T_MIN, PY_SSIZE_T_MAX
|
||||
|
||||
NULL = None
|
||||
|
||||
class BytesSubclass(bytes):
|
||||
pass
|
||||
|
||||
class BytesLike:
|
||||
def __init__(self, value):
|
||||
self.value = value
|
||||
def __bytes__(self):
|
||||
return self.value
|
||||
|
||||
|
||||
class CAPITest(unittest.TestCase):
|
||||
def test_check(self):
|
||||
# Test PyBytes_Check()
|
||||
check = _testlimitedcapi.bytes_check
|
||||
self.assertTrue(check(b'abc'))
|
||||
self.assertFalse(check('abc'))
|
||||
self.assertFalse(check(bytearray(b'abc')))
|
||||
self.assertTrue(check(BytesSubclass(b'abc')))
|
||||
self.assertFalse(check(BytesLike(b'abc')))
|
||||
self.assertFalse(check(3))
|
||||
self.assertFalse(check([]))
|
||||
self.assertFalse(check(object()))
|
||||
|
||||
# CRASHES check(NULL)
|
||||
|
||||
def test_checkexact(self):
|
||||
# Test PyBytes_CheckExact()
|
||||
check = _testlimitedcapi.bytes_checkexact
|
||||
self.assertTrue(check(b'abc'))
|
||||
self.assertFalse(check('abc'))
|
||||
self.assertFalse(check(bytearray(b'abc')))
|
||||
self.assertFalse(check(BytesSubclass(b'abc')))
|
||||
self.assertFalse(check(BytesLike(b'abc')))
|
||||
self.assertFalse(check(3))
|
||||
self.assertFalse(check([]))
|
||||
self.assertFalse(check(object()))
|
||||
|
||||
# CRASHES check(NULL)
|
||||
|
||||
def test_fromstringandsize(self):
|
||||
# Test PyBytes_FromStringAndSize()
|
||||
fromstringandsize = _testlimitedcapi.bytes_fromstringandsize
|
||||
|
||||
self.assertEqual(fromstringandsize(b'abc'), b'abc')
|
||||
self.assertEqual(fromstringandsize(b'abc', 2), b'ab')
|
||||
self.assertEqual(fromstringandsize(b'abc\0def'), b'abc\0def')
|
||||
self.assertEqual(fromstringandsize(b'a'), b'a')
|
||||
self.assertEqual(fromstringandsize(b'a', 1), b'a')
|
||||
self.assertEqual(fromstringandsize(b'', 0), b'')
|
||||
self.assertEqual(fromstringandsize(NULL, 0), b'')
|
||||
self.assertEqual(len(fromstringandsize(NULL, 3)), 3)
|
||||
self.assertRaises((MemoryError, OverflowError),
|
||||
fromstringandsize, NULL, PY_SSIZE_T_MAX)
|
||||
|
||||
self.assertRaises(SystemError, fromstringandsize, b'abc', -1)
|
||||
self.assertRaises(SystemError, fromstringandsize, b'abc', PY_SSIZE_T_MIN)
|
||||
self.assertRaises(SystemError, fromstringandsize, NULL, -1)
|
||||
self.assertRaises(SystemError, fromstringandsize, NULL, PY_SSIZE_T_MIN)
|
||||
|
||||
def test_fromstring(self):
|
||||
# Test PyBytes_FromString()
|
||||
fromstring = _testlimitedcapi.bytes_fromstring
|
||||
|
||||
self.assertEqual(fromstring(b'abc\0def'), b'abc')
|
||||
self.assertEqual(fromstring(b''), b'')
|
||||
|
||||
# CRASHES fromstring(NULL)
|
||||
|
||||
def test_fromobject(self):
|
||||
# Test PyBytes_FromObject()
|
||||
fromobject = _testlimitedcapi.bytes_fromobject
|
||||
|
||||
self.assertEqual(fromobject(b'abc'), b'abc')
|
||||
self.assertEqual(fromobject(bytearray(b'abc')), b'abc')
|
||||
self.assertEqual(fromobject(BytesSubclass(b'abc')), b'abc')
|
||||
self.assertEqual(fromobject([97, 98, 99]), b'abc')
|
||||
self.assertRaises(TypeError, fromobject, 3)
|
||||
self.assertRaises(TypeError, fromobject, BytesLike(b'abc'))
|
||||
self.assertRaises(TypeError, fromobject, 'abc')
|
||||
self.assertRaises(TypeError, fromobject, object())
|
||||
self.assertRaises(SystemError, fromobject, NULL)
|
||||
|
||||
def test_size(self):
|
||||
# Test PyBytes_Size()
|
||||
size = _testlimitedcapi.bytes_size
|
||||
|
||||
self.assertEqual(size(b''), 0)
|
||||
self.assertEqual(size(b'abc'), 3)
|
||||
self.assertEqual(size(BytesSubclass(b'abc')), 3)
|
||||
self.assertRaises(TypeError, size, bytearray(b'abc'))
|
||||
self.assertRaises(TypeError, size, 'abc')
|
||||
self.assertRaises(TypeError, size, object())
|
||||
|
||||
# CRASHES size(NULL)
|
||||
|
||||
def test_asstring(self):
|
||||
"""Test PyBytes_AsString()"""
|
||||
asstring = _testlimitedcapi.bytes_asstring
|
||||
|
||||
self.assertEqual(asstring(b'abc', 4), b'abc\0')
|
||||
self.assertEqual(asstring(b'abc\0def', 8), b'abc\0def\0')
|
||||
self.assertRaises(TypeError, asstring, 'abc', 0)
|
||||
self.assertRaises(TypeError, asstring, object(), 0)
|
||||
|
||||
# CRASHES asstring(NULL, 0)
|
||||
|
||||
def test_asstringandsize(self):
|
||||
"""Test PyBytes_AsStringAndSize()"""
|
||||
asstringandsize = _testlimitedcapi.bytes_asstringandsize
|
||||
asstringandsize_null = _testlimitedcapi.bytes_asstringandsize_null
|
||||
|
||||
self.assertEqual(asstringandsize(b'abc', 4), (b'abc\0', 3))
|
||||
self.assertEqual(asstringandsize(b'abc\0def', 8), (b'abc\0def\0', 7))
|
||||
self.assertEqual(asstringandsize_null(b'abc', 4), b'abc\0')
|
||||
self.assertRaises(ValueError, asstringandsize_null, b'abc\0def', 8)
|
||||
self.assertRaises(TypeError, asstringandsize, 'abc', 0)
|
||||
self.assertRaises(TypeError, asstringandsize_null, 'abc', 0)
|
||||
self.assertRaises(TypeError, asstringandsize, object(), 0)
|
||||
self.assertRaises(TypeError, asstringandsize_null, object(), 0)
|
||||
|
||||
# CRASHES asstringandsize(NULL, 0)
|
||||
# CRASHES asstringandsize_null(NULL, 0)
|
||||
|
||||
def test_repr(self):
|
||||
# Test PyBytes_Repr()
|
||||
bytes_repr = _testlimitedcapi.bytes_repr
|
||||
|
||||
self.assertEqual(bytes_repr(b'''abc''', 0), r"""b'abc'""")
|
||||
self.assertEqual(bytes_repr(b'''abc''', 1), r"""b'abc'""")
|
||||
self.assertEqual(bytes_repr(b'''a'b"c"d''', 0), r"""b'a\'b"c"d'""")
|
||||
self.assertEqual(bytes_repr(b'''a'b"c"d''', 1), r"""b'a\'b"c"d'""")
|
||||
self.assertEqual(bytes_repr(b'''a'b"c''', 0), r"""b'a\'b"c'""")
|
||||
self.assertEqual(bytes_repr(b'''a'b"c''', 1), r"""b'a\'b"c'""")
|
||||
self.assertEqual(bytes_repr(b'''a'b'c"d''', 0), r"""b'a\'b\'c"d'""")
|
||||
self.assertEqual(bytes_repr(b'''a'b'c"d''', 1), r"""b'a\'b\'c"d'""")
|
||||
self.assertEqual(bytes_repr(b'''a'b'c'd''', 0), r"""b'a\'b\'c\'d'""")
|
||||
self.assertEqual(bytes_repr(b'''a'b'c'd''', 1), r'''b"a'b'c'd"''')
|
||||
|
||||
self.assertEqual(bytes_repr(BytesSubclass(b'abc'), 0), r"""b'abc'""")
|
||||
|
||||
# UDEFINED bytes_repr(object(), 0)
|
||||
# CRASHES bytes_repr(NULL, 0)
|
||||
|
||||
def test_concat(self, concat=None):
|
||||
"""Test PyBytes_Concat()"""
|
||||
if concat is None:
|
||||
concat = _testlimitedcapi.bytes_concat
|
||||
|
||||
self.assertEqual(concat(b'abc', b'def'), b'abcdef')
|
||||
self.assertEqual(concat(b'a\0b', b'c\0d'), b'a\0bc\0d')
|
||||
self.assertEqual(concat(bytearray(b'abc'), b'def'), b'abcdef')
|
||||
self.assertEqual(concat(b'abc', bytearray(b'def')), b'abcdef')
|
||||
self.assertEqual(concat(bytearray(b'abc'), b''), b'abc')
|
||||
self.assertEqual(concat(b'', bytearray(b'def')), b'def')
|
||||
self.assertEqual(concat(memoryview(b'xabcy')[1:4], b'def'), b'abcdef')
|
||||
self.assertEqual(concat(b'abc', memoryview(b'xdefy')[1:4]), b'abcdef')
|
||||
|
||||
self.assertEqual(concat(b'abc', b'def', True), b'abcdef')
|
||||
self.assertEqual(concat(b'abc', bytearray(b'def'), True), b'abcdef')
|
||||
# Check that it does not change the singleton
|
||||
self.assertEqual(concat(bytes(), b'def', True), b'def')
|
||||
self.assertEqual(len(bytes()), 0)
|
||||
|
||||
self.assertRaises(TypeError, concat, memoryview(b'axbycz')[::2], b'def')
|
||||
self.assertRaises(TypeError, concat, b'abc', memoryview(b'dxeyfz')[::2])
|
||||
self.assertRaises(TypeError, concat, b'abc', 'def')
|
||||
self.assertRaises(TypeError, concat, 'abc', b'def')
|
||||
self.assertRaises(TypeError, concat, 'abc', 'def')
|
||||
self.assertRaises(TypeError, concat, [], b'def')
|
||||
self.assertRaises(TypeError, concat, b'abc', [])
|
||||
self.assertRaises(TypeError, concat, [], [])
|
||||
|
||||
self.assertEqual(concat(NULL, b'def'), NULL)
|
||||
self.assertEqual(concat(b'abc', NULL), NULL)
|
||||
self.assertEqual(concat(NULL, object()), NULL)
|
||||
self.assertEqual(concat(object(), NULL), NULL)
|
||||
|
||||
def test_concatanddel(self):
|
||||
"""Test PyBytes_ConcatAndDel()"""
|
||||
self.test_concat(_testlimitedcapi.bytes_concatanddel)
|
||||
|
||||
def test_decodeescape(self):
|
||||
"""Test PyBytes_DecodeEscape()"""
|
||||
decodeescape = _testlimitedcapi.bytes_decodeescape
|
||||
|
||||
self.assertEqual(decodeescape(b'abc'), b'abc')
|
||||
self.assertEqual(decodeescape(br'\t\n\r\x0b\x0c\x00\\\'\"'),
|
||||
b'''\t\n\r\v\f\0\\'"''')
|
||||
self.assertEqual(decodeescape(b'\t\n\r\x0b\x0c\x00'), b'\t\n\r\v\f\0')
|
||||
self.assertEqual(decodeescape(br'\xa1\xa2'), b'\xa1\xa2')
|
||||
self.assertEqual(decodeescape(br'\2\24\241'), b'\x02\x14\xa1')
|
||||
self.assertEqual(decodeescape(b'\xa1\xa2'), b'\xa1\xa2')
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
self.assertEqual(decodeescape(br'\u4f60'), br'\u4f60')
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
self.assertEqual(decodeescape(br'\z'), br'\z')
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
self.assertEqual(decodeescape(br'\541'), b'a')
|
||||
|
||||
for b in b'\\', br'\x', br'\xa', br'\xz', br'\xaz':
|
||||
self.assertRaises(ValueError, decodeescape, b)
|
||||
self.assertRaises(ValueError, decodeescape, b, 'strict')
|
||||
self.assertEqual(decodeescape(br'x\xa', 'replace'), b'x?')
|
||||
self.assertEqual(decodeescape(br'x\xay', 'replace'), b'x?y')
|
||||
self.assertEqual(decodeescape(br'x\xa\xy', 'replace'), b'x??y')
|
||||
self.assertEqual(decodeescape(br'x\xa\xy', 'ignore'), b'xy')
|
||||
self.assertRaises(ValueError, decodeescape, b'\\', 'spam')
|
||||
self.assertEqual(decodeescape(NULL), b'')
|
||||
self.assertRaises(OverflowError, decodeescape, b'abc', NULL, PY_SSIZE_T_MAX)
|
||||
self.assertRaises(OverflowError, decodeescape, NULL, NULL, PY_SSIZE_T_MAX)
|
||||
|
||||
# CRASHES decodeescape(b'abc', NULL, -1)
|
||||
# CRASHES decodeescape(NULL, NULL, 1)
|
||||
|
||||
def test_resize(self):
|
||||
"""Test _PyBytes_Resize()"""
|
||||
resize = _testcapi.bytes_resize
|
||||
|
||||
for new in True, False:
|
||||
self.assertEqual(resize(b'abc', 0, new), b'')
|
||||
self.assertEqual(resize(b'abc', 1, new), b'a')
|
||||
self.assertEqual(resize(b'abc', 2, new), b'ab')
|
||||
self.assertEqual(resize(b'abc', 3, new), b'abc')
|
||||
b = resize(b'abc', 4, new)
|
||||
self.assertEqual(len(b), 4)
|
||||
self.assertEqual(b[:3], b'abc')
|
||||
|
||||
self.assertEqual(resize(b'a', 0, new), b'')
|
||||
self.assertEqual(resize(b'a', 1, new), b'a')
|
||||
b = resize(b'a', 2, new)
|
||||
self.assertEqual(len(b), 2)
|
||||
self.assertEqual(b[:1], b'a')
|
||||
|
||||
self.assertEqual(resize(b'', 0, new), b'')
|
||||
self.assertEqual(len(resize(b'', 1, new)), 1)
|
||||
self.assertEqual(len(resize(b'', 2, new)), 2)
|
||||
|
||||
self.assertRaises(SystemError, resize, b'abc', -1, False)
|
||||
self.assertRaises(SystemError, resize, bytearray(b'abc'), 3, False)
|
||||
|
||||
# CRASHES resize(NULL, 0, False)
|
||||
# CRASHES resize(NULL, 3, False)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
520
Dependencies/Python/Lib/test/test_capi/test_codecs.py
vendored
Normal file
520
Dependencies/Python/Lib/test/test_capi/test_codecs.py
vendored
Normal file
@ -0,0 +1,520 @@
|
||||
import unittest
|
||||
import sys
|
||||
from test.support import import_helper
|
||||
|
||||
_testlimitedcapi = import_helper.import_module('_testlimitedcapi')
|
||||
|
||||
NULL = None
|
||||
|
||||
|
||||
class CAPITest(unittest.TestCase):
|
||||
# TODO: Test the following functions:
|
||||
#
|
||||
# PyUnicode_BuildEncodingMap
|
||||
# PyUnicode_FSConverter
|
||||
# PyUnicode_FSDecoder
|
||||
# PyUnicode_DecodeMBCS
|
||||
# PyUnicode_DecodeMBCSStateful
|
||||
# PyUnicode_DecodeCodePageStateful
|
||||
# PyUnicode_AsMBCSString
|
||||
# PyUnicode_EncodeCodePage
|
||||
# PyUnicode_DecodeLocaleAndSize
|
||||
# PyUnicode_DecodeLocale
|
||||
# PyUnicode_EncodeLocale
|
||||
# PyUnicode_DecodeFSDefault
|
||||
# PyUnicode_DecodeFSDefaultAndSize
|
||||
# PyUnicode_EncodeFSDefault
|
||||
|
||||
def test_fromencodedobject(self):
|
||||
"""Test PyUnicode_FromEncodedObject()"""
|
||||
fromencodedobject = _testlimitedcapi.unicode_fromencodedobject
|
||||
|
||||
self.assertEqual(fromencodedobject(b'abc', NULL), 'abc')
|
||||
self.assertEqual(fromencodedobject(b'abc', 'ascii'), 'abc')
|
||||
b = b'a\xc2\xa1\xe4\xbd\xa0\xf0\x9f\x98\x80'
|
||||
s = 'a\xa1\u4f60\U0001f600'
|
||||
self.assertEqual(fromencodedobject(b, NULL), s)
|
||||
self.assertEqual(fromencodedobject(b, 'utf-8'), s)
|
||||
self.assertEqual(fromencodedobject(b, 'latin1'), b.decode('latin1'))
|
||||
self.assertRaises(UnicodeDecodeError, fromencodedobject, b, 'ascii')
|
||||
self.assertEqual(fromencodedobject(b, 'ascii', 'replace'),
|
||||
'a' + '\ufffd'*9)
|
||||
self.assertEqual(fromencodedobject(bytearray(b), NULL), s)
|
||||
self.assertEqual(fromencodedobject(bytearray(b), 'utf-8'), s)
|
||||
self.assertRaises(LookupError, fromencodedobject, b'abc', 'foo')
|
||||
self.assertRaises(LookupError, fromencodedobject, b, 'ascii', 'foo')
|
||||
self.assertRaises(TypeError, fromencodedobject, 'abc', NULL)
|
||||
self.assertRaises(TypeError, fromencodedobject, 'abc', 'ascii')
|
||||
self.assertRaises(TypeError, fromencodedobject, [], NULL)
|
||||
self.assertRaises(TypeError, fromencodedobject, [], 'ascii')
|
||||
self.assertRaises(SystemError, fromencodedobject, NULL, NULL)
|
||||
self.assertRaises(SystemError, fromencodedobject, NULL, 'ascii')
|
||||
|
||||
def test_decode(self):
|
||||
"""Test PyUnicode_Decode()"""
|
||||
decode = _testlimitedcapi.unicode_decode
|
||||
|
||||
self.assertEqual(decode(b'[\xe2\x82\xac]', 'utf-8'), '[\u20ac]')
|
||||
self.assertEqual(decode(b'[\xa4]', 'iso8859-15'), '[\u20ac]')
|
||||
self.assertEqual(decode(b'[\xa4]', 'iso8859-15', 'strict'), '[\u20ac]')
|
||||
self.assertRaises(UnicodeDecodeError, decode, b'[\xa4]', 'utf-8')
|
||||
self.assertEqual(decode(b'[\xa4]', 'utf-8', 'replace'), '[\ufffd]')
|
||||
|
||||
self.assertEqual(decode(b'[\xe2\x82\xac]', NULL), '[\u20ac]')
|
||||
self.assertEqual(decode(b'[\xa4]', NULL, 'replace'), '[\ufffd]')
|
||||
|
||||
self.assertRaises(LookupError, decode, b'\xa4', 'foo')
|
||||
self.assertRaises(LookupError, decode, b'\xa4', 'utf-8', 'foo')
|
||||
# TODO: Test PyUnicode_Decode() with NULL as data and
|
||||
# negative size.
|
||||
|
||||
def test_asencodedstring(self):
|
||||
"""Test PyUnicode_AsEncodedString()"""
|
||||
asencodedstring = _testlimitedcapi.unicode_asencodedstring
|
||||
|
||||
self.assertEqual(asencodedstring('abc', NULL), b'abc')
|
||||
self.assertEqual(asencodedstring('abc', 'ascii'), b'abc')
|
||||
s = 'a\xa1\u4f60\U0001f600'
|
||||
b = b'a\xc2\xa1\xe4\xbd\xa0\xf0\x9f\x98\x80'
|
||||
self.assertEqual(asencodedstring(s, NULL), b)
|
||||
self.assertEqual(asencodedstring(s, 'utf-8'), b)
|
||||
self.assertEqual(asencodedstring('\xa1\xa2', 'latin1'), b'\xa1\xa2')
|
||||
self.assertRaises(UnicodeEncodeError, asencodedstring, '\xa1\xa2', 'ascii')
|
||||
self.assertEqual(asencodedstring(s, 'ascii', 'replace'), b'a???')
|
||||
|
||||
self.assertRaises(LookupError, asencodedstring, 'abc', 'foo')
|
||||
self.assertRaises(LookupError, asencodedstring, s, 'ascii', 'foo')
|
||||
self.assertRaises(TypeError, asencodedstring, b'abc', NULL)
|
||||
self.assertRaises(TypeError, asencodedstring, b'abc', 'ascii')
|
||||
self.assertRaises(TypeError, asencodedstring, [], NULL)
|
||||
self.assertRaises(TypeError, asencodedstring, [], 'ascii')
|
||||
# CRASHES asencodedstring(NULL, NULL)
|
||||
# CRASHES asencodedstring(NULL, 'ascii')
|
||||
|
||||
def test_decodeutf8(self):
|
||||
"""Test PyUnicode_DecodeUTF8()"""
|
||||
decodeutf8 = _testlimitedcapi.unicode_decodeutf8
|
||||
|
||||
for s in ['abc', '\xa1\xa2', '\u4f60\u597d', 'a\U0001f600']:
|
||||
b = s.encode('utf-8')
|
||||
self.assertEqual(decodeutf8(b), s)
|
||||
self.assertEqual(decodeutf8(b, 'strict'), s)
|
||||
|
||||
self.assertRaises(UnicodeDecodeError, decodeutf8, b'\x80')
|
||||
self.assertRaises(UnicodeDecodeError, decodeutf8, b'\xc0')
|
||||
self.assertRaises(UnicodeDecodeError, decodeutf8, b'\xff')
|
||||
self.assertRaises(UnicodeDecodeError, decodeutf8, b'a\xf0\x9f')
|
||||
self.assertEqual(decodeutf8(b'a\xf0\x9f', 'replace'), 'a\ufffd')
|
||||
self.assertEqual(decodeutf8(b'a\xf0\x9fb', 'replace'), 'a\ufffdb')
|
||||
|
||||
self.assertRaises(LookupError, decodeutf8, b'a\x80', 'foo')
|
||||
# TODO: Test PyUnicode_DecodeUTF8() with NULL as data and
|
||||
# negative size.
|
||||
|
||||
def test_decodeutf8stateful(self):
|
||||
"""Test PyUnicode_DecodeUTF8Stateful()"""
|
||||
decodeutf8stateful = _testlimitedcapi.unicode_decodeutf8stateful
|
||||
|
||||
for s in ['abc', '\xa1\xa2', '\u4f60\u597d', 'a\U0001f600']:
|
||||
b = s.encode('utf-8')
|
||||
self.assertEqual(decodeutf8stateful(b), (s, len(b)))
|
||||
self.assertEqual(decodeutf8stateful(b, 'strict'), (s, len(b)))
|
||||
|
||||
self.assertRaises(UnicodeDecodeError, decodeutf8stateful, b'\x80')
|
||||
self.assertRaises(UnicodeDecodeError, decodeutf8stateful, b'\xc0')
|
||||
self.assertRaises(UnicodeDecodeError, decodeutf8stateful, b'\xff')
|
||||
self.assertEqual(decodeutf8stateful(b'a\xf0\x9f'), ('a', 1))
|
||||
self.assertEqual(decodeutf8stateful(b'a\xf0\x9f', 'replace'), ('a', 1))
|
||||
self.assertRaises(UnicodeDecodeError, decodeutf8stateful, b'a\xf0\x9fb')
|
||||
self.assertEqual(decodeutf8stateful(b'a\xf0\x9fb', 'replace'), ('a\ufffdb', 4))
|
||||
|
||||
self.assertRaises(LookupError, decodeutf8stateful, b'a\x80', 'foo')
|
||||
# TODO: Test PyUnicode_DecodeUTF8Stateful() with NULL as data and
|
||||
# negative size.
|
||||
# TODO: Test PyUnicode_DecodeUTF8Stateful() with NULL as the address of
|
||||
# "consumed".
|
||||
|
||||
def test_asutf8string(self):
|
||||
"""Test PyUnicode_AsUTF8String()"""
|
||||
asutf8string = _testlimitedcapi.unicode_asutf8string
|
||||
|
||||
for s in ['abc', '\xa1\xa2', '\u4f60\u597d', 'a\U0001f600']:
|
||||
self.assertEqual(asutf8string(s), s.encode('utf-8'))
|
||||
|
||||
self.assertRaises(UnicodeEncodeError, asutf8string, '\ud8ff')
|
||||
self.assertRaises(TypeError, asutf8string, b'abc')
|
||||
self.assertRaises(TypeError, asutf8string, [])
|
||||
# CRASHES asutf8string(NULL)
|
||||
|
||||
def test_decodeutf16(self):
|
||||
"""Test PyUnicode_DecodeUTF16()"""
|
||||
decodeutf16 = _testlimitedcapi.unicode_decodeutf16
|
||||
|
||||
naturalbyteorder = -1 if sys.byteorder == 'little' else 1
|
||||
for s in ['abc', '\xa1\xa2', '\u4f60\u597d', 'a\U0001f600']:
|
||||
b = s.encode('utf-16')
|
||||
self.assertEqual(decodeutf16(0, b), (naturalbyteorder, s))
|
||||
b = s.encode('utf-16le')
|
||||
self.assertEqual(decodeutf16(-1, b), (-1, s))
|
||||
self.assertEqual(decodeutf16(0, b'\xff\xfe'+b), (-1, s))
|
||||
b = s.encode('utf-16be')
|
||||
self.assertEqual(decodeutf16(1, b), (1, s))
|
||||
self.assertEqual(decodeutf16(0, b'\xfe\xff'+b), (1, s))
|
||||
|
||||
self.assertRaises(UnicodeDecodeError, decodeutf16, -1, b'a')
|
||||
self.assertRaises(UnicodeDecodeError, decodeutf16, 1, b'a')
|
||||
self.assertRaises(UnicodeDecodeError, decodeutf16, 0, b'\xff\xfea')
|
||||
self.assertRaises(UnicodeDecodeError, decodeutf16, 0, b'\xfe\xffa')
|
||||
|
||||
self.assertRaises(UnicodeDecodeError, decodeutf16, -1, b'\x00\xde')
|
||||
self.assertRaises(UnicodeDecodeError, decodeutf16, 1, b'\xde\x00')
|
||||
self.assertRaises(UnicodeDecodeError, decodeutf16, 0, b'\xde\xde')
|
||||
self.assertEqual(decodeutf16(-1, b'\x00\xde', 'replace'), (-1, '\ufffd'))
|
||||
self.assertEqual(decodeutf16(1, b'\xde\x00', 'replace'), (1, '\ufffd'))
|
||||
self.assertEqual(decodeutf16(0, b'\xde\xde', 'replace'), (0, '\ufffd'))
|
||||
self.assertEqual(decodeutf16(0, b'\xff\xfe\x00\xde', 'replace'), (-1, '\ufffd'))
|
||||
self.assertEqual(decodeutf16(0, b'\xfe\xff\xde\x00', 'replace'), (1, '\ufffd'))
|
||||
|
||||
self.assertRaises(UnicodeDecodeError, decodeutf16, -1, b'\x3d\xd8')
|
||||
self.assertRaises(UnicodeDecodeError, decodeutf16, 1, b'\xd8\x3d')
|
||||
self.assertRaises(UnicodeDecodeError, decodeutf16, 0, b'\xd8\xd8')
|
||||
self.assertEqual(decodeutf16(-1, b'\x3d\xd8', 'replace'), (-1, '\ufffd'))
|
||||
self.assertEqual(decodeutf16(1, b'\xd8\x3d', 'replace'), (1, '\ufffd'))
|
||||
self.assertEqual(decodeutf16(0, b'\xd8\xd8', 'replace'), (0, '\ufffd'))
|
||||
self.assertEqual(decodeutf16(0, b'\xff\xfe\x3d\xd8', 'replace'), (-1, '\ufffd'))
|
||||
self.assertEqual(decodeutf16(0, b'\xfe\xff\xd8\x3d', 'replace'), (1, '\ufffd'))
|
||||
|
||||
self.assertRaises(LookupError, decodeutf16, -1, b'\x00\xde', 'foo')
|
||||
self.assertRaises(LookupError, decodeutf16, 1, b'\xde\x00', 'foo')
|
||||
self.assertRaises(LookupError, decodeutf16, 0, b'\xde\xde', 'foo')
|
||||
# TODO: Test PyUnicode_DecodeUTF16() with NULL as data and
|
||||
# negative size.
|
||||
|
||||
def test_decodeutf16stateful(self):
|
||||
"""Test PyUnicode_DecodeUTF16Stateful()"""
|
||||
decodeutf16stateful = _testlimitedcapi.unicode_decodeutf16stateful
|
||||
|
||||
naturalbyteorder = -1 if sys.byteorder == 'little' else 1
|
||||
for s in ['abc', '\xa1\xa2', '\u4f60\u597d', 'a\U0001f600']:
|
||||
b = s.encode('utf-16')
|
||||
self.assertEqual(decodeutf16stateful(0, b), (naturalbyteorder, s, len(b)))
|
||||
b = s.encode('utf-16le')
|
||||
self.assertEqual(decodeutf16stateful(-1, b), (-1, s, len(b)))
|
||||
self.assertEqual(decodeutf16stateful(0, b'\xff\xfe'+b), (-1, s, len(b)+2))
|
||||
b = s.encode('utf-16be')
|
||||
self.assertEqual(decodeutf16stateful(1, b), (1, s, len(b)))
|
||||
self.assertEqual(decodeutf16stateful(0, b'\xfe\xff'+b), (1, s, len(b)+2))
|
||||
|
||||
self.assertEqual(decodeutf16stateful(-1, b'\x61\x00\x3d'), (-1, 'a', 2))
|
||||
self.assertEqual(decodeutf16stateful(-1, b'\x61\x00\x3d\xd8'), (-1, 'a', 2))
|
||||
self.assertEqual(decodeutf16stateful(-1, b'\x61\x00\x3d\xd8\x00'), (-1, 'a', 2))
|
||||
self.assertEqual(decodeutf16stateful(1, b'\x00\x61\xd8'), (1, 'a', 2))
|
||||
self.assertEqual(decodeutf16stateful(1, b'\x00\x61\xd8\x3d'), (1, 'a', 2))
|
||||
self.assertEqual(decodeutf16stateful(1, b'\x00\x61\xd8\x3d\xde'), (1, 'a', 2))
|
||||
self.assertEqual(decodeutf16stateful(0, b'\xff\xfe\x61\x00\x3d\xd8\x00'), (-1, 'a', 4))
|
||||
self.assertEqual(decodeutf16stateful(0, b'\xfe\xff\x00\x61\xd8\x3d\xde'), (1, 'a', 4))
|
||||
|
||||
self.assertRaises(UnicodeDecodeError, decodeutf16stateful, -1, b'\x00\xde')
|
||||
self.assertRaises(UnicodeDecodeError, decodeutf16stateful, 1, b'\xde\x00')
|
||||
self.assertRaises(UnicodeDecodeError, decodeutf16stateful, 0, b'\xde\xde')
|
||||
self.assertEqual(decodeutf16stateful(-1, b'\x00\xde', 'replace'), (-1, '\ufffd', 2))
|
||||
self.assertEqual(decodeutf16stateful(1, b'\xde\x00', 'replace'), (1, '\ufffd', 2))
|
||||
self.assertEqual(decodeutf16stateful(0, b'\xde\xde', 'replace'), (0, '\ufffd', 2))
|
||||
self.assertEqual(decodeutf16stateful(0, b'\xff\xfe\x00\xde', 'replace'), (-1, '\ufffd', 4))
|
||||
self.assertEqual(decodeutf16stateful(0, b'\xfe\xff\xde\x00', 'replace'), (1, '\ufffd', 4))
|
||||
|
||||
self.assertRaises(UnicodeDecodeError, decodeutf16stateful, -1, b'\x3d\xd8\x61\x00')
|
||||
self.assertEqual(decodeutf16stateful(-1, b'\x3d\xd8\x61\x00', 'replace'), (-1, '\ufffda', 4))
|
||||
self.assertRaises(UnicodeDecodeError, decodeutf16stateful, 1, b'\xd8\x3d\x00\x61')
|
||||
self.assertEqual(decodeutf16stateful(1, b'\xd8\x3d\x00\x61', 'replace'), (1, '\ufffda', 4))
|
||||
|
||||
self.assertRaises(LookupError, decodeutf16stateful, -1, b'\x00\xde', 'foo')
|
||||
self.assertRaises(LookupError, decodeutf16stateful, 1, b'\xde\x00', 'foo')
|
||||
self.assertRaises(LookupError, decodeutf16stateful, 0, b'\xde\xde', 'foo')
|
||||
# TODO: Test PyUnicode_DecodeUTF16Stateful() with NULL as data and
|
||||
# negative size.
|
||||
# TODO: Test PyUnicode_DecodeUTF16Stateful() with NULL as the address of
|
||||
# "consumed".
|
||||
|
||||
def test_asutf16string(self):
|
||||
"""Test PyUnicode_AsUTF16String()"""
|
||||
asutf16string = _testlimitedcapi.unicode_asutf16string
|
||||
|
||||
for s in ['abc', '\xa1\xa2', '\u4f60\u597d', 'a\U0001f600']:
|
||||
self.assertEqual(asutf16string(s), s.encode('utf-16'))
|
||||
|
||||
self.assertRaises(UnicodeEncodeError, asutf16string, '\ud8ff')
|
||||
self.assertRaises(TypeError, asutf16string, b'abc')
|
||||
self.assertRaises(TypeError, asutf16string, [])
|
||||
# CRASHES asutf16string(NULL)
|
||||
|
||||
def test_decodeutf32(self):
|
||||
"""Test PyUnicode_DecodeUTF8()"""
|
||||
decodeutf32 = _testlimitedcapi.unicode_decodeutf32
|
||||
|
||||
naturalbyteorder = -1 if sys.byteorder == 'little' else 1
|
||||
for s in ['abc', '\xa1\xa2', '\u4f60\u597d', 'a\U0001f600']:
|
||||
b = s.encode('utf-32')
|
||||
self.assertEqual(decodeutf32(0, b), (naturalbyteorder, s))
|
||||
b = s.encode('utf-32le')
|
||||
self.assertEqual(decodeutf32(-1, b), (-1, s))
|
||||
self.assertEqual(decodeutf32(0, b'\xff\xfe\x00\x00'+b), (-1, s))
|
||||
b = s.encode('utf-32be')
|
||||
self.assertEqual(decodeutf32(1, b), (1, s))
|
||||
self.assertEqual(decodeutf32(0, b'\x00\x00\xfe\xff'+b), (1, s))
|
||||
|
||||
self.assertRaises(UnicodeDecodeError, decodeutf32, -1, b'\x61\x00\x00\x00\x00')
|
||||
self.assertRaises(UnicodeDecodeError, decodeutf32, 1, b'\x00\x00\x00\x61\x00')
|
||||
self.assertRaises(UnicodeDecodeError, decodeutf32, 0, b'\xff\xfe\x00\x00\x61\x00\x00\x00\x00')
|
||||
self.assertRaises(UnicodeDecodeError, decodeutf32, 0, b'\x00\x00\xfe\xff\x00\x00\x00\x61\x00')
|
||||
|
||||
self.assertRaises(UnicodeDecodeError, decodeutf32, -1, b'\xff\xff\xff\xff')
|
||||
self.assertRaises(UnicodeDecodeError, decodeutf32, 1, b'\xff\xff\xff\xff')
|
||||
self.assertRaises(UnicodeDecodeError, decodeutf32, 0, b'\xff\xff\xff\xff')
|
||||
self.assertEqual(decodeutf32(-1, b'\xff\xff\xff\xff', 'replace'), (-1, '\ufffd'))
|
||||
self.assertEqual(decodeutf32(1, b'\xff\xff\xff\xff', 'replace'), (1, '\ufffd'))
|
||||
self.assertEqual(decodeutf32(0, b'\xff\xff\xff\xff', 'replace'), (0, '\ufffd'))
|
||||
self.assertEqual(decodeutf32(0, b'\xff\xfe\x00\x00\xff\xff\xff\xff', 'replace'), (-1, '\ufffd'))
|
||||
self.assertEqual(decodeutf32(0, b'\x00\x00\xfe\xff\xff\xff\xff\xff', 'replace'), (1, '\ufffd'))
|
||||
|
||||
self.assertRaises(UnicodeDecodeError, decodeutf32, -1, b'\x3d\xd8\x00\x00')
|
||||
self.assertEqual(decodeutf32(-1, b'\x3d\xd8\x00\x00', 'replace'), (-1, '\ufffd'))
|
||||
self.assertRaises(UnicodeDecodeError, decodeutf32, 1, b'\x00\x00\xd8\x3d')
|
||||
self.assertEqual(decodeutf32(1, b'\x00\x00\xd8\x3d', 'replace'), (1, '\ufffd'))
|
||||
|
||||
self.assertRaises(LookupError, decodeutf32, -1, b'\xff\xff\xff\xff', 'foo')
|
||||
self.assertRaises(LookupError, decodeutf32, 1, b'\xff\xff\xff\xff', 'foo')
|
||||
self.assertRaises(LookupError, decodeutf32, 0, b'\xff\xff\xff\xff', 'foo')
|
||||
# TODO: Test PyUnicode_DecodeUTF32() with NULL as data and
|
||||
# negative size.
|
||||
|
||||
def test_decodeutf32stateful(self):
|
||||
"""Test PyUnicode_DecodeUTF32Stateful()"""
|
||||
decodeutf32stateful = _testlimitedcapi.unicode_decodeutf32stateful
|
||||
|
||||
naturalbyteorder = -1 if sys.byteorder == 'little' else 1
|
||||
for s in ['abc', '\xa1\xa2', '\u4f60\u597d', 'a\U0001f600']:
|
||||
b = s.encode('utf-32')
|
||||
self.assertEqual(decodeutf32stateful(0, b), (naturalbyteorder, s, len(b)))
|
||||
b = s.encode('utf-32le')
|
||||
self.assertEqual(decodeutf32stateful(-1, b), (-1, s, len(b)))
|
||||
self.assertEqual(decodeutf32stateful(0, b'\xff\xfe\x00\x00'+b), (-1, s, len(b)+4))
|
||||
b = s.encode('utf-32be')
|
||||
self.assertEqual(decodeutf32stateful(1, b), (1, s, len(b)))
|
||||
self.assertEqual(decodeutf32stateful(0, b'\x00\x00\xfe\xff'+b), (1, s, len(b)+4))
|
||||
|
||||
self.assertEqual(decodeutf32stateful(-1, b'\x61\x00\x00\x00\x00'), (-1, 'a', 4))
|
||||
self.assertEqual(decodeutf32stateful(-1, b'\x61\x00\x00\x00\x00\xf6'), (-1, 'a', 4))
|
||||
self.assertEqual(decodeutf32stateful(-1, b'\x61\x00\x00\x00\x00\xf6\x01'), (-1, 'a', 4))
|
||||
self.assertEqual(decodeutf32stateful(1, b'\x00\x00\x00\x61\x00'), (1, 'a', 4))
|
||||
self.assertEqual(decodeutf32stateful(1, b'\x00\x00\x00\x61\x00\x01'), (1, 'a', 4))
|
||||
self.assertEqual(decodeutf32stateful(1, b'\x00\x00\x00\x61\x00\x01\xf6'), (1, 'a', 4))
|
||||
self.assertEqual(decodeutf32stateful(0, b'\xff\xfe\x00\x00\x61\x00\x00\x00\x00\xf6\x01'), (-1, 'a', 8))
|
||||
self.assertEqual(decodeutf32stateful(0, b'\x00\x00\xfe\xff\x00\x00\x00\x61\x00\x01\xf6'), (1, 'a', 8))
|
||||
|
||||
for b in b'\xff', b'\xff\xff', b'\xff\xff\xff':
|
||||
self.assertEqual(decodeutf32stateful(-1, b), (-1, '', 0))
|
||||
self.assertEqual(decodeutf32stateful(1, b), (1, '', 0))
|
||||
self.assertEqual(decodeutf32stateful(0, b), (0, '', 0))
|
||||
self.assertEqual(decodeutf32stateful(0, b'\xff\xfe\x00\x00'+b), (-1, '', 4))
|
||||
self.assertEqual(decodeutf32stateful(0, b'\x00\x00\xfe\xff'+b), (1, '', 4))
|
||||
self.assertRaises(UnicodeDecodeError, decodeutf32stateful, -1, b'\xff\xff\xff\xff')
|
||||
self.assertRaises(UnicodeDecodeError, decodeutf32stateful, 1, b'\xff\xff\xff\xff')
|
||||
self.assertRaises(UnicodeDecodeError, decodeutf32stateful, 0, b'\xff\xff\xff\xff')
|
||||
self.assertEqual(decodeutf32stateful(-1, b'\xff\xff\xff\xff', 'replace'), (-1, '\ufffd', 4))
|
||||
self.assertEqual(decodeutf32stateful(1, b'\xff\xff\xff\xff', 'replace'), (1, '\ufffd', 4))
|
||||
self.assertEqual(decodeutf32stateful(0, b'\xff\xff\xff\xff', 'replace'), (0, '\ufffd', 4))
|
||||
self.assertEqual(decodeutf32stateful(0, b'\xff\xfe\x00\x00\xff\xff\xff\xff', 'replace'), (-1, '\ufffd', 8))
|
||||
self.assertEqual(decodeutf32stateful(0, b'\x00\x00\xfe\xff\xff\xff\xff\xff', 'replace'), (1, '\ufffd', 8))
|
||||
|
||||
self.assertRaises(UnicodeDecodeError, decodeutf32stateful, -1, b'\x3d\xd8\x00\x00')
|
||||
self.assertEqual(decodeutf32stateful(-1, b'\x3d\xd8\x00\x00', 'replace'), (-1, '\ufffd', 4))
|
||||
self.assertRaises(UnicodeDecodeError, decodeutf32stateful, 1, b'\x00\x00\xd8\x3d')
|
||||
self.assertEqual(decodeutf32stateful(1, b'\x00\x00\xd8\x3d', 'replace'), (1, '\ufffd', 4))
|
||||
|
||||
self.assertRaises(LookupError, decodeutf32stateful, -1, b'\xff\xff\xff\xff', 'foo')
|
||||
self.assertRaises(LookupError, decodeutf32stateful, 1, b'\xff\xff\xff\xff', 'foo')
|
||||
self.assertRaises(LookupError, decodeutf32stateful, 0, b'\xff\xff\xff\xff', 'foo')
|
||||
# TODO: Test PyUnicode_DecodeUTF32Stateful() with NULL as data and
|
||||
# negative size.
|
||||
# TODO: Test PyUnicode_DecodeUTF32Stateful() with NULL as the address of
|
||||
# "consumed".
|
||||
|
||||
def test_asutf32string(self):
|
||||
"""Test PyUnicode_AsUTF32String()"""
|
||||
asutf32string = _testlimitedcapi.unicode_asutf32string
|
||||
|
||||
for s in ['abc', '\xa1\xa2', '\u4f60\u597d', 'a\U0001f600']:
|
||||
self.assertEqual(asutf32string(s), s.encode('utf-32'))
|
||||
|
||||
self.assertRaises(UnicodeEncodeError, asutf32string, '\ud8ff')
|
||||
self.assertRaises(TypeError, asutf32string, b'abc')
|
||||
self.assertRaises(TypeError, asutf32string, [])
|
||||
# CRASHES asutf32string(NULL)
|
||||
|
||||
def test_decodelatin1(self):
|
||||
"""Test PyUnicode_DecodeLatin1()"""
|
||||
decodelatin1 = _testlimitedcapi.unicode_decodelatin1
|
||||
|
||||
self.assertEqual(decodelatin1(b'abc'), 'abc')
|
||||
self.assertEqual(decodelatin1(b'abc', 'strict'), 'abc')
|
||||
self.assertEqual(decodelatin1(b'\xa1\xa2'), '\xa1\xa2')
|
||||
self.assertEqual(decodelatin1(b'\xa1\xa2', 'strict'), '\xa1\xa2')
|
||||
# TODO: Test PyUnicode_DecodeLatin1() with NULL as data and
|
||||
# negative size.
|
||||
|
||||
def test_aslatin1string(self):
|
||||
"""Test PyUnicode_AsLatin1String()"""
|
||||
aslatin1string = _testlimitedcapi.unicode_aslatin1string
|
||||
|
||||
self.assertEqual(aslatin1string('abc'), b'abc')
|
||||
self.assertEqual(aslatin1string('\xa1\xa2'), b'\xa1\xa2')
|
||||
|
||||
self.assertRaises(UnicodeEncodeError, aslatin1string, '\u4f60')
|
||||
self.assertRaises(TypeError, aslatin1string, b'abc')
|
||||
self.assertRaises(TypeError, aslatin1string, [])
|
||||
# CRASHES aslatin1string(NULL)
|
||||
|
||||
def test_decodeascii(self):
|
||||
"""Test PyUnicode_DecodeASCII()"""
|
||||
decodeascii = _testlimitedcapi.unicode_decodeascii
|
||||
|
||||
self.assertEqual(decodeascii(b'abc'), 'abc')
|
||||
self.assertEqual(decodeascii(b'abc', 'strict'), 'abc')
|
||||
|
||||
self.assertRaises(UnicodeDecodeError, decodeascii, b'\xff')
|
||||
self.assertEqual(decodeascii(b'a\xff', 'replace'), 'a\ufffd')
|
||||
self.assertEqual(decodeascii(b'a\xffb', 'replace'), 'a\ufffdb')
|
||||
|
||||
self.assertRaises(LookupError, decodeascii, b'a\xff', 'foo')
|
||||
# TODO: Test PyUnicode_DecodeASCII() with NULL as data and
|
||||
# negative size.
|
||||
|
||||
def test_asasciistring(self):
|
||||
"""Test PyUnicode_AsASCIIString()"""
|
||||
asasciistring = _testlimitedcapi.unicode_asasciistring
|
||||
|
||||
self.assertEqual(asasciistring('abc'), b'abc')
|
||||
|
||||
self.assertRaises(UnicodeEncodeError, asasciistring, '\x80')
|
||||
self.assertRaises(TypeError, asasciistring, b'abc')
|
||||
self.assertRaises(TypeError, asasciistring, [])
|
||||
# CRASHES asasciistring(NULL)
|
||||
|
||||
def test_decodecharmap(self):
|
||||
"""Test PyUnicode_DecodeCharmap()"""
|
||||
decodecharmap = _testlimitedcapi.unicode_decodecharmap
|
||||
|
||||
self.assertEqual(decodecharmap(b'\3\0\7', {0: 'a', 3: 'b', 7: 'c'}), 'bac')
|
||||
self.assertEqual(decodecharmap(b'\1\0\2', ['a', 'b', 'c']), 'bac')
|
||||
self.assertEqual(decodecharmap(b'\1\0\2', 'abc'), 'bac')
|
||||
self.assertEqual(decodecharmap(b'\1\0\2', ['\xa1', '\xa2', '\xa3']), '\xa2\xa1\xa3')
|
||||
self.assertEqual(decodecharmap(b'\1\0\2', ['\u4f60', '\u597d', '\u4e16']), '\u597d\u4f60\u4e16')
|
||||
self.assertEqual(decodecharmap(b'\1\0\2', ['\U0001f600', '\U0001f601', '\U0001f602']), '\U0001f601\U0001f600\U0001f602')
|
||||
|
||||
self.assertEqual(decodecharmap(b'\1\0\2', [97, 98, 99]), 'bac')
|
||||
self.assertEqual(decodecharmap(b'\1\0\2', ['', 'b', 'cd']), 'bcd')
|
||||
|
||||
self.assertRaises(UnicodeDecodeError, decodecharmap, b'\0', {})
|
||||
self.assertRaises(UnicodeDecodeError, decodecharmap, b'\0', {0: None})
|
||||
self.assertEqual(decodecharmap(b'\1\0\2', [None, 'b', 'c'], 'replace'), 'b\ufffdc')
|
||||
self.assertEqual(decodecharmap(b'\1\0\2\xff', NULL), '\1\0\2\xff')
|
||||
self.assertRaises(TypeError, decodecharmap, b'\0', 42)
|
||||
|
||||
# TODO: Test PyUnicode_DecodeCharmap() with NULL as data and
|
||||
# negative size.
|
||||
|
||||
def test_ascharmapstring(self):
|
||||
"""Test PyUnicode_AsCharmapString()"""
|
||||
ascharmapstring = _testlimitedcapi.unicode_ascharmapstring
|
||||
|
||||
self.assertEqual(ascharmapstring('abc', {97: 3, 98: 0, 99: 7}), b'\3\0\7')
|
||||
self.assertEqual(ascharmapstring('\xa1\xa2\xa3', {0xa1: 3, 0xa2: 0, 0xa3: 7}), b'\3\0\7')
|
||||
self.assertEqual(ascharmapstring('\u4f60\u597d\u4e16', {0x4f60: 3, 0x597d: 0, 0x4e16: 7}), b'\3\0\7')
|
||||
self.assertEqual(ascharmapstring('\U0001f600\U0001f601\U0001f602', {0x1f600: 3, 0x1f601: 0, 0x1f602: 7}), b'\3\0\7')
|
||||
self.assertEqual(ascharmapstring('abc', {97: 3, 98: b'', 99: b'spam'}), b'\3spam')
|
||||
|
||||
self.assertRaises(UnicodeEncodeError, ascharmapstring, 'a', {})
|
||||
self.assertRaises(UnicodeEncodeError, ascharmapstring, 'a', {97: None})
|
||||
self.assertRaises(TypeError, ascharmapstring, b'a', {})
|
||||
self.assertRaises(TypeError, ascharmapstring, [], {})
|
||||
self.assertRaises(TypeError, ascharmapstring, 'a', NULL)
|
||||
# CRASHES ascharmapstring(NULL, {})
|
||||
|
||||
def test_decodeunicodeescape(self):
|
||||
"""Test PyUnicode_DecodeUnicodeEscape()"""
|
||||
decodeunicodeescape = _testlimitedcapi.unicode_decodeunicodeescape
|
||||
|
||||
self.assertEqual(decodeunicodeescape(b'abc'), 'abc')
|
||||
self.assertEqual(decodeunicodeescape(br'\t\n\r\x0b\x0c\x00\\'), '\t\n\r\v\f\0\\')
|
||||
self.assertEqual(decodeunicodeescape(b'\t\n\r\x0b\x0c\x00'), '\t\n\r\v\f\0')
|
||||
self.assertEqual(decodeunicodeescape(br'\xa1\xa2'), '\xa1\xa2')
|
||||
self.assertEqual(decodeunicodeescape(b'\xa1\xa2'), '\xa1\xa2')
|
||||
self.assertEqual(decodeunicodeescape(br'\u4f60\u597d'), '\u4f60\u597d')
|
||||
self.assertEqual(decodeunicodeescape(br'\U0001f600'), '\U0001f600')
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
self.assertEqual(decodeunicodeescape(br'\z'), r'\z')
|
||||
|
||||
for b in b'\\', br'\xa', br'\u4f6', br'\U0001f60':
|
||||
self.assertRaises(UnicodeDecodeError, decodeunicodeescape, b)
|
||||
self.assertRaises(UnicodeDecodeError, decodeunicodeescape, b, 'strict')
|
||||
self.assertEqual(decodeunicodeescape(br'x\U0001f60', 'replace'), 'x\ufffd')
|
||||
self.assertEqual(decodeunicodeescape(br'x\U0001f60y', 'replace'), 'x\ufffdy')
|
||||
|
||||
self.assertRaises(LookupError, decodeunicodeescape, b'\\', 'foo')
|
||||
# TODO: Test PyUnicode_DecodeUnicodeEscape() with NULL as data and
|
||||
# negative size.
|
||||
|
||||
def test_asunicodeescapestring(self):
|
||||
"""Test PyUnicode_AsUnicodeEscapeString()"""
|
||||
asunicodeescapestring = _testlimitedcapi.unicode_asunicodeescapestring
|
||||
|
||||
self.assertEqual(asunicodeescapestring('abc'), b'abc')
|
||||
self.assertEqual(asunicodeescapestring('\t\n\r\v\f\0\\'), br'\t\n\r\x0b\x0c\x00\\')
|
||||
self.assertEqual(asunicodeescapestring('\xa1\xa2'), br'\xa1\xa2')
|
||||
self.assertEqual(asunicodeescapestring('\u4f60\u597d'), br'\u4f60\u597d')
|
||||
self.assertEqual(asunicodeescapestring('\U0001f600'), br'\U0001f600')
|
||||
|
||||
self.assertRaises(TypeError, asunicodeescapestring, b'abc')
|
||||
self.assertRaises(TypeError, asunicodeescapestring, [])
|
||||
# CRASHES asunicodeescapestring(NULL)
|
||||
|
||||
def test_decoderawunicodeescape(self):
|
||||
"""Test PyUnicode_DecodeRawUnicodeEscape()"""
|
||||
decoderawunicodeescape = _testlimitedcapi.unicode_decoderawunicodeescape
|
||||
|
||||
self.assertEqual(decoderawunicodeescape(b'abc'), 'abc')
|
||||
self.assertEqual(decoderawunicodeescape(b'\t\n\r\v\f\0\\'), '\t\n\r\v\f\0\\')
|
||||
self.assertEqual(decoderawunicodeescape(b'\xa1\xa2'), '\xa1\xa2')
|
||||
self.assertEqual(decoderawunicodeescape(br'\u4f60\u597d'), '\u4f60\u597d')
|
||||
self.assertEqual(decoderawunicodeescape(br'\U0001f600'), '\U0001f600')
|
||||
self.assertEqual(decoderawunicodeescape(br'\xa1\xa2'), r'\xa1\xa2')
|
||||
self.assertEqual(decoderawunicodeescape(br'\z'), r'\z')
|
||||
|
||||
for b in br'\u4f6', br'\U0001f60':
|
||||
self.assertRaises(UnicodeDecodeError, decoderawunicodeescape, b)
|
||||
self.assertRaises(UnicodeDecodeError, decoderawunicodeescape, b, 'strict')
|
||||
self.assertEqual(decoderawunicodeescape(br'x\U0001f60', 'replace'), 'x\ufffd')
|
||||
self.assertEqual(decoderawunicodeescape(br'x\U0001f60y', 'replace'), 'x\ufffdy')
|
||||
|
||||
self.assertRaises(LookupError, decoderawunicodeescape, br'\U0001f60', 'foo')
|
||||
# TODO: Test PyUnicode_DecodeRawUnicodeEscape() with NULL as data and
|
||||
# negative size.
|
||||
|
||||
def test_asrawunicodeescapestring(self):
|
||||
"""Test PyUnicode_AsRawUnicodeEscapeString()"""
|
||||
asrawunicodeescapestring = _testlimitedcapi.unicode_asrawunicodeescapestring
|
||||
|
||||
self.assertEqual(asrawunicodeescapestring('abc'), b'abc')
|
||||
self.assertEqual(asrawunicodeescapestring('\t\n\r\v\f\0\\'), b'\t\n\r\v\f\0\\')
|
||||
self.assertEqual(asrawunicodeescapestring('\xa1\xa2'), b'\xa1\xa2')
|
||||
self.assertEqual(asrawunicodeescapestring('\u4f60\u597d'), br'\u4f60\u597d')
|
||||
self.assertEqual(asrawunicodeescapestring('\U0001f600'), br'\U0001f600')
|
||||
|
||||
self.assertRaises(TypeError, asrawunicodeescapestring, b'abc')
|
||||
self.assertRaises(TypeError, asrawunicodeescapestring, [])
|
||||
# CRASHES asrawunicodeescapestring(NULL)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
251
Dependencies/Python/Lib/test/test_capi/test_complex.py
vendored
Normal file
251
Dependencies/Python/Lib/test/test_capi/test_complex.py
vendored
Normal file
@ -0,0 +1,251 @@
|
||||
from math import isnan
|
||||
import errno
|
||||
import unittest
|
||||
import warnings
|
||||
|
||||
from test.test_capi.test_getargs import (BadComplex, BadComplex2, Complex,
|
||||
FloatSubclass, Float, BadFloat,
|
||||
BadFloat2, ComplexSubclass)
|
||||
from test.support import import_helper
|
||||
|
||||
|
||||
_testcapi = import_helper.import_module('_testcapi')
|
||||
_testlimitedcapi = import_helper.import_module('_testlimitedcapi')
|
||||
|
||||
NULL = None
|
||||
INF = float("inf")
|
||||
NAN = float("nan")
|
||||
DBL_MAX = _testcapi.DBL_MAX
|
||||
|
||||
|
||||
class BadComplex3:
|
||||
def __complex__(self):
|
||||
raise RuntimeError
|
||||
|
||||
|
||||
class CAPIComplexTest(unittest.TestCase):
|
||||
def test_check(self):
|
||||
# Test PyComplex_Check()
|
||||
check = _testlimitedcapi.complex_check
|
||||
|
||||
self.assertTrue(check(1+2j))
|
||||
self.assertTrue(check(ComplexSubclass(1+2j)))
|
||||
self.assertFalse(check(Complex()))
|
||||
self.assertFalse(check(3))
|
||||
self.assertFalse(check(3.0))
|
||||
self.assertFalse(check(object()))
|
||||
|
||||
# CRASHES check(NULL)
|
||||
|
||||
def test_checkexact(self):
|
||||
# PyComplex_CheckExact()
|
||||
checkexact = _testlimitedcapi.complex_checkexact
|
||||
|
||||
self.assertTrue(checkexact(1+2j))
|
||||
self.assertFalse(checkexact(ComplexSubclass(1+2j)))
|
||||
self.assertFalse(checkexact(Complex()))
|
||||
self.assertFalse(checkexact(3))
|
||||
self.assertFalse(checkexact(3.0))
|
||||
self.assertFalse(checkexact(object()))
|
||||
|
||||
# CRASHES checkexact(NULL)
|
||||
|
||||
def test_fromccomplex(self):
|
||||
# Test PyComplex_FromCComplex()
|
||||
fromccomplex = _testcapi.complex_fromccomplex
|
||||
|
||||
self.assertEqual(fromccomplex(1+2j), 1.0+2.0j)
|
||||
|
||||
def test_fromdoubles(self):
|
||||
# Test PyComplex_FromDoubles()
|
||||
fromdoubles = _testlimitedcapi.complex_fromdoubles
|
||||
|
||||
self.assertEqual(fromdoubles(1.0, 2.0), 1.0+2.0j)
|
||||
|
||||
def test_realasdouble(self):
|
||||
# Test PyComplex_RealAsDouble()
|
||||
realasdouble = _testlimitedcapi.complex_realasdouble
|
||||
|
||||
self.assertEqual(realasdouble(1+2j), 1.0)
|
||||
self.assertEqual(realasdouble(-1+0j), -1.0)
|
||||
self.assertEqual(realasdouble(4.25), 4.25)
|
||||
self.assertEqual(realasdouble(-1.0), -1.0)
|
||||
self.assertEqual(realasdouble(42), 42.)
|
||||
self.assertEqual(realasdouble(-1), -1.0)
|
||||
|
||||
# Test subclasses of complex/float
|
||||
self.assertEqual(realasdouble(ComplexSubclass(1+2j)), 1.0)
|
||||
self.assertEqual(realasdouble(FloatSubclass(4.25)), 4.25)
|
||||
|
||||
# Test types with __complex__ dunder method
|
||||
self.assertEqual(realasdouble(Complex()), 4.25)
|
||||
self.assertRaises(TypeError, realasdouble, BadComplex())
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
self.assertEqual(realasdouble(BadComplex2()), 4.25)
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("error", DeprecationWarning)
|
||||
self.assertRaises(DeprecationWarning, realasdouble, BadComplex2())
|
||||
self.assertRaises(RuntimeError, realasdouble, BadComplex3())
|
||||
|
||||
# Test types with __float__ dunder method
|
||||
self.assertEqual(realasdouble(Float()), 4.25)
|
||||
self.assertRaises(TypeError, realasdouble, BadFloat())
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
self.assertEqual(realasdouble(BadFloat2()), 4.25)
|
||||
|
||||
self.assertRaises(TypeError, realasdouble, object())
|
||||
|
||||
# CRASHES realasdouble(NULL)
|
||||
|
||||
def test_imagasdouble(self):
|
||||
# Test PyComplex_ImagAsDouble()
|
||||
imagasdouble = _testlimitedcapi.complex_imagasdouble
|
||||
|
||||
self.assertEqual(imagasdouble(1+2j), 2.0)
|
||||
self.assertEqual(imagasdouble(1-1j), -1.0)
|
||||
self.assertEqual(imagasdouble(4.25), 0.0)
|
||||
self.assertEqual(imagasdouble(42), 0.0)
|
||||
|
||||
# Test subclasses of complex/float
|
||||
self.assertEqual(imagasdouble(ComplexSubclass(1+2j)), 2.0)
|
||||
self.assertEqual(imagasdouble(FloatSubclass(4.25)), 0.0)
|
||||
|
||||
# Test types with __complex__ dunder method
|
||||
self.assertEqual(imagasdouble(Complex()), 0.5)
|
||||
self.assertRaises(TypeError, imagasdouble, BadComplex())
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
self.assertEqual(imagasdouble(BadComplex2()), 0.5)
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("error", DeprecationWarning)
|
||||
self.assertRaises(DeprecationWarning, imagasdouble, BadComplex2())
|
||||
self.assertRaises(RuntimeError, imagasdouble, BadComplex3())
|
||||
|
||||
# Test types with __float__ dunder method
|
||||
self.assertEqual(imagasdouble(Float()), 0.0)
|
||||
self.assertRaises(TypeError, imagasdouble, BadFloat())
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
self.assertEqual(imagasdouble(BadFloat2()), 0.0)
|
||||
|
||||
self.assertRaises(TypeError, imagasdouble, object())
|
||||
|
||||
# CRASHES imagasdouble(NULL)
|
||||
|
||||
def test_asccomplex(self):
|
||||
# Test PyComplex_AsCComplex()
|
||||
asccomplex = _testcapi.complex_asccomplex
|
||||
|
||||
self.assertEqual(asccomplex(1+2j), 1.0+2.0j)
|
||||
self.assertEqual(asccomplex(-1+2j), -1.0+2.0j)
|
||||
self.assertEqual(asccomplex(4.25), 4.25+0.0j)
|
||||
self.assertEqual(asccomplex(-1.0), -1.0+0.0j)
|
||||
self.assertEqual(asccomplex(42), 42+0j)
|
||||
self.assertEqual(asccomplex(-1), -1.0+0.0j)
|
||||
|
||||
# Test subclasses of complex/float
|
||||
self.assertEqual(asccomplex(ComplexSubclass(1+2j)), 1.0+2.0j)
|
||||
self.assertEqual(asccomplex(FloatSubclass(4.25)), 4.25+0.0j)
|
||||
|
||||
# Test types with __complex__ dunder method
|
||||
self.assertEqual(asccomplex(Complex()), 4.25+0.5j)
|
||||
self.assertRaises(TypeError, asccomplex, BadComplex())
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
self.assertEqual(asccomplex(BadComplex2()), 4.25+0.5j)
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("error", DeprecationWarning)
|
||||
self.assertRaises(DeprecationWarning, asccomplex, BadComplex2())
|
||||
self.assertRaises(RuntimeError, asccomplex, BadComplex3())
|
||||
|
||||
# Test types with __float__ dunder method
|
||||
self.assertEqual(asccomplex(Float()), 4.25+0.0j)
|
||||
self.assertRaises(TypeError, asccomplex, BadFloat())
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
self.assertEqual(asccomplex(BadFloat2()), 4.25+0.0j)
|
||||
|
||||
self.assertRaises(TypeError, asccomplex, object())
|
||||
|
||||
# CRASHES asccomplex(NULL)
|
||||
|
||||
def test_py_c_sum(self):
|
||||
# Test _Py_c_sum()
|
||||
_py_c_sum = _testcapi._py_c_sum
|
||||
|
||||
self.assertEqual(_py_c_sum(1, 1j), (1+1j, 0))
|
||||
|
||||
def test_py_c_diff(self):
|
||||
# Test _Py_c_diff()
|
||||
_py_c_diff = _testcapi._py_c_diff
|
||||
|
||||
self.assertEqual(_py_c_diff(1, 1j), (1-1j, 0))
|
||||
|
||||
def test_py_c_neg(self):
|
||||
# Test _Py_c_neg()
|
||||
_py_c_neg = _testcapi._py_c_neg
|
||||
|
||||
self.assertEqual(_py_c_neg(1+1j), -1-1j)
|
||||
|
||||
def test_py_c_prod(self):
|
||||
# Test _Py_c_prod()
|
||||
_py_c_prod = _testcapi._py_c_prod
|
||||
|
||||
self.assertEqual(_py_c_prod(2, 1j), (2j, 0))
|
||||
|
||||
def test_py_c_quot(self):
|
||||
# Test _Py_c_quot()
|
||||
_py_c_quot = _testcapi._py_c_quot
|
||||
|
||||
self.assertEqual(_py_c_quot(1, 1j), (-1j, 0))
|
||||
self.assertEqual(_py_c_quot(1, -1j), (1j, 0))
|
||||
self.assertEqual(_py_c_quot(1j, 2), (0.5j, 0))
|
||||
self.assertEqual(_py_c_quot(1j, -2), (-0.5j, 0))
|
||||
self.assertEqual(_py_c_quot(1, 2j), (-0.5j, 0))
|
||||
|
||||
z, e = _py_c_quot(NAN, 1j)
|
||||
self.assertTrue(isnan(z.real))
|
||||
self.assertTrue(isnan(z.imag))
|
||||
self.assertEqual(e, 0)
|
||||
|
||||
z, e = _py_c_quot(1j, NAN)
|
||||
self.assertTrue(isnan(z.real))
|
||||
self.assertTrue(isnan(z.imag))
|
||||
self.assertEqual(e, 0)
|
||||
|
||||
self.assertEqual(_py_c_quot(1, 0j)[1], errno.EDOM)
|
||||
|
||||
def test_py_c_pow(self):
|
||||
# Test _Py_c_pow()
|
||||
_py_c_pow = _testcapi._py_c_pow
|
||||
|
||||
self.assertEqual(_py_c_pow(1j, 0j), (1+0j, 0))
|
||||
self.assertEqual(_py_c_pow(1, 1j), (1+0j, 0))
|
||||
self.assertEqual(_py_c_pow(0j, 1), (0j, 0))
|
||||
self.assertAlmostEqual(_py_c_pow(1j, 2)[0], -1.0+0j)
|
||||
|
||||
r, e = _py_c_pow(1+1j, -1)
|
||||
self.assertAlmostEqual(r, 0.5-0.5j)
|
||||
self.assertEqual(e, 0)
|
||||
|
||||
self.assertEqual(_py_c_pow(0j, -1)[1], errno.EDOM)
|
||||
self.assertEqual(_py_c_pow(0j, 1j)[1], errno.EDOM)
|
||||
self.assertEqual(_py_c_pow(*[DBL_MAX+1j]*2)[0], complex(*[INF]*2))
|
||||
|
||||
|
||||
def test_py_c_abs(self):
|
||||
# Test _Py_c_abs()
|
||||
_py_c_abs = _testcapi._py_c_abs
|
||||
|
||||
self.assertEqual(_py_c_abs(-1), (1.0, 0))
|
||||
self.assertEqual(_py_c_abs(1j), (1.0, 0))
|
||||
|
||||
self.assertEqual(_py_c_abs(complex('+inf+1j')), (INF, 0))
|
||||
self.assertEqual(_py_c_abs(complex('-inf+1j')), (INF, 0))
|
||||
self.assertEqual(_py_c_abs(complex('1.25+infj')), (INF, 0))
|
||||
self.assertEqual(_py_c_abs(complex('1.25-infj')), (INF, 0))
|
||||
|
||||
self.assertTrue(isnan(_py_c_abs(complex('1.25+nanj'))[0]))
|
||||
self.assertTrue(isnan(_py_c_abs(complex('nan-1j'))[0]))
|
||||
|
||||
self.assertEqual(_py_c_abs(complex(*[DBL_MAX]*2))[1], errno.ERANGE)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
550
Dependencies/Python/Lib/test/test_capi/test_dict.py
vendored
Normal file
550
Dependencies/Python/Lib/test/test_capi/test_dict.py
vendored
Normal file
@ -0,0 +1,550 @@
|
||||
import unittest
|
||||
from collections import OrderedDict, UserDict
|
||||
from types import MappingProxyType
|
||||
from test import support
|
||||
from test.support import import_helper
|
||||
|
||||
|
||||
_testcapi = import_helper.import_module("_testcapi")
|
||||
_testlimitedcapi = import_helper.import_module("_testlimitedcapi")
|
||||
|
||||
|
||||
NULL = None
|
||||
INVALID_UTF8 = b'\xff'
|
||||
|
||||
class DictSubclass(dict):
|
||||
def __getitem__(self, key):
|
||||
raise RuntimeError('do not get evil')
|
||||
def __setitem__(self, key, value):
|
||||
raise RuntimeError('do not set evil')
|
||||
def __delitem__(self, key):
|
||||
raise RuntimeError('do not del evil')
|
||||
|
||||
def gen():
|
||||
yield 'a'
|
||||
yield 'b'
|
||||
yield 'c'
|
||||
|
||||
|
||||
class CAPITest(unittest.TestCase):
|
||||
|
||||
def test_dict_check(self):
|
||||
check = _testlimitedcapi.dict_check
|
||||
self.assertTrue(check({1: 2}))
|
||||
self.assertTrue(check(OrderedDict({1: 2})))
|
||||
self.assertFalse(check(UserDict({1: 2})))
|
||||
self.assertFalse(check([1, 2]))
|
||||
self.assertFalse(check(object()))
|
||||
# CRASHES check(NULL)
|
||||
|
||||
def test_dict_checkexact(self):
|
||||
check = _testlimitedcapi.dict_checkexact
|
||||
self.assertTrue(check({1: 2}))
|
||||
self.assertFalse(check(OrderedDict({1: 2})))
|
||||
self.assertFalse(check(UserDict({1: 2})))
|
||||
self.assertFalse(check([1, 2]))
|
||||
self.assertFalse(check(object()))
|
||||
# CRASHES check(NULL)
|
||||
|
||||
def test_dict_new(self):
|
||||
dict_new = _testlimitedcapi.dict_new
|
||||
dct = dict_new()
|
||||
self.assertEqual(dct, {})
|
||||
self.assertIs(type(dct), dict)
|
||||
dct2 = dict_new()
|
||||
self.assertIsNot(dct2, dct)
|
||||
|
||||
def test_dictproxy_new(self):
|
||||
dictproxy_new = _testlimitedcapi.dictproxy_new
|
||||
for dct in {1: 2}, OrderedDict({1: 2}), UserDict({1: 2}):
|
||||
proxy = dictproxy_new(dct)
|
||||
self.assertIs(type(proxy), MappingProxyType)
|
||||
self.assertEqual(proxy, dct)
|
||||
with self.assertRaises(TypeError):
|
||||
proxy[1] = 3
|
||||
self.assertEqual(proxy[1], 2)
|
||||
dct[1] = 4
|
||||
self.assertEqual(proxy[1], 4)
|
||||
|
||||
self.assertRaises(TypeError, dictproxy_new, [])
|
||||
self.assertRaises(TypeError, dictproxy_new, 42)
|
||||
# CRASHES dictproxy_new(NULL)
|
||||
|
||||
def test_dict_copy(self):
|
||||
copy = _testlimitedcapi.dict_copy
|
||||
for dct in {1: 2}, OrderedDict({1: 2}):
|
||||
dct_copy = copy(dct)
|
||||
self.assertIs(type(dct_copy), dict)
|
||||
self.assertEqual(dct_copy, dct)
|
||||
|
||||
self.assertRaises(SystemError, copy, UserDict())
|
||||
self.assertRaises(SystemError, copy, [])
|
||||
self.assertRaises(SystemError, copy, 42)
|
||||
self.assertRaises(SystemError, copy, NULL)
|
||||
|
||||
def test_dict_clear(self):
|
||||
clear = _testlimitedcapi.dict_clear
|
||||
dct = {1: 2}
|
||||
clear(dct)
|
||||
self.assertEqual(dct, {})
|
||||
|
||||
# NOTE: It is not safe to call it with OrderedDict.
|
||||
|
||||
# Has no effect for non-dicts.
|
||||
dct = UserDict({1: 2})
|
||||
clear(dct)
|
||||
self.assertEqual(dct, {1: 2})
|
||||
lst = [1, 2]
|
||||
clear(lst)
|
||||
self.assertEqual(lst, [1, 2])
|
||||
clear(object())
|
||||
|
||||
# CRASHES? clear(NULL)
|
||||
|
||||
def test_dict_size(self):
|
||||
size = _testlimitedcapi.dict_size
|
||||
self.assertEqual(size({1: 2}), 1)
|
||||
self.assertEqual(size(OrderedDict({1: 2})), 1)
|
||||
|
||||
self.assertRaises(SystemError, size, UserDict())
|
||||
self.assertRaises(SystemError, size, [])
|
||||
self.assertRaises(SystemError, size, 42)
|
||||
self.assertRaises(SystemError, size, object())
|
||||
self.assertRaises(SystemError, size, NULL)
|
||||
|
||||
def test_dict_getitem(self):
|
||||
getitem = _testlimitedcapi.dict_getitem
|
||||
dct = {'a': 1, '\U0001f40d': 2}
|
||||
self.assertEqual(getitem(dct, 'a'), 1)
|
||||
self.assertIs(getitem(dct, 'b'), KeyError)
|
||||
self.assertEqual(getitem(dct, '\U0001f40d'), 2)
|
||||
|
||||
dct2 = DictSubclass(dct)
|
||||
self.assertEqual(getitem(dct2, 'a'), 1)
|
||||
self.assertIs(getitem(dct2, 'b'), KeyError)
|
||||
|
||||
with support.catch_unraisable_exception() as cm:
|
||||
self.assertIs(getitem({}, []), KeyError) # unhashable
|
||||
self.assertEqual(cm.unraisable.exc_type, TypeError)
|
||||
self.assertEqual(str(cm.unraisable.exc_value),
|
||||
"unhashable type: 'list'")
|
||||
|
||||
self.assertIs(getitem(42, 'a'), KeyError)
|
||||
self.assertIs(getitem([1], 0), KeyError)
|
||||
# CRASHES getitem({}, NULL)
|
||||
# CRASHES getitem(NULL, 'a')
|
||||
|
||||
def test_dict_getitemstring(self):
|
||||
getitemstring = _testlimitedcapi.dict_getitemstring
|
||||
dct = {'a': 1, '\U0001f40d': 2}
|
||||
self.assertEqual(getitemstring(dct, b'a'), 1)
|
||||
self.assertIs(getitemstring(dct, b'b'), KeyError)
|
||||
self.assertEqual(getitemstring(dct, '\U0001f40d'.encode()), 2)
|
||||
|
||||
dct2 = DictSubclass(dct)
|
||||
self.assertEqual(getitemstring(dct2, b'a'), 1)
|
||||
self.assertIs(getitemstring(dct2, b'b'), KeyError)
|
||||
|
||||
with support.catch_unraisable_exception() as cm:
|
||||
self.assertIs(getitemstring({}, INVALID_UTF8), KeyError)
|
||||
self.assertEqual(cm.unraisable.exc_type, UnicodeDecodeError)
|
||||
self.assertRegex(str(cm.unraisable.exc_value),
|
||||
"'utf-8' codec can't decode")
|
||||
|
||||
self.assertIs(getitemstring(42, b'a'), KeyError)
|
||||
self.assertIs(getitemstring([], b'a'), KeyError)
|
||||
# CRASHES getitemstring({}, NULL)
|
||||
# CRASHES getitemstring(NULL, b'a')
|
||||
|
||||
def test_dict_getitemref(self):
|
||||
getitem = _testcapi.dict_getitemref
|
||||
dct = {'a': 1, '\U0001f40d': 2}
|
||||
self.assertEqual(getitem(dct, 'a'), 1)
|
||||
self.assertIs(getitem(dct, 'b'), KeyError)
|
||||
self.assertEqual(getitem(dct, '\U0001f40d'), 2)
|
||||
|
||||
dct2 = DictSubclass(dct)
|
||||
self.assertEqual(getitem(dct2, 'a'), 1)
|
||||
self.assertIs(getitem(dct2, 'b'), KeyError)
|
||||
|
||||
self.assertRaises(SystemError, getitem, 42, 'a')
|
||||
self.assertRaises(TypeError, getitem, {}, []) # unhashable
|
||||
self.assertRaises(SystemError, getitem, [], 1)
|
||||
self.assertRaises(SystemError, getitem, [], 'a')
|
||||
# CRASHES getitem({}, NULL)
|
||||
# CRASHES getitem(NULL, 'a')
|
||||
|
||||
def test_dict_getitemstringref(self):
|
||||
getitemstring = _testcapi.dict_getitemstringref
|
||||
dct = {'a': 1, '\U0001f40d': 2}
|
||||
self.assertEqual(getitemstring(dct, b'a'), 1)
|
||||
self.assertIs(getitemstring(dct, b'b'), KeyError)
|
||||
self.assertEqual(getitemstring(dct, '\U0001f40d'.encode()), 2)
|
||||
|
||||
dct2 = DictSubclass(dct)
|
||||
self.assertEqual(getitemstring(dct2, b'a'), 1)
|
||||
self.assertIs(getitemstring(dct2, b'b'), KeyError)
|
||||
|
||||
self.assertRaises(SystemError, getitemstring, 42, b'a')
|
||||
self.assertRaises(UnicodeDecodeError, getitemstring, {}, INVALID_UTF8)
|
||||
self.assertRaises(SystemError, getitemstring, [], b'a')
|
||||
# CRASHES getitemstring({}, NULL)
|
||||
# CRASHES getitemstring(NULL, b'a')
|
||||
|
||||
def test_dict_getitemwitherror(self):
|
||||
getitem = _testlimitedcapi.dict_getitemwitherror
|
||||
dct = {'a': 1, '\U0001f40d': 2}
|
||||
self.assertEqual(getitem(dct, 'a'), 1)
|
||||
self.assertIs(getitem(dct, 'b'), KeyError)
|
||||
self.assertEqual(getitem(dct, '\U0001f40d'), 2)
|
||||
|
||||
dct2 = DictSubclass(dct)
|
||||
self.assertEqual(getitem(dct2, 'a'), 1)
|
||||
self.assertIs(getitem(dct2, 'b'), KeyError)
|
||||
|
||||
self.assertRaises(SystemError, getitem, 42, 'a')
|
||||
self.assertRaises(TypeError, getitem, {}, []) # unhashable
|
||||
self.assertRaises(SystemError, getitem, [], 1)
|
||||
self.assertRaises(SystemError, getitem, [], 'a')
|
||||
# CRASHES getitem({}, NULL)
|
||||
# CRASHES getitem(NULL, 'a')
|
||||
|
||||
def test_dict_contains(self):
|
||||
contains = _testlimitedcapi.dict_contains
|
||||
dct = {'a': 1, '\U0001f40d': 2}
|
||||
self.assertTrue(contains(dct, 'a'))
|
||||
self.assertFalse(contains(dct, 'b'))
|
||||
self.assertTrue(contains(dct, '\U0001f40d'))
|
||||
|
||||
dct2 = DictSubclass(dct)
|
||||
self.assertTrue(contains(dct2, 'a'))
|
||||
self.assertFalse(contains(dct2, 'b'))
|
||||
|
||||
self.assertRaises(TypeError, contains, {}, []) # unhashable
|
||||
# CRASHES contains({}, NULL)
|
||||
# CRASHES contains(UserDict(), 'a')
|
||||
# CRASHES contains(42, 'a')
|
||||
# CRASHES contains(NULL, 'a')
|
||||
|
||||
def test_dict_contains_string(self):
|
||||
contains_string = _testcapi.dict_containsstring
|
||||
dct = {'a': 1, '\U0001f40d': 2}
|
||||
self.assertTrue(contains_string(dct, b'a'))
|
||||
self.assertFalse(contains_string(dct, b'b'))
|
||||
self.assertTrue(contains_string(dct, '\U0001f40d'.encode()))
|
||||
self.assertRaises(UnicodeDecodeError, contains_string, dct, INVALID_UTF8)
|
||||
|
||||
dct2 = DictSubclass(dct)
|
||||
self.assertTrue(contains_string(dct2, b'a'))
|
||||
self.assertFalse(contains_string(dct2, b'b'))
|
||||
|
||||
# CRASHES contains({}, NULL)
|
||||
# CRASHES contains(NULL, b'a')
|
||||
|
||||
def test_dict_setitem(self):
|
||||
setitem = _testlimitedcapi.dict_setitem
|
||||
dct = {}
|
||||
setitem(dct, 'a', 5)
|
||||
self.assertEqual(dct, {'a': 5})
|
||||
setitem(dct, '\U0001f40d', 8)
|
||||
self.assertEqual(dct, {'a': 5, '\U0001f40d': 8})
|
||||
|
||||
dct2 = DictSubclass()
|
||||
setitem(dct2, 'a', 5)
|
||||
self.assertEqual(dct2, {'a': 5})
|
||||
|
||||
self.assertRaises(TypeError, setitem, {}, [], 5) # unhashable
|
||||
self.assertRaises(SystemError, setitem, UserDict(), 'a', 5)
|
||||
self.assertRaises(SystemError, setitem, [1], 0, 5)
|
||||
self.assertRaises(SystemError, setitem, 42, 'a', 5)
|
||||
# CRASHES setitem({}, NULL, 5)
|
||||
# CRASHES setitem({}, 'a', NULL)
|
||||
# CRASHES setitem(NULL, 'a', 5)
|
||||
|
||||
def test_dict_setitemstring(self):
|
||||
setitemstring = _testlimitedcapi.dict_setitemstring
|
||||
dct = {}
|
||||
setitemstring(dct, b'a', 5)
|
||||
self.assertEqual(dct, {'a': 5})
|
||||
setitemstring(dct, '\U0001f40d'.encode(), 8)
|
||||
self.assertEqual(dct, {'a': 5, '\U0001f40d': 8})
|
||||
|
||||
dct2 = DictSubclass()
|
||||
setitemstring(dct2, b'a', 5)
|
||||
self.assertEqual(dct2, {'a': 5})
|
||||
|
||||
self.assertRaises(UnicodeDecodeError, setitemstring, {}, INVALID_UTF8, 5)
|
||||
self.assertRaises(SystemError, setitemstring, UserDict(), b'a', 5)
|
||||
self.assertRaises(SystemError, setitemstring, 42, b'a', 5)
|
||||
# CRASHES setitemstring({}, NULL, 5)
|
||||
# CRASHES setitemstring({}, b'a', NULL)
|
||||
# CRASHES setitemstring(NULL, b'a', 5)
|
||||
|
||||
def test_dict_delitem(self):
|
||||
delitem = _testlimitedcapi.dict_delitem
|
||||
dct = {'a': 1, 'c': 2, '\U0001f40d': 3}
|
||||
delitem(dct, 'a')
|
||||
self.assertEqual(dct, {'c': 2, '\U0001f40d': 3})
|
||||
self.assertRaises(KeyError, delitem, dct, 'b')
|
||||
delitem(dct, '\U0001f40d')
|
||||
self.assertEqual(dct, {'c': 2})
|
||||
|
||||
dct2 = DictSubclass({'a': 1, 'c': 2})
|
||||
delitem(dct2, 'a')
|
||||
self.assertEqual(dct2, {'c': 2})
|
||||
self.assertRaises(KeyError, delitem, dct2, 'b')
|
||||
|
||||
self.assertRaises(TypeError, delitem, {}, []) # unhashable
|
||||
self.assertRaises(SystemError, delitem, UserDict({'a': 1}), 'a')
|
||||
self.assertRaises(SystemError, delitem, [1], 0)
|
||||
self.assertRaises(SystemError, delitem, 42, 'a')
|
||||
# CRASHES delitem({}, NULL)
|
||||
# CRASHES delitem(NULL, 'a')
|
||||
|
||||
def test_dict_delitemstring(self):
|
||||
delitemstring = _testlimitedcapi.dict_delitemstring
|
||||
dct = {'a': 1, 'c': 2, '\U0001f40d': 3}
|
||||
delitemstring(dct, b'a')
|
||||
self.assertEqual(dct, {'c': 2, '\U0001f40d': 3})
|
||||
self.assertRaises(KeyError, delitemstring, dct, b'b')
|
||||
delitemstring(dct, '\U0001f40d'.encode())
|
||||
self.assertEqual(dct, {'c': 2})
|
||||
|
||||
dct2 = DictSubclass({'a': 1, 'c': 2})
|
||||
delitemstring(dct2, b'a')
|
||||
self.assertEqual(dct2, {'c': 2})
|
||||
self.assertRaises(KeyError, delitemstring, dct2, b'b')
|
||||
|
||||
self.assertRaises(UnicodeDecodeError, delitemstring, {}, INVALID_UTF8)
|
||||
self.assertRaises(SystemError, delitemstring, UserDict({'a': 1}), b'a')
|
||||
self.assertRaises(SystemError, delitemstring, 42, b'a')
|
||||
# CRASHES delitemstring({}, NULL)
|
||||
# CRASHES delitemstring(NULL, b'a')
|
||||
|
||||
def test_dict_setdefault(self):
|
||||
setdefault = _testcapi.dict_setdefault
|
||||
dct = {}
|
||||
self.assertEqual(setdefault(dct, 'a', 5), 5)
|
||||
self.assertEqual(dct, {'a': 5})
|
||||
self.assertEqual(setdefault(dct, 'a', 8), 5)
|
||||
self.assertEqual(dct, {'a': 5})
|
||||
|
||||
dct2 = DictSubclass()
|
||||
self.assertEqual(setdefault(dct2, 'a', 5), 5)
|
||||
self.assertEqual(dct2, {'a': 5})
|
||||
self.assertEqual(setdefault(dct2, 'a', 8), 5)
|
||||
self.assertEqual(dct2, {'a': 5})
|
||||
|
||||
self.assertRaises(TypeError, setdefault, {}, [], 5) # unhashable
|
||||
self.assertRaises(SystemError, setdefault, UserDict(), 'a', 5)
|
||||
self.assertRaises(SystemError, setdefault, [1], 0, 5)
|
||||
self.assertRaises(SystemError, setdefault, 42, 'a', 5)
|
||||
# CRASHES setdefault({}, NULL, 5)
|
||||
# CRASHES setdefault({}, 'a', NULL)
|
||||
# CRASHES setdefault(NULL, 'a', 5)
|
||||
|
||||
def test_dict_setdefaultref(self):
|
||||
setdefault = _testcapi.dict_setdefaultref
|
||||
dct = {}
|
||||
self.assertEqual(setdefault(dct, 'a', 5), 5)
|
||||
self.assertEqual(dct, {'a': 5})
|
||||
self.assertEqual(setdefault(dct, 'a', 8), 5)
|
||||
self.assertEqual(dct, {'a': 5})
|
||||
|
||||
dct2 = DictSubclass()
|
||||
self.assertEqual(setdefault(dct2, 'a', 5), 5)
|
||||
self.assertEqual(dct2, {'a': 5})
|
||||
self.assertEqual(setdefault(dct2, 'a', 8), 5)
|
||||
self.assertEqual(dct2, {'a': 5})
|
||||
|
||||
self.assertRaises(TypeError, setdefault, {}, [], 5) # unhashable
|
||||
self.assertRaises(SystemError, setdefault, UserDict(), 'a', 5)
|
||||
self.assertRaises(SystemError, setdefault, [1], 0, 5)
|
||||
self.assertRaises(SystemError, setdefault, 42, 'a', 5)
|
||||
# CRASHES setdefault({}, NULL, 5)
|
||||
# CRASHES setdefault({}, 'a', NULL)
|
||||
# CRASHES setdefault(NULL, 'a', 5)
|
||||
|
||||
def test_mapping_keys_valuesitems(self):
|
||||
class BadMapping(dict):
|
||||
def keys(self):
|
||||
return None
|
||||
def values(self):
|
||||
return None
|
||||
def items(self):
|
||||
return None
|
||||
dict_obj = {'foo': 1, 'bar': 2, 'spam': 3}
|
||||
for mapping in [dict_obj, DictSubclass(dict_obj), BadMapping(dict_obj)]:
|
||||
self.assertListEqual(_testlimitedcapi.dict_keys(mapping),
|
||||
list(dict_obj.keys()))
|
||||
self.assertListEqual(_testlimitedcapi.dict_values(mapping),
|
||||
list(dict_obj.values()))
|
||||
self.assertListEqual(_testlimitedcapi.dict_items(mapping),
|
||||
list(dict_obj.items()))
|
||||
|
||||
def test_dict_keys_valuesitems_bad_arg(self):
|
||||
for mapping in UserDict(), [], object():
|
||||
self.assertRaises(SystemError, _testlimitedcapi.dict_keys, mapping)
|
||||
self.assertRaises(SystemError, _testlimitedcapi.dict_values, mapping)
|
||||
self.assertRaises(SystemError, _testlimitedcapi.dict_items, mapping)
|
||||
|
||||
def test_dict_next(self):
|
||||
dict_next = _testlimitedcapi.dict_next
|
||||
self.assertIsNone(dict_next({}, 0))
|
||||
dct = {'a': 1, 'b': 2, 'c': 3}
|
||||
pos = 0
|
||||
pairs = []
|
||||
while True:
|
||||
res = dict_next(dct, pos)
|
||||
if res is None:
|
||||
break
|
||||
rc, pos, key, value = res
|
||||
self.assertEqual(rc, 1)
|
||||
pairs.append((key, value))
|
||||
self.assertEqual(pairs, list(dct.items()))
|
||||
|
||||
# CRASHES dict_next(NULL, 0)
|
||||
|
||||
def test_dict_update(self):
|
||||
update = _testlimitedcapi.dict_update
|
||||
for cls1 in dict, DictSubclass:
|
||||
for cls2 in dict, DictSubclass, UserDict:
|
||||
dct = cls1({'a': 1, 'b': 2})
|
||||
update(dct, cls2({'b': 3, 'c': 4}))
|
||||
self.assertEqual(dct, {'a': 1, 'b': 3, 'c': 4})
|
||||
|
||||
self.assertRaises(AttributeError, update, {}, [])
|
||||
self.assertRaises(AttributeError, update, {}, 42)
|
||||
self.assertRaises(SystemError, update, UserDict(), {})
|
||||
self.assertRaises(SystemError, update, 42, {})
|
||||
self.assertRaises(SystemError, update, {}, NULL)
|
||||
self.assertRaises(SystemError, update, NULL, {})
|
||||
|
||||
def test_dict_merge(self):
|
||||
merge = _testlimitedcapi.dict_merge
|
||||
for cls1 in dict, DictSubclass:
|
||||
for cls2 in dict, DictSubclass, UserDict:
|
||||
dct = cls1({'a': 1, 'b': 2})
|
||||
merge(dct, cls2({'b': 3, 'c': 4}), 0)
|
||||
self.assertEqual(dct, {'a': 1, 'b': 2, 'c': 4})
|
||||
dct = cls1({'a': 1, 'b': 2})
|
||||
merge(dct, cls2({'b': 3, 'c': 4}), 1)
|
||||
self.assertEqual(dct, {'a': 1, 'b': 3, 'c': 4})
|
||||
|
||||
self.assertRaises(AttributeError, merge, {}, [], 0)
|
||||
self.assertRaises(AttributeError, merge, {}, 42, 0)
|
||||
self.assertRaises(SystemError, merge, UserDict(), {}, 0)
|
||||
self.assertRaises(SystemError, merge, 42, {}, 0)
|
||||
self.assertRaises(SystemError, merge, {}, NULL, 0)
|
||||
self.assertRaises(SystemError, merge, NULL, {}, 0)
|
||||
|
||||
def test_dict_mergefromseq2(self):
|
||||
mergefromseq2 = _testlimitedcapi.dict_mergefromseq2
|
||||
for cls1 in dict, DictSubclass:
|
||||
for cls2 in list, iter:
|
||||
dct = cls1({'a': 1, 'b': 2})
|
||||
mergefromseq2(dct, cls2([('b', 3), ('c', 4)]), 0)
|
||||
self.assertEqual(dct, {'a': 1, 'b': 2, 'c': 4})
|
||||
dct = cls1({'a': 1, 'b': 2})
|
||||
mergefromseq2(dct, cls2([('b', 3), ('c', 4)]), 1)
|
||||
self.assertEqual(dct, {'a': 1, 'b': 3, 'c': 4})
|
||||
|
||||
self.assertRaises(ValueError, mergefromseq2, {}, [(1,)], 0)
|
||||
self.assertRaises(ValueError, mergefromseq2, {}, [(1, 2, 3)], 0)
|
||||
self.assertRaises(TypeError, mergefromseq2, {}, [1], 0)
|
||||
self.assertRaises(TypeError, mergefromseq2, {}, 42, 0)
|
||||
# CRASHES mergefromseq2(UserDict(), [], 0)
|
||||
# CRASHES mergefromseq2(42, [], 0)
|
||||
# CRASHES mergefromseq2({}, NULL, 0)
|
||||
# CRASHES mergefromseq2(NULL, {}, 0)
|
||||
|
||||
def test_dict_pop(self):
|
||||
# Test PyDict_Pop()
|
||||
dict_pop = _testcapi.dict_pop
|
||||
dict_pop_null = _testcapi.dict_pop_null
|
||||
|
||||
# key present, get removed value
|
||||
mydict = {"key": "value", "key2": "value2"}
|
||||
self.assertEqual(dict_pop(mydict, "key"), (1, "value"))
|
||||
self.assertEqual(mydict, {"key2": "value2"})
|
||||
self.assertEqual(dict_pop(mydict, "key2"), (1, "value2"))
|
||||
self.assertEqual(mydict, {})
|
||||
|
||||
# key present, ignore removed value
|
||||
mydict = {"key": "value", "key2": "value2"}
|
||||
self.assertEqual(dict_pop_null(mydict, "key"), 1)
|
||||
self.assertEqual(mydict, {"key2": "value2"})
|
||||
self.assertEqual(dict_pop_null(mydict, "key2"), 1)
|
||||
self.assertEqual(mydict, {})
|
||||
|
||||
# key missing, expect removed value; empty dict has a fast path
|
||||
self.assertEqual(dict_pop({}, "key"), (0, NULL))
|
||||
self.assertEqual(dict_pop({"a": 1}, "key"), (0, NULL))
|
||||
|
||||
# key missing, ignored removed value; empty dict has a fast path
|
||||
self.assertEqual(dict_pop_null({}, "key"), 0)
|
||||
self.assertEqual(dict_pop_null({"a": 1}, "key"), 0)
|
||||
|
||||
# dict error
|
||||
not_dict = UserDict({1: 2})
|
||||
self.assertRaises(SystemError, dict_pop, not_dict, "key")
|
||||
self.assertRaises(SystemError, dict_pop_null, not_dict, "key")
|
||||
|
||||
# key error; don't hash key if dict is empty
|
||||
not_hashable_key = ["list"]
|
||||
self.assertEqual(dict_pop({}, not_hashable_key), (0, NULL))
|
||||
with self.assertRaises(TypeError):
|
||||
dict_pop({'key': 1}, not_hashable_key)
|
||||
dict_pop({}, NULL) # key is not checked if dict is empty
|
||||
|
||||
# CRASHES dict_pop(NULL, "key")
|
||||
# CRASHES dict_pop({"a": 1}, NULL)
|
||||
|
||||
def test_dict_popstring(self):
|
||||
# Test PyDict_PopString()
|
||||
dict_popstring = _testcapi.dict_popstring
|
||||
dict_popstring_null = _testcapi.dict_popstring_null
|
||||
|
||||
# key present, get removed value
|
||||
mydict = {"key": "value", "key2": "value2"}
|
||||
self.assertEqual(dict_popstring(mydict, "key"), (1, "value"))
|
||||
self.assertEqual(mydict, {"key2": "value2"})
|
||||
self.assertEqual(dict_popstring(mydict, "key2"), (1, "value2"))
|
||||
self.assertEqual(mydict, {})
|
||||
|
||||
# key present, ignore removed value
|
||||
mydict = {"key": "value", "key2": "value2"}
|
||||
self.assertEqual(dict_popstring_null(mydict, "key"), 1)
|
||||
self.assertEqual(mydict, {"key2": "value2"})
|
||||
self.assertEqual(dict_popstring_null(mydict, "key2"), 1)
|
||||
self.assertEqual(mydict, {})
|
||||
|
||||
# key missing; empty dict has a fast path
|
||||
self.assertEqual(dict_popstring({}, "key"), (0, NULL))
|
||||
self.assertEqual(dict_popstring_null({}, "key"), 0)
|
||||
self.assertEqual(dict_popstring({"a": 1}, "key"), (0, NULL))
|
||||
self.assertEqual(dict_popstring_null({"a": 1}, "key"), 0)
|
||||
|
||||
# non-ASCII key
|
||||
non_ascii = '\U0001f40d'
|
||||
dct = {'\U0001f40d': 123}
|
||||
self.assertEqual(dict_popstring(dct, '\U0001f40d'.encode()), (1, 123))
|
||||
dct = {'\U0001f40d': 123}
|
||||
self.assertEqual(dict_popstring_null(dct, '\U0001f40d'.encode()), 1)
|
||||
|
||||
# dict error
|
||||
not_dict = UserDict({1: 2})
|
||||
self.assertRaises(SystemError, dict_popstring, not_dict, "key")
|
||||
self.assertRaises(SystemError, dict_popstring_null, not_dict, "key")
|
||||
|
||||
# key error
|
||||
self.assertRaises(UnicodeDecodeError, dict_popstring, {1: 2}, INVALID_UTF8)
|
||||
self.assertRaises(UnicodeDecodeError, dict_popstring_null, {1: 2}, INVALID_UTF8)
|
||||
|
||||
# CRASHES dict_popstring(NULL, "key")
|
||||
# CRASHES dict_popstring({}, NULL)
|
||||
# CRASHES dict_popstring({"a": 1}, NULL)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
103
Dependencies/Python/Lib/test/test_capi/test_eval.py
vendored
Normal file
103
Dependencies/Python/Lib/test/test_capi/test_eval.py
vendored
Normal file
@ -0,0 +1,103 @@
|
||||
import sys
|
||||
import unittest
|
||||
from test.support import import_helper
|
||||
|
||||
_testlimitedcapi = import_helper.import_module('_testlimitedcapi')
|
||||
|
||||
|
||||
class Tests(unittest.TestCase):
|
||||
def test_eval_get_func_name(self):
|
||||
eval_get_func_name = _testlimitedcapi.eval_get_func_name
|
||||
|
||||
def function_example(): ...
|
||||
|
||||
class A:
|
||||
def method_example(self): ...
|
||||
|
||||
self.assertEqual(eval_get_func_name(function_example),
|
||||
"function_example")
|
||||
self.assertEqual(eval_get_func_name(A.method_example),
|
||||
"method_example")
|
||||
self.assertEqual(eval_get_func_name(A().method_example),
|
||||
"method_example")
|
||||
self.assertEqual(eval_get_func_name(sum), "sum") # c function
|
||||
self.assertEqual(eval_get_func_name(A), "type")
|
||||
|
||||
def test_eval_get_func_desc(self):
|
||||
eval_get_func_desc = _testlimitedcapi.eval_get_func_desc
|
||||
|
||||
def function_example(): ...
|
||||
|
||||
class A:
|
||||
def method_example(self): ...
|
||||
|
||||
self.assertEqual(eval_get_func_desc(function_example),
|
||||
"()")
|
||||
self.assertEqual(eval_get_func_desc(A.method_example),
|
||||
"()")
|
||||
self.assertEqual(eval_get_func_desc(A().method_example),
|
||||
"()")
|
||||
self.assertEqual(eval_get_func_desc(sum), "()") # c function
|
||||
self.assertEqual(eval_get_func_desc(A), " object")
|
||||
|
||||
def test_eval_getlocals(self):
|
||||
# Test PyEval_GetLocals()
|
||||
x = 1
|
||||
self.assertEqual(_testlimitedcapi.eval_getlocals(),
|
||||
{'self': self,
|
||||
'x': 1})
|
||||
|
||||
y = 2
|
||||
self.assertEqual(_testlimitedcapi.eval_getlocals(),
|
||||
{'self': self,
|
||||
'x': 1,
|
||||
'y': 2})
|
||||
|
||||
def test_eval_getglobals(self):
|
||||
# Test PyEval_GetGlobals()
|
||||
self.assertEqual(_testlimitedcapi.eval_getglobals(),
|
||||
globals())
|
||||
|
||||
def test_eval_getbuiltins(self):
|
||||
# Test PyEval_GetBuiltins()
|
||||
self.assertEqual(_testlimitedcapi.eval_getbuiltins(),
|
||||
globals()['__builtins__'])
|
||||
|
||||
def test_eval_getframe(self):
|
||||
# Test PyEval_GetFrame()
|
||||
self.assertEqual(_testlimitedcapi.eval_getframe(),
|
||||
sys._getframe())
|
||||
|
||||
def test_eval_getframe_builtins(self):
|
||||
# Test PyEval_GetFrameBuiltins()
|
||||
self.assertEqual(_testlimitedcapi.eval_getframe_builtins(),
|
||||
sys._getframe().f_builtins)
|
||||
|
||||
def test_eval_getframe_globals(self):
|
||||
# Test PyEval_GetFrameGlobals()
|
||||
self.assertEqual(_testlimitedcapi.eval_getframe_globals(),
|
||||
sys._getframe().f_globals)
|
||||
|
||||
def test_eval_getframe_locals(self):
|
||||
# Test PyEval_GetFrameLocals()
|
||||
self.assertEqual(_testlimitedcapi.eval_getframe_locals(),
|
||||
sys._getframe().f_locals)
|
||||
|
||||
def test_eval_get_recursion_limit(self):
|
||||
# Test Py_GetRecursionLimit()
|
||||
self.assertEqual(_testlimitedcapi.eval_get_recursion_limit(),
|
||||
sys.getrecursionlimit())
|
||||
|
||||
def test_eval_set_recursion_limit(self):
|
||||
# Test Py_SetRecursionLimit()
|
||||
old_limit = sys.getrecursionlimit()
|
||||
try:
|
||||
limit = old_limit + 123
|
||||
_testlimitedcapi.eval_set_recursion_limit(limit)
|
||||
self.assertEqual(sys.getrecursionlimit(), limit)
|
||||
finally:
|
||||
sys.setrecursionlimit(old_limit)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
126
Dependencies/Python/Lib/test/test_capi/test_eval_code_ex.py
vendored
Normal file
126
Dependencies/Python/Lib/test/test_capi/test_eval_code_ex.py
vendored
Normal file
@ -0,0 +1,126 @@
|
||||
import unittest
|
||||
import builtins
|
||||
from collections import UserDict
|
||||
|
||||
from test.support import import_helper
|
||||
from test.support import swap_attr
|
||||
|
||||
|
||||
# Skip this test if the _testcapi module isn't available.
|
||||
_testcapi = import_helper.import_module('_testcapi')
|
||||
|
||||
NULL = None
|
||||
|
||||
|
||||
class PyEval_EvalCodeExTests(unittest.TestCase):
|
||||
|
||||
def test_simple(self):
|
||||
def f():
|
||||
return a
|
||||
|
||||
eval_code_ex = _testcapi.eval_code_ex
|
||||
code = f.__code__
|
||||
self.assertEqual(eval_code_ex(code, dict(a=1)), 1)
|
||||
|
||||
self.assertRaises(NameError, eval_code_ex, code, {})
|
||||
self.assertRaises(SystemError, eval_code_ex, code, UserDict(a=1))
|
||||
self.assertRaises(SystemError, eval_code_ex, code, [])
|
||||
self.assertRaises(SystemError, eval_code_ex, code, 1)
|
||||
# CRASHES eval_code_ex(code, NULL)
|
||||
# CRASHES eval_code_ex(1, {})
|
||||
# CRASHES eval_code_ex(NULL, {})
|
||||
|
||||
def test_custom_locals(self):
|
||||
# Monkey-patch __build_class__ to get a class code object.
|
||||
code = None
|
||||
def build_class(func, name, /, *bases, **kwds):
|
||||
nonlocal code
|
||||
code = func.__code__
|
||||
|
||||
with swap_attr(builtins, '__build_class__', build_class):
|
||||
class A:
|
||||
# Uses LOAD_NAME for a
|
||||
r[:] = [a]
|
||||
|
||||
eval_code_ex = _testcapi.eval_code_ex
|
||||
results = []
|
||||
g = dict(a=1, r=results)
|
||||
self.assertIsNone(eval_code_ex(code, g))
|
||||
self.assertEqual(results, [1])
|
||||
self.assertIsNone(eval_code_ex(code, g, dict(a=2)))
|
||||
self.assertEqual(results, [2])
|
||||
self.assertIsNone(eval_code_ex(code, g, UserDict(a=3)))
|
||||
self.assertEqual(results, [3])
|
||||
self.assertIsNone(eval_code_ex(code, g, {}))
|
||||
self.assertEqual(results, [1])
|
||||
self.assertIsNone(eval_code_ex(code, g, NULL))
|
||||
self.assertEqual(results, [1])
|
||||
|
||||
self.assertRaises(TypeError, eval_code_ex, code, g, [])
|
||||
self.assertRaises(TypeError, eval_code_ex, code, g, 1)
|
||||
self.assertRaises(NameError, eval_code_ex, code, dict(r=results), {})
|
||||
self.assertRaises(NameError, eval_code_ex, code, dict(r=results), NULL)
|
||||
self.assertRaises(TypeError, eval_code_ex, code, dict(r=results), [])
|
||||
self.assertRaises(TypeError, eval_code_ex, code, dict(r=results), 1)
|
||||
|
||||
def test_with_args(self):
|
||||
def f(a, b, c):
|
||||
return a
|
||||
|
||||
eval_code_ex = _testcapi.eval_code_ex
|
||||
code = f.__code__
|
||||
self.assertEqual(eval_code_ex(code, {}, {}, (1, 2, 3)), 1)
|
||||
self.assertRaises(TypeError, eval_code_ex, code, {}, {}, (1, 2))
|
||||
self.assertRaises(TypeError, eval_code_ex, code, {}, {}, (1, 2, 3, 4))
|
||||
|
||||
def test_with_kwargs(self):
|
||||
def f(a, b, c):
|
||||
return a
|
||||
|
||||
eval_code_ex = _testcapi.eval_code_ex
|
||||
code = f.__code__
|
||||
self.assertEqual(eval_code_ex(code, {}, {}, (), dict(a=1, b=2, c=3)), 1)
|
||||
self.assertRaises(TypeError, eval_code_ex, code, {}, {}, (), dict(a=1, b=2))
|
||||
self.assertRaises(TypeError, eval_code_ex, code, {}, {}, (), dict(a=1, b=2))
|
||||
self.assertRaises(TypeError, eval_code_ex, code, {}, {}, (), dict(a=1, b=2, c=3, d=4))
|
||||
|
||||
def test_with_default(self):
|
||||
def f(a):
|
||||
return a
|
||||
|
||||
eval_code_ex = _testcapi.eval_code_ex
|
||||
code = f.__code__
|
||||
self.assertEqual(eval_code_ex(code, {}, {}, (), {}, (1,)), 1)
|
||||
self.assertRaises(TypeError, eval_code_ex, code, {}, {}, (), {}, ())
|
||||
|
||||
def test_with_kwarg_default(self):
|
||||
def f(*, a):
|
||||
return a
|
||||
|
||||
eval_code_ex = _testcapi.eval_code_ex
|
||||
code = f.__code__
|
||||
self.assertEqual(eval_code_ex(code, {}, {}, (), {}, (), dict(a=1)), 1)
|
||||
self.assertRaises(TypeError, eval_code_ex, code, {}, {}, (), {}, (), {})
|
||||
self.assertRaises(TypeError, eval_code_ex, code, {}, {}, (), {}, (), NULL)
|
||||
self.assertRaises(SystemError, eval_code_ex, code, {}, {}, (), {}, (), UserDict(a=1))
|
||||
self.assertRaises(SystemError, eval_code_ex, code, {}, {}, (), {}, (), [])
|
||||
self.assertRaises(SystemError, eval_code_ex, code, {}, {}, (), {}, (), 1)
|
||||
|
||||
def test_with_closure(self):
|
||||
a = 1
|
||||
b = 2
|
||||
def f():
|
||||
b
|
||||
return a
|
||||
|
||||
eval_code_ex = _testcapi.eval_code_ex
|
||||
code = f.__code__
|
||||
self.assertEqual(eval_code_ex(code, {}, {}, (), {}, (), {}, f.__closure__), 1)
|
||||
self.assertEqual(eval_code_ex(code, {}, {}, (), {}, (), {}, f.__closure__[::-1]), 2)
|
||||
|
||||
# CRASHES eval_code_ex(code, {}, {}, (), {}, (), {}, ()), 1)
|
||||
# CRASHES eval_code_ex(code, {}, {}, (), {}, (), {}, NULL), 1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
509
Dependencies/Python/Lib/test/test_capi/test_exceptions.py
vendored
Normal file
509
Dependencies/Python/Lib/test/test_capi/test_exceptions.py
vendored
Normal file
@ -0,0 +1,509 @@
|
||||
import errno
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import unittest
|
||||
import textwrap
|
||||
|
||||
from test import support
|
||||
from test.support import import_helper
|
||||
from test.support.os_helper import TESTFN, TESTFN_UNDECODABLE
|
||||
from test.support.script_helper import assert_python_failure, assert_python_ok
|
||||
from test.support.testcase import ExceptionIsLikeMixin
|
||||
|
||||
from .test_misc import decode_stderr
|
||||
|
||||
# Skip this test if the _testcapi module isn't available.
|
||||
_testcapi = import_helper.import_module('_testcapi')
|
||||
|
||||
NULL = None
|
||||
|
||||
class CustomError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class Test_Exceptions(unittest.TestCase):
|
||||
|
||||
def test_exception(self):
|
||||
raised_exception = ValueError("5")
|
||||
new_exc = TypeError("TEST")
|
||||
try:
|
||||
raise raised_exception
|
||||
except ValueError as e:
|
||||
orig_sys_exception = sys.exception()
|
||||
orig_exception = _testcapi.set_exception(new_exc)
|
||||
new_sys_exception = sys.exception()
|
||||
new_exception = _testcapi.set_exception(orig_exception)
|
||||
reset_sys_exception = sys.exception()
|
||||
|
||||
self.assertEqual(orig_exception, e)
|
||||
|
||||
self.assertEqual(orig_exception, raised_exception)
|
||||
self.assertEqual(orig_sys_exception, orig_exception)
|
||||
self.assertEqual(reset_sys_exception, orig_exception)
|
||||
self.assertEqual(new_exception, new_exc)
|
||||
self.assertEqual(new_sys_exception, new_exception)
|
||||
else:
|
||||
self.fail("Exception not raised")
|
||||
|
||||
def test_exc_info(self):
|
||||
raised_exception = ValueError("5")
|
||||
new_exc = TypeError("TEST")
|
||||
try:
|
||||
raise raised_exception
|
||||
except ValueError as e:
|
||||
tb = e.__traceback__
|
||||
orig_sys_exc_info = sys.exc_info()
|
||||
orig_exc_info = _testcapi.set_exc_info(new_exc.__class__, new_exc, None)
|
||||
new_sys_exc_info = sys.exc_info()
|
||||
new_exc_info = _testcapi.set_exc_info(*orig_exc_info)
|
||||
reset_sys_exc_info = sys.exc_info()
|
||||
|
||||
self.assertEqual(orig_exc_info[1], e)
|
||||
|
||||
self.assertSequenceEqual(orig_exc_info, (raised_exception.__class__, raised_exception, tb))
|
||||
self.assertSequenceEqual(orig_sys_exc_info, orig_exc_info)
|
||||
self.assertSequenceEqual(reset_sys_exc_info, orig_exc_info)
|
||||
self.assertSequenceEqual(new_exc_info, (new_exc.__class__, new_exc, None))
|
||||
self.assertSequenceEqual(new_sys_exc_info, new_exc_info)
|
||||
else:
|
||||
self.assertTrue(False)
|
||||
|
||||
def test_warn_with_stacklevel(self):
|
||||
code = textwrap.dedent('''\
|
||||
import _testcapi
|
||||
|
||||
def foo():
|
||||
_testcapi.function_set_warning()
|
||||
|
||||
foo() # line 6
|
||||
|
||||
|
||||
foo() # line 9
|
||||
''')
|
||||
proc = assert_python_ok("-c", code)
|
||||
warnings = proc.err.splitlines()
|
||||
self.assertEqual(warnings, [
|
||||
b'<string>:6: RuntimeWarning: Testing PyErr_WarnEx',
|
||||
b'<string>:9: RuntimeWarning: Testing PyErr_WarnEx',
|
||||
])
|
||||
|
||||
def test_warn_during_finalization(self):
|
||||
code = textwrap.dedent('''\
|
||||
import _testcapi
|
||||
|
||||
class Foo:
|
||||
def foo(self):
|
||||
_testcapi.function_set_warning()
|
||||
def __del__(self):
|
||||
self.foo()
|
||||
|
||||
ref = Foo()
|
||||
''')
|
||||
proc = assert_python_ok("-c", code)
|
||||
warnings = proc.err.splitlines()
|
||||
# Due to the finalization of the interpreter, the source will be ommited
|
||||
# because the ``warnings`` module cannot be imported at this time
|
||||
self.assertEqual(warnings, [
|
||||
b'<string>:7: RuntimeWarning: Testing PyErr_WarnEx',
|
||||
])
|
||||
|
||||
|
||||
class Test_FatalError(unittest.TestCase):
|
||||
|
||||
def check_fatal_error(self, code, expected, not_expected=()):
|
||||
with support.SuppressCrashReport():
|
||||
rc, out, err = assert_python_failure('-sSI', '-c', code)
|
||||
|
||||
err = decode_stderr(err)
|
||||
self.assertIn('Fatal Python error: _testcapi_fatal_error_impl: MESSAGE\n',
|
||||
err)
|
||||
|
||||
match = re.search(r'^Extension modules:(.*) \(total: ([0-9]+)\)$',
|
||||
err, re.MULTILINE)
|
||||
if not match:
|
||||
self.fail(f"Cannot find 'Extension modules:' in {err!r}")
|
||||
modules = set(match.group(1).strip().split(', '))
|
||||
total = int(match.group(2))
|
||||
|
||||
for name in expected:
|
||||
self.assertIn(name, modules)
|
||||
for name in not_expected:
|
||||
self.assertNotIn(name, modules)
|
||||
self.assertEqual(len(modules), total)
|
||||
|
||||
@support.requires_subprocess()
|
||||
def test_fatal_error(self):
|
||||
# By default, stdlib extension modules are ignored,
|
||||
# but not test modules.
|
||||
expected = ('_testcapi',)
|
||||
not_expected = ('sys',)
|
||||
code = 'import _testcapi, sys; _testcapi.fatal_error(b"MESSAGE")'
|
||||
self.check_fatal_error(code, expected, not_expected)
|
||||
|
||||
# Mark _testcapi as stdlib module, but not sys
|
||||
expected = ('sys',)
|
||||
not_expected = ('_testcapi',)
|
||||
code = """if True:
|
||||
import _testcapi, sys
|
||||
sys.stdlib_module_names = frozenset({"_testcapi"})
|
||||
_testcapi.fatal_error(b"MESSAGE")
|
||||
"""
|
||||
self.check_fatal_error(code, expected)
|
||||
|
||||
|
||||
class Test_ErrSetAndRestore(unittest.TestCase):
|
||||
|
||||
def test_err_set_raised(self):
|
||||
with self.assertRaises(ValueError):
|
||||
_testcapi.err_set_raised(ValueError())
|
||||
v = ValueError()
|
||||
try:
|
||||
_testcapi.err_set_raised(v)
|
||||
except ValueError as ex:
|
||||
self.assertIs(v, ex)
|
||||
|
||||
def test_err_restore(self):
|
||||
with self.assertRaises(ValueError):
|
||||
_testcapi.err_restore(ValueError)
|
||||
with self.assertRaises(ValueError):
|
||||
_testcapi.err_restore(ValueError, 1)
|
||||
with self.assertRaises(ValueError):
|
||||
_testcapi.err_restore(ValueError, 1, None)
|
||||
with self.assertRaises(ValueError):
|
||||
_testcapi.err_restore(ValueError, ValueError())
|
||||
try:
|
||||
_testcapi.err_restore(KeyError, "hi")
|
||||
except KeyError as k:
|
||||
self.assertEqual("hi", k.args[0])
|
||||
try:
|
||||
1/0
|
||||
except Exception as e:
|
||||
tb = e.__traceback__
|
||||
with self.assertRaises(ValueError):
|
||||
_testcapi.err_restore(ValueError, 1, tb)
|
||||
with self.assertRaises(TypeError):
|
||||
_testcapi.err_restore(ValueError, 1, 0)
|
||||
try:
|
||||
_testcapi.err_restore(ValueError, 1, tb)
|
||||
except ValueError as v:
|
||||
self.assertEqual(1, v.args[0])
|
||||
self.assertIs(tb, v.__traceback__.tb_next)
|
||||
|
||||
def test_set_object(self):
|
||||
|
||||
# new exception as obj is not an exception
|
||||
with self.assertRaises(ValueError) as e:
|
||||
_testcapi.exc_set_object(ValueError, 42)
|
||||
self.assertEqual(e.exception.args, (42,))
|
||||
|
||||
# wraps the exception because unrelated types
|
||||
with self.assertRaises(ValueError) as e:
|
||||
_testcapi.exc_set_object(ValueError, TypeError(1,2,3))
|
||||
wrapped = e.exception.args[0]
|
||||
self.assertIsInstance(wrapped, TypeError)
|
||||
self.assertEqual(wrapped.args, (1, 2, 3))
|
||||
|
||||
# is superclass, so does not wrap
|
||||
with self.assertRaises(PermissionError) as e:
|
||||
_testcapi.exc_set_object(OSError, PermissionError(24))
|
||||
self.assertEqual(e.exception.args, (24,))
|
||||
|
||||
class Meta(type):
|
||||
def __subclasscheck__(cls, sub):
|
||||
1/0
|
||||
|
||||
class Broken(Exception, metaclass=Meta):
|
||||
pass
|
||||
|
||||
with self.assertRaises(ZeroDivisionError) as e:
|
||||
_testcapi.exc_set_object(Broken, Broken())
|
||||
|
||||
def test_set_object_and_fetch(self):
|
||||
class Broken(Exception):
|
||||
def __init__(self, *arg):
|
||||
raise ValueError("Broken __init__")
|
||||
|
||||
exc = _testcapi.exc_set_object_fetch(Broken, 'abcd')
|
||||
self.assertIsInstance(exc, ValueError)
|
||||
self.assertEqual(exc.__notes__[0],
|
||||
"Normalization failed: type=Broken args='abcd'")
|
||||
|
||||
class BadArg:
|
||||
def __repr__(self):
|
||||
raise TypeError('Broken arg type')
|
||||
|
||||
exc = _testcapi.exc_set_object_fetch(Broken, BadArg())
|
||||
self.assertIsInstance(exc, ValueError)
|
||||
self.assertEqual(exc.__notes__[0],
|
||||
'Normalization failed: type=Broken args=<unknown>')
|
||||
|
||||
def test_set_string(self):
|
||||
"""Test PyErr_SetString()"""
|
||||
setstring = _testcapi.err_setstring
|
||||
with self.assertRaises(ZeroDivisionError) as e:
|
||||
setstring(ZeroDivisionError, b'error')
|
||||
self.assertEqual(e.exception.args, ('error',))
|
||||
with self.assertRaises(ZeroDivisionError) as e:
|
||||
setstring(ZeroDivisionError, 'помилка'.encode())
|
||||
self.assertEqual(e.exception.args, ('помилка',))
|
||||
|
||||
with self.assertRaises(UnicodeDecodeError):
|
||||
setstring(ZeroDivisionError, b'\xff')
|
||||
self.assertRaises(SystemError, setstring, list, b'error')
|
||||
# CRASHES setstring(ZeroDivisionError, NULL)
|
||||
# CRASHES setstring(NULL, b'error')
|
||||
|
||||
def test_format(self):
|
||||
"""Test PyErr_Format()"""
|
||||
import_helper.import_module('ctypes')
|
||||
from ctypes import pythonapi, py_object, c_char_p, c_int
|
||||
name = "PyErr_Format"
|
||||
PyErr_Format = getattr(pythonapi, name)
|
||||
PyErr_Format.argtypes = (py_object, c_char_p,)
|
||||
PyErr_Format.restype = py_object
|
||||
with self.assertRaises(ZeroDivisionError) as e:
|
||||
PyErr_Format(ZeroDivisionError, b'%s %d', b'error', c_int(42))
|
||||
self.assertEqual(e.exception.args, ('error 42',))
|
||||
with self.assertRaises(ZeroDivisionError) as e:
|
||||
PyErr_Format(ZeroDivisionError, b'%s', 'помилка'.encode())
|
||||
self.assertEqual(e.exception.args, ('помилка',))
|
||||
|
||||
with self.assertRaisesRegex(OverflowError, 'not in range'):
|
||||
PyErr_Format(ZeroDivisionError, b'%c', c_int(-1))
|
||||
with self.assertRaisesRegex(ValueError, 'format string'):
|
||||
PyErr_Format(ZeroDivisionError, b'\xff')
|
||||
self.assertRaises(SystemError, PyErr_Format, list, b'error')
|
||||
# CRASHES PyErr_Format(ZeroDivisionError, NULL)
|
||||
# CRASHES PyErr_Format(py_object(), b'error')
|
||||
|
||||
def test_setfromerrnowithfilename(self):
|
||||
"""Test PyErr_SetFromErrnoWithFilename()"""
|
||||
setfromerrnowithfilename = _testcapi.err_setfromerrnowithfilename
|
||||
ENOENT = errno.ENOENT
|
||||
with self.assertRaises(FileNotFoundError) as e:
|
||||
setfromerrnowithfilename(ENOENT, OSError, b'file')
|
||||
self.assertEqual(e.exception.args,
|
||||
(ENOENT, 'No such file or directory'))
|
||||
self.assertEqual(e.exception.errno, ENOENT)
|
||||
self.assertEqual(e.exception.filename, 'file')
|
||||
|
||||
with self.assertRaises(FileNotFoundError) as e:
|
||||
setfromerrnowithfilename(ENOENT, OSError, os.fsencode(TESTFN))
|
||||
self.assertEqual(e.exception.filename, TESTFN)
|
||||
|
||||
if TESTFN_UNDECODABLE:
|
||||
with self.assertRaises(FileNotFoundError) as e:
|
||||
setfromerrnowithfilename(ENOENT, OSError, TESTFN_UNDECODABLE)
|
||||
self.assertEqual(e.exception.filename,
|
||||
os.fsdecode(TESTFN_UNDECODABLE))
|
||||
|
||||
with self.assertRaises(FileNotFoundError) as e:
|
||||
setfromerrnowithfilename(ENOENT, OSError, NULL)
|
||||
self.assertIsNone(e.exception.filename)
|
||||
|
||||
with self.assertRaises(OSError) as e:
|
||||
setfromerrnowithfilename(0, OSError, b'file')
|
||||
self.assertEqual(e.exception.args, (0, 'Error'))
|
||||
self.assertEqual(e.exception.errno, 0)
|
||||
self.assertEqual(e.exception.filename, 'file')
|
||||
|
||||
with self.assertRaises(ZeroDivisionError) as e:
|
||||
setfromerrnowithfilename(ENOENT, ZeroDivisionError, b'file')
|
||||
self.assertEqual(e.exception.args,
|
||||
(ENOENT, 'No such file or directory', 'file'))
|
||||
# CRASHES setfromerrnowithfilename(ENOENT, NULL, b'error')
|
||||
|
||||
def test_err_writeunraisable(self):
|
||||
# Test PyErr_WriteUnraisable()
|
||||
writeunraisable = _testcapi.err_writeunraisable
|
||||
firstline = self.test_err_writeunraisable.__code__.co_firstlineno
|
||||
|
||||
with support.catch_unraisable_exception() as cm:
|
||||
writeunraisable(CustomError('oops!'), hex)
|
||||
self.assertEqual(cm.unraisable.exc_type, CustomError)
|
||||
self.assertEqual(str(cm.unraisable.exc_value), 'oops!')
|
||||
self.assertEqual(cm.unraisable.exc_traceback.tb_lineno,
|
||||
firstline + 6)
|
||||
self.assertIsNone(cm.unraisable.err_msg)
|
||||
self.assertEqual(cm.unraisable.object, hex)
|
||||
|
||||
with support.catch_unraisable_exception() as cm:
|
||||
writeunraisable(CustomError('oops!'), NULL)
|
||||
self.assertEqual(cm.unraisable.exc_type, CustomError)
|
||||
self.assertEqual(str(cm.unraisable.exc_value), 'oops!')
|
||||
self.assertEqual(cm.unraisable.exc_traceback.tb_lineno,
|
||||
firstline + 15)
|
||||
self.assertIsNone(cm.unraisable.err_msg)
|
||||
self.assertIsNone(cm.unraisable.object)
|
||||
|
||||
with (support.swap_attr(sys, 'unraisablehook', None),
|
||||
support.captured_stderr() as stderr):
|
||||
writeunraisable(CustomError('oops!'), hex)
|
||||
lines = stderr.getvalue().splitlines()
|
||||
self.assertEqual(lines[0], f'Exception ignored in: {hex!r}')
|
||||
self.assertEqual(lines[1], 'Traceback (most recent call last):')
|
||||
self.assertEqual(lines[-1], f'{__name__}.CustomError: oops!')
|
||||
|
||||
with (support.swap_attr(sys, 'unraisablehook', None),
|
||||
support.captured_stderr() as stderr):
|
||||
writeunraisable(CustomError('oops!'), NULL)
|
||||
lines = stderr.getvalue().splitlines()
|
||||
self.assertEqual(lines[0], 'Traceback (most recent call last):')
|
||||
self.assertEqual(lines[-1], f'{__name__}.CustomError: oops!')
|
||||
|
||||
# CRASHES writeunraisable(NULL, hex)
|
||||
# CRASHES writeunraisable(NULL, NULL)
|
||||
|
||||
def test_err_formatunraisable(self):
|
||||
# Test PyErr_FormatUnraisable()
|
||||
formatunraisable = _testcapi.err_formatunraisable
|
||||
firstline = self.test_err_formatunraisable.__code__.co_firstlineno
|
||||
|
||||
with support.catch_unraisable_exception() as cm:
|
||||
formatunraisable(CustomError('oops!'), b'Error in %R', [])
|
||||
self.assertEqual(cm.unraisable.exc_type, CustomError)
|
||||
self.assertEqual(str(cm.unraisable.exc_value), 'oops!')
|
||||
self.assertEqual(cm.unraisable.exc_traceback.tb_lineno,
|
||||
firstline + 6)
|
||||
self.assertEqual(cm.unraisable.err_msg, 'Error in []')
|
||||
self.assertIsNone(cm.unraisable.object)
|
||||
|
||||
with support.catch_unraisable_exception() as cm:
|
||||
formatunraisable(CustomError('oops!'), b'undecodable \xff')
|
||||
self.assertEqual(cm.unraisable.exc_type, CustomError)
|
||||
self.assertEqual(str(cm.unraisable.exc_value), 'oops!')
|
||||
self.assertEqual(cm.unraisable.exc_traceback.tb_lineno,
|
||||
firstline + 15)
|
||||
self.assertIsNone(cm.unraisable.err_msg)
|
||||
self.assertIsNone(cm.unraisable.object)
|
||||
|
||||
with support.catch_unraisable_exception() as cm:
|
||||
formatunraisable(CustomError('oops!'), NULL)
|
||||
self.assertEqual(cm.unraisable.exc_type, CustomError)
|
||||
self.assertEqual(str(cm.unraisable.exc_value), 'oops!')
|
||||
self.assertEqual(cm.unraisable.exc_traceback.tb_lineno,
|
||||
firstline + 24)
|
||||
self.assertIsNone(cm.unraisable.err_msg)
|
||||
self.assertIsNone(cm.unraisable.object)
|
||||
|
||||
with (support.swap_attr(sys, 'unraisablehook', None),
|
||||
support.captured_stderr() as stderr):
|
||||
formatunraisable(CustomError('oops!'), b'Error in %R', [])
|
||||
lines = stderr.getvalue().splitlines()
|
||||
self.assertEqual(lines[0], f'Error in []:')
|
||||
self.assertEqual(lines[1], 'Traceback (most recent call last):')
|
||||
self.assertEqual(lines[-1], f'{__name__}.CustomError: oops!')
|
||||
|
||||
with (support.swap_attr(sys, 'unraisablehook', None),
|
||||
support.captured_stderr() as stderr):
|
||||
formatunraisable(CustomError('oops!'), b'undecodable \xff')
|
||||
lines = stderr.getvalue().splitlines()
|
||||
self.assertEqual(lines[0], 'Traceback (most recent call last):')
|
||||
self.assertEqual(lines[-1], f'{__name__}.CustomError: oops!')
|
||||
|
||||
with (support.swap_attr(sys, 'unraisablehook', None),
|
||||
support.captured_stderr() as stderr):
|
||||
formatunraisable(CustomError('oops!'), NULL)
|
||||
lines = stderr.getvalue().splitlines()
|
||||
self.assertEqual(lines[0], 'Traceback (most recent call last):')
|
||||
self.assertEqual(lines[-1], f'{__name__}.CustomError: oops!')
|
||||
|
||||
# CRASHES formatunraisable(NULL, b'Error in %R', [])
|
||||
# CRASHES formatunraisable(NULL, NULL)
|
||||
|
||||
|
||||
class Test_PyUnstable_Exc_PrepReraiseStar(ExceptionIsLikeMixin, unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
try:
|
||||
raise ExceptionGroup("eg", [TypeError('bad type'), ValueError(42)])
|
||||
except ExceptionGroup as e:
|
||||
self.orig = e
|
||||
|
||||
def test_invalid_args(self):
|
||||
with self.assertRaisesRegex(TypeError, "orig must be an exception"):
|
||||
_testcapi.unstable_exc_prep_reraise_star(42, [None])
|
||||
|
||||
with self.assertRaisesRegex(TypeError, "excs must be a list"):
|
||||
_testcapi.unstable_exc_prep_reraise_star(self.orig, 42)
|
||||
|
||||
with self.assertRaisesRegex(TypeError, "not an exception"):
|
||||
_testcapi.unstable_exc_prep_reraise_star(self.orig, [TypeError(42), 42])
|
||||
|
||||
with self.assertRaisesRegex(ValueError, "orig must be a raised exception"):
|
||||
_testcapi.unstable_exc_prep_reraise_star(ValueError(42), [TypeError(42)])
|
||||
|
||||
with self.assertRaisesRegex(ValueError, "orig must be a raised exception"):
|
||||
_testcapi.unstable_exc_prep_reraise_star(ExceptionGroup("eg", [ValueError(42)]),
|
||||
[TypeError(42)])
|
||||
|
||||
|
||||
def test_nothing_to_reraise(self):
|
||||
self.assertEqual(
|
||||
_testcapi.unstable_exc_prep_reraise_star(self.orig, [None]), None)
|
||||
|
||||
try:
|
||||
raise ValueError(42)
|
||||
except ValueError as e:
|
||||
orig = e
|
||||
self.assertEqual(
|
||||
_testcapi.unstable_exc_prep_reraise_star(orig, [None]), None)
|
||||
|
||||
def test_reraise_orig(self):
|
||||
orig = self.orig
|
||||
res = _testcapi.unstable_exc_prep_reraise_star(orig, [orig])
|
||||
self.assertExceptionIsLike(res, orig)
|
||||
|
||||
def test_raise_orig_parts(self):
|
||||
orig = self.orig
|
||||
match, rest = orig.split(TypeError)
|
||||
|
||||
test_cases = [
|
||||
([match, rest], orig),
|
||||
([rest, match], orig),
|
||||
([match], match),
|
||||
([rest], rest),
|
||||
([], None),
|
||||
]
|
||||
|
||||
for input, expected in test_cases:
|
||||
with self.subTest(input=input):
|
||||
res = _testcapi.unstable_exc_prep_reraise_star(orig, input)
|
||||
self.assertExceptionIsLike(res, expected)
|
||||
|
||||
|
||||
def test_raise_with_new_exceptions(self):
|
||||
orig = self.orig
|
||||
|
||||
match, rest = orig.split(TypeError)
|
||||
new1 = OSError('bad file')
|
||||
new2 = RuntimeError('bad runtime')
|
||||
|
||||
test_cases = [
|
||||
([new1, match, rest], ExceptionGroup("", [new1, orig])),
|
||||
([match, new1, rest], ExceptionGroup("", [new1, orig])),
|
||||
([match, rest, new1], ExceptionGroup("", [new1, orig])),
|
||||
|
||||
([new1, new2, match, rest], ExceptionGroup("", [new1, new2, orig])),
|
||||
([new1, match, new2, rest], ExceptionGroup("", [new1, new2, orig])),
|
||||
([new2, rest, match, new1], ExceptionGroup("", [new2, new1, orig])),
|
||||
([rest, new2, match, new1], ExceptionGroup("", [new2, new1, orig])),
|
||||
|
||||
|
||||
([new1, new2, rest], ExceptionGroup("", [new1, new2, rest])),
|
||||
([new1, match, new2], ExceptionGroup("", [new1, new2, match])),
|
||||
([rest, new2, new1], ExceptionGroup("", [new2, new1, rest])),
|
||||
([new1, new2], ExceptionGroup("", [new1, new2])),
|
||||
([new2, new1], ExceptionGroup("", [new2, new1])),
|
||||
]
|
||||
|
||||
for (input, expected) in test_cases:
|
||||
with self.subTest(input=input):
|
||||
res = _testcapi.unstable_exc_prep_reraise_star(orig, input)
|
||||
self.assertExceptionIsLike(res, expected)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
234
Dependencies/Python/Lib/test/test_capi/test_file.py
vendored
Normal file
234
Dependencies/Python/Lib/test/test_capi/test_file.py
vendored
Normal file
@ -0,0 +1,234 @@
|
||||
import io
|
||||
import os
|
||||
import unittest
|
||||
import warnings
|
||||
from test import support
|
||||
from test.support import import_helper, os_helper, warnings_helper
|
||||
|
||||
|
||||
_testcapi = import_helper.import_module('_testcapi')
|
||||
_testlimitedcapi = import_helper.import_module('_testlimitedcapi')
|
||||
_io = import_helper.import_module('_io')
|
||||
NULL = None
|
||||
STDOUT_FD = 1
|
||||
|
||||
with open(__file__, 'rb') as fp:
|
||||
FIRST_LINE = next(fp).decode()
|
||||
FIRST_LINE_NORM = FIRST_LINE.rstrip() + '\n'
|
||||
|
||||
|
||||
class CAPIFileTest(unittest.TestCase):
|
||||
def test_pyfile_fromfd(self):
|
||||
# Test PyFile_FromFd() which is a thin wrapper to _io.open()
|
||||
pyfile_fromfd = _testlimitedcapi.pyfile_fromfd
|
||||
filename = __file__
|
||||
with open(filename, "rb") as fp:
|
||||
fd = fp.fileno()
|
||||
|
||||
# FileIO
|
||||
fp.seek(0)
|
||||
obj = pyfile_fromfd(fd, filename, "rb", 0, NULL, NULL, NULL, 0)
|
||||
try:
|
||||
self.assertIsInstance(obj, _io.FileIO)
|
||||
self.assertEqual(obj.readline(), FIRST_LINE.encode())
|
||||
finally:
|
||||
obj.close()
|
||||
|
||||
# BufferedReader
|
||||
fp.seek(0)
|
||||
obj = pyfile_fromfd(fd, filename, "rb", 1024, NULL, NULL, NULL, 0)
|
||||
try:
|
||||
self.assertIsInstance(obj, _io.BufferedReader)
|
||||
self.assertEqual(obj.readline(), FIRST_LINE.encode())
|
||||
finally:
|
||||
obj.close()
|
||||
|
||||
# TextIOWrapper
|
||||
fp.seek(0)
|
||||
obj = pyfile_fromfd(fd, filename, "r", 1,
|
||||
"utf-8", "replace", NULL, 0)
|
||||
try:
|
||||
self.assertIsInstance(obj, _io.TextIOWrapper)
|
||||
self.assertEqual(obj.encoding, "utf-8")
|
||||
self.assertEqual(obj.errors, "replace")
|
||||
self.assertEqual(obj.readline(), FIRST_LINE_NORM)
|
||||
finally:
|
||||
obj.close()
|
||||
|
||||
def test_pyfile_getline(self):
|
||||
# Test PyFile_GetLine(file, n): call file.readline()
|
||||
# and strip "\n" suffix if n < 0.
|
||||
pyfile_getline = _testlimitedcapi.pyfile_getline
|
||||
|
||||
# Test Unicode
|
||||
with open(__file__, "r") as fp:
|
||||
fp.seek(0)
|
||||
self.assertEqual(pyfile_getline(fp, -1),
|
||||
FIRST_LINE_NORM.rstrip('\n'))
|
||||
fp.seek(0)
|
||||
self.assertEqual(pyfile_getline(fp, 0),
|
||||
FIRST_LINE_NORM)
|
||||
fp.seek(0)
|
||||
self.assertEqual(pyfile_getline(fp, 6),
|
||||
FIRST_LINE_NORM[:6])
|
||||
|
||||
# Test bytes
|
||||
with open(__file__, "rb") as fp:
|
||||
fp.seek(0)
|
||||
self.assertEqual(pyfile_getline(fp, -1),
|
||||
FIRST_LINE.rstrip('\n').encode())
|
||||
fp.seek(0)
|
||||
self.assertEqual(pyfile_getline(fp, 0),
|
||||
FIRST_LINE.encode())
|
||||
fp.seek(0)
|
||||
self.assertEqual(pyfile_getline(fp, 6),
|
||||
FIRST_LINE.encode()[:6])
|
||||
|
||||
def test_pyfile_writestring(self):
|
||||
# Test PyFile_WriteString(str, file): call file.write(str)
|
||||
writestr = _testlimitedcapi.pyfile_writestring
|
||||
|
||||
with io.StringIO() as fp:
|
||||
self.assertEqual(writestr("a\xe9\u20ac\U0010FFFF".encode(), fp), 0)
|
||||
with self.assertRaises(UnicodeDecodeError):
|
||||
writestr(b"\xff", fp)
|
||||
with self.assertRaises(UnicodeDecodeError):
|
||||
writestr("\udc80".encode("utf-8", "surrogatepass"), fp)
|
||||
|
||||
text = fp.getvalue()
|
||||
self.assertEqual(text, "a\xe9\u20ac\U0010FFFF")
|
||||
|
||||
with self.assertRaises(SystemError):
|
||||
writestr(b"abc", NULL)
|
||||
|
||||
def test_pyfile_writeobject(self):
|
||||
# Test PyFile_WriteObject(obj, file, flags):
|
||||
# - Call file.write(str(obj)) if flags equals Py_PRINT_RAW.
|
||||
# - Call file.write(repr(obj)) otherwise.
|
||||
writeobject = _testlimitedcapi.pyfile_writeobject
|
||||
Py_PRINT_RAW = 1
|
||||
|
||||
with io.StringIO() as fp:
|
||||
# Test flags=Py_PRINT_RAW
|
||||
self.assertEqual(writeobject("raw", fp, Py_PRINT_RAW), 0)
|
||||
writeobject(NULL, fp, Py_PRINT_RAW)
|
||||
|
||||
# Test flags=0
|
||||
self.assertEqual(writeobject("repr", fp, 0), 0)
|
||||
writeobject(NULL, fp, 0)
|
||||
|
||||
text = fp.getvalue()
|
||||
self.assertEqual(text, "raw<NULL>'repr'<NULL>")
|
||||
|
||||
# invalid file type
|
||||
for invalid_file in (123, "abc", object()):
|
||||
with self.subTest(file=invalid_file):
|
||||
with self.assertRaises(AttributeError):
|
||||
writeobject("abc", invalid_file, Py_PRINT_RAW)
|
||||
|
||||
with self.assertRaises(TypeError):
|
||||
writeobject("abc", NULL, 0)
|
||||
|
||||
def test_pyobject_asfiledescriptor(self):
|
||||
# Test PyObject_AsFileDescriptor(obj):
|
||||
# - Return obj if obj is an integer.
|
||||
# - Return obj.fileno() otherwise.
|
||||
# File descriptor must be >= 0.
|
||||
asfd = _testlimitedcapi.pyobject_asfiledescriptor
|
||||
|
||||
self.assertEqual(asfd(123), 123)
|
||||
self.assertEqual(asfd(0), 0)
|
||||
|
||||
with open(__file__, "rb") as fp:
|
||||
self.assertEqual(asfd(fp), fp.fileno())
|
||||
|
||||
# bool emits RuntimeWarning
|
||||
msg = r"bool is used as a file descriptor"
|
||||
with warnings_helper.check_warnings((msg, RuntimeWarning)):
|
||||
self.assertEqual(asfd(True), 1)
|
||||
|
||||
class FakeFile:
|
||||
def __init__(self, fd):
|
||||
self.fd = fd
|
||||
def fileno(self):
|
||||
return self.fd
|
||||
|
||||
# file descriptor must be positive
|
||||
with self.assertRaises(ValueError):
|
||||
asfd(-1)
|
||||
with self.assertRaises(ValueError):
|
||||
asfd(FakeFile(-1))
|
||||
|
||||
# fileno() result must be an integer
|
||||
with self.assertRaises(TypeError):
|
||||
asfd(FakeFile("text"))
|
||||
|
||||
# unsupported types
|
||||
for obj in ("string", ["list"], object()):
|
||||
with self.subTest(obj=obj):
|
||||
with self.assertRaises(TypeError):
|
||||
asfd(obj)
|
||||
|
||||
# CRASHES asfd(NULL)
|
||||
|
||||
def test_pyfile_newstdprinter(self):
|
||||
# Test PyFile_NewStdPrinter()
|
||||
pyfile_newstdprinter = _testcapi.pyfile_newstdprinter
|
||||
|
||||
file = pyfile_newstdprinter(STDOUT_FD)
|
||||
self.assertEqual(file.closed, False)
|
||||
self.assertIsNone(file.encoding)
|
||||
self.assertEqual(file.mode, "w")
|
||||
|
||||
self.assertEqual(file.fileno(), STDOUT_FD)
|
||||
self.assertEqual(file.isatty(), os.isatty(STDOUT_FD))
|
||||
|
||||
# flush() is a no-op
|
||||
self.assertIsNone(file.flush())
|
||||
|
||||
# close() is a no-op
|
||||
self.assertIsNone(file.close())
|
||||
self.assertEqual(file.closed, False)
|
||||
|
||||
support.check_disallow_instantiation(self, type(file))
|
||||
|
||||
def test_pyfile_newstdprinter_write(self):
|
||||
# Test the write() method of PyFile_NewStdPrinter()
|
||||
pyfile_newstdprinter = _testcapi.pyfile_newstdprinter
|
||||
|
||||
filename = os_helper.TESTFN
|
||||
self.addCleanup(os_helper.unlink, filename)
|
||||
|
||||
try:
|
||||
old_stdout = os.dup(STDOUT_FD)
|
||||
except OSError as exc:
|
||||
# os.dup(STDOUT_FD) is not supported on WASI
|
||||
self.skipTest(f"os.dup() failed with {exc!r}")
|
||||
|
||||
try:
|
||||
with open(filename, "wb") as fp:
|
||||
# PyFile_NewStdPrinter() only accepts fileno(stdout)
|
||||
# or fileno(stderr) file descriptor.
|
||||
fd = fp.fileno()
|
||||
os.dup2(fd, STDOUT_FD)
|
||||
|
||||
file = pyfile_newstdprinter(STDOUT_FD)
|
||||
self.assertEqual(file.write("text"), 4)
|
||||
# The surrogate character is encoded with
|
||||
# the "surrogateescape" error handler
|
||||
self.assertEqual(file.write("[\udc80]"), 8)
|
||||
finally:
|
||||
os.dup2(old_stdout, STDOUT_FD)
|
||||
os.close(old_stdout)
|
||||
|
||||
with open(filename, "r") as fp:
|
||||
self.assertEqual(fp.read(), "text[\\udc80]")
|
||||
|
||||
# TODO: Test Py_UniversalNewlineFgets()
|
||||
|
||||
# PyFile_SetOpenCodeHook() and PyFile_OpenCode() are tested by
|
||||
# test_embed.test_open_code_hook()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
183
Dependencies/Python/Lib/test/test_capi/test_float.py
vendored
Normal file
183
Dependencies/Python/Lib/test/test_capi/test_float.py
vendored
Normal file
@ -0,0 +1,183 @@
|
||||
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()
|
1381
Dependencies/Python/Lib/test/test_capi/test_getargs.py
vendored
Normal file
1381
Dependencies/Python/Lib/test/test_capi/test_getargs.py
vendored
Normal file
File diff suppressed because it is too large
Load Diff
83
Dependencies/Python/Lib/test/test_capi/test_hash.py
vendored
Normal file
83
Dependencies/Python/Lib/test/test_capi/test_hash.py
vendored
Normal file
@ -0,0 +1,83 @@
|
||||
import sys
|
||||
import unittest
|
||||
from test.support import import_helper
|
||||
_testcapi = import_helper.import_module('_testcapi')
|
||||
|
||||
|
||||
SIZEOF_VOID_P = _testcapi.SIZEOF_VOID_P
|
||||
SIZEOF_PY_HASH_T = SIZEOF_VOID_P
|
||||
|
||||
|
||||
class CAPITest(unittest.TestCase):
|
||||
def test_hash_getfuncdef(self):
|
||||
# Test PyHash_GetFuncDef()
|
||||
hash_getfuncdef = _testcapi.hash_getfuncdef
|
||||
func_def = hash_getfuncdef()
|
||||
|
||||
match func_def.name:
|
||||
case "fnv":
|
||||
self.assertEqual(func_def.hash_bits, 8 * SIZEOF_PY_HASH_T)
|
||||
self.assertEqual(func_def.seed_bits, 16 * SIZEOF_PY_HASH_T)
|
||||
case "siphash13":
|
||||
self.assertEqual(func_def.hash_bits, 64)
|
||||
self.assertEqual(func_def.seed_bits, 128)
|
||||
case "siphash24":
|
||||
self.assertEqual(func_def.hash_bits, 64)
|
||||
self.assertEqual(func_def.seed_bits, 128)
|
||||
case _:
|
||||
self.fail(f"unknown function name: {func_def.name!r}")
|
||||
|
||||
# compare with sys.hash_info
|
||||
hash_info = sys.hash_info
|
||||
self.assertEqual(func_def.name, hash_info.algorithm)
|
||||
self.assertEqual(func_def.hash_bits, hash_info.hash_bits)
|
||||
self.assertEqual(func_def.seed_bits, hash_info.seed_bits)
|
||||
|
||||
def test_hash_pointer(self):
|
||||
# Test Py_HashPointer()
|
||||
hash_pointer = _testcapi.hash_pointer
|
||||
|
||||
UHASH_T_MASK = ((2 ** (8 * SIZEOF_PY_HASH_T)) - 1)
|
||||
HASH_T_MAX = (2 ** (8 * SIZEOF_PY_HASH_T - 1) - 1)
|
||||
|
||||
def python_hash_pointer(x):
|
||||
# Py_HashPointer() rotates the pointer bits by 4 bits to the right
|
||||
x = (x >> 4) | ((x & 15) << (8 * SIZEOF_VOID_P - 4))
|
||||
|
||||
# Convert unsigned uintptr_t (Py_uhash_t) to signed Py_hash_t
|
||||
if HASH_T_MAX < x:
|
||||
x = (~x) + 1
|
||||
x &= UHASH_T_MASK
|
||||
x = (~x) + 1
|
||||
return x
|
||||
|
||||
if SIZEOF_VOID_P == 8:
|
||||
values = (
|
||||
0xABCDEF1234567890,
|
||||
0x1234567890ABCDEF,
|
||||
0xFEE4ABEDD1CECA5E,
|
||||
)
|
||||
else:
|
||||
values = (
|
||||
0x12345678,
|
||||
0x1234ABCD,
|
||||
0xDEADCAFE,
|
||||
)
|
||||
|
||||
for value in values:
|
||||
expected = python_hash_pointer(value)
|
||||
with self.subTest(value=value):
|
||||
self.assertEqual(hash_pointer(value), expected,
|
||||
f"hash_pointer({value:x}) = "
|
||||
f"{hash_pointer(value):x} != {expected:x}")
|
||||
|
||||
# Py_HashPointer(NULL) returns 0
|
||||
self.assertEqual(hash_pointer(0), 0)
|
||||
|
||||
# Py_HashPointer((void*)(uintptr_t)-1) doesn't return -1 but -2
|
||||
VOID_P_MAX = -1 & (2 ** (8 * SIZEOF_VOID_P) - 1)
|
||||
self.assertEqual(hash_pointer(VOID_P_MAX), -2)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
16
Dependencies/Python/Lib/test/test_capi/test_immortal.py
vendored
Normal file
16
Dependencies/Python/Lib/test/test_capi/test_immortal.py
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
import unittest
|
||||
from test.support import import_helper
|
||||
|
||||
_testcapi = import_helper.import_module('_testcapi')
|
||||
|
||||
|
||||
class TestCAPI(unittest.TestCase):
|
||||
def test_immortal_builtins(self):
|
||||
_testcapi.test_immortal_builtins()
|
||||
|
||||
def test_immortal_small_ints(self):
|
||||
_testcapi.test_immortal_small_ints()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
322
Dependencies/Python/Lib/test/test_capi/test_import.py
vendored
Normal file
322
Dependencies/Python/Lib/test/test_capi/test_import.py
vendored
Normal file
@ -0,0 +1,322 @@
|
||||
import importlib.util
|
||||
import os.path
|
||||
import sys
|
||||
import types
|
||||
import unittest
|
||||
from test.support import os_helper
|
||||
from test.support import import_helper
|
||||
from test.support.warnings_helper import check_warnings
|
||||
|
||||
_testlimitedcapi = import_helper.import_module('_testlimitedcapi')
|
||||
NULL = None
|
||||
|
||||
|
||||
class ImportTests(unittest.TestCase):
|
||||
def test_getmagicnumber(self):
|
||||
# Test PyImport_GetMagicNumber()
|
||||
magic = _testlimitedcapi.PyImport_GetMagicNumber()
|
||||
self.assertEqual(magic,
|
||||
int.from_bytes(importlib.util.MAGIC_NUMBER, 'little'))
|
||||
|
||||
def test_getmagictag(self):
|
||||
# Test PyImport_GetMagicTag()
|
||||
tag = _testlimitedcapi.PyImport_GetMagicTag()
|
||||
self.assertEqual(tag, sys.implementation.cache_tag)
|
||||
|
||||
def test_getmoduledict(self):
|
||||
# Test PyImport_GetModuleDict()
|
||||
modules = _testlimitedcapi.PyImport_GetModuleDict()
|
||||
self.assertIs(modules, sys.modules)
|
||||
|
||||
def check_import_loaded_module(self, import_module):
|
||||
for name in ('os', 'sys', 'test', 'unittest'):
|
||||
with self.subTest(name=name):
|
||||
self.assertIn(name, sys.modules)
|
||||
old_module = sys.modules[name]
|
||||
module = import_module(name)
|
||||
self.assertIsInstance(module, types.ModuleType)
|
||||
self.assertIs(module, old_module)
|
||||
|
||||
def check_import_fresh_module(self, import_module):
|
||||
old_modules = dict(sys.modules)
|
||||
try:
|
||||
for name in ('colorsys', 'math'):
|
||||
with self.subTest(name=name):
|
||||
sys.modules.pop(name, None)
|
||||
module = import_module(name)
|
||||
self.assertIsInstance(module, types.ModuleType)
|
||||
self.assertIs(module, sys.modules[name])
|
||||
self.assertEqual(module.__name__, name)
|
||||
finally:
|
||||
sys.modules.clear()
|
||||
sys.modules.update(old_modules)
|
||||
|
||||
def test_getmodule(self):
|
||||
# Test PyImport_GetModule()
|
||||
getmodule = _testlimitedcapi.PyImport_GetModule
|
||||
self.check_import_loaded_module(getmodule)
|
||||
|
||||
nonexistent = 'nonexistent'
|
||||
self.assertNotIn(nonexistent, sys.modules)
|
||||
self.assertIs(getmodule(nonexistent), KeyError)
|
||||
self.assertIs(getmodule(''), KeyError)
|
||||
self.assertIs(getmodule(object()), KeyError)
|
||||
|
||||
self.assertRaises(TypeError, getmodule, []) # unhashable
|
||||
# CRASHES getmodule(NULL)
|
||||
|
||||
def check_addmodule(self, add_module, accept_nonstr=False):
|
||||
# create a new module
|
||||
names = ['nonexistent']
|
||||
if accept_nonstr:
|
||||
names.append(b'\xff') # non-UTF-8
|
||||
for name in names:
|
||||
with self.subTest(name=name):
|
||||
self.assertNotIn(name, sys.modules)
|
||||
try:
|
||||
module = add_module(name)
|
||||
self.assertIsInstance(module, types.ModuleType)
|
||||
self.assertEqual(module.__name__, name)
|
||||
self.assertIs(module, sys.modules[name])
|
||||
finally:
|
||||
sys.modules.pop(name, None)
|
||||
|
||||
# get an existing module
|
||||
self.check_import_loaded_module(add_module)
|
||||
|
||||
def test_addmoduleobject(self):
|
||||
# Test PyImport_AddModuleObject()
|
||||
addmoduleobject = _testlimitedcapi.PyImport_AddModuleObject
|
||||
self.check_addmodule(addmoduleobject, accept_nonstr=True)
|
||||
|
||||
self.assertRaises(TypeError, addmoduleobject, []) # unhashable
|
||||
# CRASHES addmoduleobject(NULL)
|
||||
|
||||
def test_addmodule(self):
|
||||
# Test PyImport_AddModule()
|
||||
addmodule = _testlimitedcapi.PyImport_AddModule
|
||||
self.check_addmodule(addmodule)
|
||||
|
||||
self.assertRaises(UnicodeDecodeError, addmodule, b'\xff')
|
||||
# CRASHES addmodule(NULL)
|
||||
|
||||
def test_addmoduleref(self):
|
||||
# Test PyImport_AddModuleRef()
|
||||
addmoduleref = _testlimitedcapi.PyImport_AddModuleRef
|
||||
self.check_addmodule(addmoduleref)
|
||||
|
||||
self.assertRaises(UnicodeDecodeError, addmoduleref, b'\xff')
|
||||
# CRASHES addmoduleref(NULL)
|
||||
|
||||
def check_import_func(self, import_module):
|
||||
self.check_import_loaded_module(import_module)
|
||||
self.check_import_fresh_module(import_module)
|
||||
self.assertRaises(ModuleNotFoundError, import_module, 'nonexistent')
|
||||
self.assertRaises(ValueError, import_module, '')
|
||||
|
||||
def test_import(self):
|
||||
# Test PyImport_Import()
|
||||
import_ = _testlimitedcapi.PyImport_Import
|
||||
self.check_import_func(import_)
|
||||
|
||||
self.assertRaises(TypeError, import_, b'os')
|
||||
self.assertRaises(SystemError, import_, NULL)
|
||||
|
||||
def test_importmodule(self):
|
||||
# Test PyImport_ImportModule()
|
||||
importmodule = _testlimitedcapi.PyImport_ImportModule
|
||||
self.check_import_func(importmodule)
|
||||
|
||||
self.assertRaises(UnicodeDecodeError, importmodule, b'\xff')
|
||||
# CRASHES importmodule(NULL)
|
||||
|
||||
def test_importmodulenoblock(self):
|
||||
# Test deprecated PyImport_ImportModuleNoBlock()
|
||||
importmodulenoblock = _testlimitedcapi.PyImport_ImportModuleNoBlock
|
||||
with check_warnings(('', DeprecationWarning)):
|
||||
self.check_import_func(importmodulenoblock)
|
||||
self.assertRaises(UnicodeDecodeError, importmodulenoblock, b'\xff')
|
||||
|
||||
# CRASHES importmodulenoblock(NULL)
|
||||
|
||||
def check_frozen_import(self, import_frozen_module):
|
||||
# Importing a frozen module executes its code, so start by unloading
|
||||
# the module to execute the code in a new (temporary) module.
|
||||
old_zipimport = sys.modules.pop('zipimport')
|
||||
try:
|
||||
self.assertEqual(import_frozen_module('zipimport'), 1)
|
||||
|
||||
# import zipimport again
|
||||
self.assertEqual(import_frozen_module('zipimport'), 1)
|
||||
finally:
|
||||
sys.modules['zipimport'] = old_zipimport
|
||||
|
||||
# not a frozen module
|
||||
self.assertEqual(import_frozen_module('sys'), 0)
|
||||
self.assertEqual(import_frozen_module('nonexistent'), 0)
|
||||
self.assertEqual(import_frozen_module(''), 0)
|
||||
|
||||
def test_importfrozenmodule(self):
|
||||
# Test PyImport_ImportFrozenModule()
|
||||
importfrozenmodule = _testlimitedcapi.PyImport_ImportFrozenModule
|
||||
self.check_frozen_import(importfrozenmodule)
|
||||
|
||||
self.assertRaises(UnicodeDecodeError, importfrozenmodule, b'\xff')
|
||||
# CRASHES importfrozenmodule(NULL)
|
||||
|
||||
def test_importfrozenmoduleobject(self):
|
||||
# Test PyImport_ImportFrozenModuleObject()
|
||||
importfrozenmoduleobject = _testlimitedcapi.PyImport_ImportFrozenModuleObject
|
||||
self.check_frozen_import(importfrozenmoduleobject)
|
||||
self.assertEqual(importfrozenmoduleobject(b'zipimport'), 0)
|
||||
self.assertEqual(importfrozenmoduleobject(NULL), 0)
|
||||
|
||||
def test_importmoduleex(self):
|
||||
# Test PyImport_ImportModuleEx()
|
||||
importmoduleex = _testlimitedcapi.PyImport_ImportModuleEx
|
||||
self.check_import_func(lambda name: importmoduleex(name, NULL, NULL, NULL))
|
||||
|
||||
self.assertRaises(ModuleNotFoundError, importmoduleex, 'nonexistent', NULL, NULL, NULL)
|
||||
self.assertRaises(ValueError, importmoduleex, '', NULL, NULL, NULL)
|
||||
self.assertRaises(UnicodeDecodeError, importmoduleex, b'\xff', NULL, NULL, NULL)
|
||||
# CRASHES importmoduleex(NULL, NULL, NULL, NULL)
|
||||
|
||||
def check_importmodulelevel(self, importmodulelevel):
|
||||
self.check_import_func(lambda name: importmodulelevel(name, NULL, NULL, NULL, 0))
|
||||
|
||||
self.assertRaises(ModuleNotFoundError, importmodulelevel, 'nonexistent', NULL, NULL, NULL, 0)
|
||||
self.assertRaises(ValueError, importmodulelevel, '', NULL, NULL, NULL, 0)
|
||||
|
||||
if __package__:
|
||||
self.assertIs(importmodulelevel('test_import', globals(), NULL, NULL, 1),
|
||||
sys.modules['test.test_capi.test_import'])
|
||||
self.assertIs(importmodulelevel('test_capi', globals(), NULL, NULL, 2),
|
||||
sys.modules['test.test_capi'])
|
||||
self.assertRaises(ValueError, importmodulelevel, 'os', NULL, NULL, NULL, -1)
|
||||
with self.assertWarns(ImportWarning):
|
||||
self.assertRaises(KeyError, importmodulelevel, 'test_import', {}, NULL, NULL, 1)
|
||||
self.assertRaises(TypeError, importmodulelevel, 'test_import', [], NULL, NULL, 1)
|
||||
|
||||
def test_importmodulelevel(self):
|
||||
# Test PyImport_ImportModuleLevel()
|
||||
importmodulelevel = _testlimitedcapi.PyImport_ImportModuleLevel
|
||||
self.check_importmodulelevel(importmodulelevel)
|
||||
|
||||
self.assertRaises(UnicodeDecodeError, importmodulelevel, b'\xff', NULL, NULL, NULL, 0)
|
||||
# CRASHES importmodulelevel(NULL, NULL, NULL, NULL, 0)
|
||||
|
||||
def test_importmodulelevelobject(self):
|
||||
# Test PyImport_ImportModuleLevelObject()
|
||||
importmodulelevel = _testlimitedcapi.PyImport_ImportModuleLevelObject
|
||||
self.check_importmodulelevel(importmodulelevel)
|
||||
|
||||
self.assertRaises(TypeError, importmodulelevel, b'os', NULL, NULL, NULL, 0)
|
||||
self.assertRaises(ValueError, importmodulelevel, NULL, NULL, NULL, NULL, 0)
|
||||
|
||||
def check_executecodemodule(self, execute_code, *args):
|
||||
name = 'test_import_executecode'
|
||||
try:
|
||||
# Create a temporary module where the code will be executed
|
||||
self.assertNotIn(name, sys.modules)
|
||||
module = _testlimitedcapi.PyImport_AddModuleRef(name)
|
||||
self.assertFalse(hasattr(module, 'attr'))
|
||||
|
||||
# Execute the code
|
||||
code = compile('attr = 1', '<test>', 'exec')
|
||||
module2 = execute_code(name, code, *args)
|
||||
self.assertIs(module2, module)
|
||||
|
||||
# Check the function side effects
|
||||
self.assertEqual(module.attr, 1)
|
||||
finally:
|
||||
sys.modules.pop(name, None)
|
||||
return module.__spec__.origin
|
||||
|
||||
def test_executecodemodule(self):
|
||||
# Test PyImport_ExecCodeModule()
|
||||
execcodemodule = _testlimitedcapi.PyImport_ExecCodeModule
|
||||
self.check_executecodemodule(execcodemodule)
|
||||
|
||||
code = compile('attr = 1', '<test>', 'exec')
|
||||
self.assertRaises(UnicodeDecodeError, execcodemodule, b'\xff', code)
|
||||
# CRASHES execcodemodule(NULL, code)
|
||||
# CRASHES execcodemodule(name, NULL)
|
||||
|
||||
def test_executecodemoduleex(self):
|
||||
# Test PyImport_ExecCodeModuleEx()
|
||||
execcodemoduleex = _testlimitedcapi.PyImport_ExecCodeModuleEx
|
||||
|
||||
# Test NULL path (it should not crash)
|
||||
self.check_executecodemodule(execcodemoduleex, NULL)
|
||||
|
||||
# Test non-NULL path
|
||||
pathname = b'pathname'
|
||||
origin = self.check_executecodemodule(execcodemoduleex, pathname)
|
||||
self.assertEqual(origin, os.path.abspath(os.fsdecode(pathname)))
|
||||
|
||||
pathname = os_helper.TESTFN_UNDECODABLE
|
||||
if pathname:
|
||||
origin = self.check_executecodemodule(execcodemoduleex, pathname)
|
||||
self.assertEqual(origin, os.path.abspath(os.fsdecode(pathname)))
|
||||
|
||||
code = compile('attr = 1', '<test>', 'exec')
|
||||
self.assertRaises(UnicodeDecodeError, execcodemoduleex, b'\xff', code, NULL)
|
||||
# CRASHES execcodemoduleex(NULL, code, NULL)
|
||||
# CRASHES execcodemoduleex(name, NULL, NULL)
|
||||
|
||||
def check_executecode_pathnames(self, execute_code_func, object=False):
|
||||
# Test non-NULL pathname and NULL cpathname
|
||||
|
||||
# Test NULL paths (it should not crash)
|
||||
self.check_executecodemodule(execute_code_func, NULL, NULL)
|
||||
|
||||
pathname = 'pathname'
|
||||
origin = self.check_executecodemodule(execute_code_func, pathname, NULL)
|
||||
self.assertEqual(origin, os.path.abspath(os.fsdecode(pathname)))
|
||||
origin = self.check_executecodemodule(execute_code_func, NULL, pathname)
|
||||
if not object:
|
||||
self.assertEqual(origin, os.path.abspath(os.fsdecode(pathname)))
|
||||
|
||||
pathname = os_helper.TESTFN_UNDECODABLE
|
||||
if pathname:
|
||||
if object:
|
||||
pathname = os.fsdecode(pathname)
|
||||
origin = self.check_executecodemodule(execute_code_func, pathname, NULL)
|
||||
self.assertEqual(origin, os.path.abspath(os.fsdecode(pathname)))
|
||||
self.check_executecodemodule(execute_code_func, NULL, pathname)
|
||||
|
||||
# Test NULL pathname and non-NULL cpathname
|
||||
pyc_filename = importlib.util.cache_from_source(__file__)
|
||||
py_filename = importlib.util.source_from_cache(pyc_filename)
|
||||
origin = self.check_executecodemodule(execute_code_func, NULL, pyc_filename)
|
||||
if not object:
|
||||
self.assertEqual(origin, py_filename)
|
||||
|
||||
def test_executecodemodulewithpathnames(self):
|
||||
# Test PyImport_ExecCodeModuleWithPathnames()
|
||||
execute_code_func = _testlimitedcapi.PyImport_ExecCodeModuleWithPathnames
|
||||
self.check_executecode_pathnames(execute_code_func)
|
||||
|
||||
code = compile('attr = 1', '<test>', 'exec')
|
||||
self.assertRaises(UnicodeDecodeError, execute_code_func, b'\xff', code, NULL, NULL)
|
||||
# CRASHES execute_code_func(NULL, code, NULL, NULL)
|
||||
# CRASHES execute_code_func(name, NULL, NULL, NULL)
|
||||
|
||||
def test_executecodemoduleobject(self):
|
||||
# Test PyImport_ExecCodeModuleObject()
|
||||
execute_code_func = _testlimitedcapi.PyImport_ExecCodeModuleObject
|
||||
self.check_executecode_pathnames(execute_code_func, object=True)
|
||||
|
||||
code = compile('attr = 1', '<test>', 'exec')
|
||||
self.assertRaises(TypeError, execute_code_func, [], code, NULL, NULL)
|
||||
# CRASHES execute_code_func(NULL, code, NULL, NULL)
|
||||
# CRASHES execute_code_func(name, NULL, NULL, NULL)
|
||||
|
||||
# TODO: test PyImport_GetImporter()
|
||||
# TODO: test PyImport_ReloadModule()
|
||||
# TODO: test PyImport_ExtendInittab()
|
||||
# PyImport_AppendInittab() is tested by test_embed
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
357
Dependencies/Python/Lib/test/test_capi/test_list.py
vendored
Normal file
357
Dependencies/Python/Lib/test/test_capi/test_list.py
vendored
Normal file
@ -0,0 +1,357 @@
|
||||
import gc
|
||||
import weakref
|
||||
import unittest
|
||||
from test.support import import_helper
|
||||
from collections import UserList
|
||||
_testcapi = import_helper.import_module('_testcapi')
|
||||
_testlimitedcapi = import_helper.import_module('_testlimitedcapi')
|
||||
|
||||
NULL = None
|
||||
PY_SSIZE_T_MIN = _testcapi.PY_SSIZE_T_MIN
|
||||
PY_SSIZE_T_MAX = _testcapi.PY_SSIZE_T_MAX
|
||||
|
||||
class ListSubclass(list):
|
||||
pass
|
||||
|
||||
|
||||
class DelAppend:
|
||||
def __init__(self, lst, item):
|
||||
self.lst = lst
|
||||
self.item = item
|
||||
|
||||
def __del__(self):
|
||||
self.lst.append(self.item)
|
||||
|
||||
|
||||
class CAPITest(unittest.TestCase):
|
||||
def test_check(self):
|
||||
# Test PyList_Check()
|
||||
check = _testlimitedcapi.list_check
|
||||
self.assertTrue(check([1, 2]))
|
||||
self.assertTrue(check([]))
|
||||
self.assertTrue(check(ListSubclass([1, 2])))
|
||||
self.assertFalse(check({1: 2}))
|
||||
self.assertFalse(check((1, 2)))
|
||||
self.assertFalse(check(42))
|
||||
self.assertFalse(check(object()))
|
||||
|
||||
# CRASHES check(NULL)
|
||||
|
||||
|
||||
def test_list_check_exact(self):
|
||||
# Test PyList_CheckExact()
|
||||
check = _testlimitedcapi.list_check_exact
|
||||
self.assertTrue(check([1]))
|
||||
self.assertTrue(check([]))
|
||||
self.assertFalse(check(ListSubclass([1])))
|
||||
self.assertFalse(check(UserList([1, 2])))
|
||||
self.assertFalse(check({1: 2}))
|
||||
self.assertFalse(check(object()))
|
||||
|
||||
# CRASHES check(NULL)
|
||||
|
||||
def test_list_new(self):
|
||||
# Test PyList_New()
|
||||
list_new = _testlimitedcapi.list_new
|
||||
lst = list_new(0)
|
||||
self.assertEqual(lst, [])
|
||||
self.assertIs(type(lst), list)
|
||||
lst2 = list_new(0)
|
||||
self.assertIsNot(lst2, lst)
|
||||
self.assertRaises(SystemError, list_new, NULL)
|
||||
self.assertRaises(SystemError, list_new, -1)
|
||||
|
||||
def test_list_size(self):
|
||||
# Test PyList_Size()
|
||||
size = _testlimitedcapi.list_size
|
||||
self.assertEqual(size([]), 0)
|
||||
self.assertEqual(size([1, 2]), 2)
|
||||
self.assertEqual(size(ListSubclass([1, 2])), 2)
|
||||
self.assertRaises(SystemError, size, UserList())
|
||||
self.assertRaises(SystemError, size, {})
|
||||
self.assertRaises(SystemError, size, 23)
|
||||
self.assertRaises(SystemError, size, object())
|
||||
# CRASHES size(NULL)
|
||||
|
||||
def test_list_get_size(self):
|
||||
# Test PyList_GET_SIZE()
|
||||
size = _testcapi.list_get_size
|
||||
self.assertEqual(size([]), 0)
|
||||
self.assertEqual(size([1, 2]), 2)
|
||||
self.assertEqual(size(ListSubclass([1, 2])), 2)
|
||||
# CRASHES size(object())
|
||||
# CRASHES size(23)
|
||||
# CRASHES size({})
|
||||
# CRASHES size(UserList())
|
||||
# CRASHES size(NULL)
|
||||
|
||||
def check_list_get_item(self, getitem, exctype):
|
||||
# Common test cases for PyList_GetItem() and PyList_GetItemRef()
|
||||
lst = [1, 2, 3]
|
||||
self.assertEqual(getitem(lst, 0), 1)
|
||||
self.assertEqual(getitem(lst, 2), 3)
|
||||
self.assertRaises(IndexError, getitem, lst, 3)
|
||||
self.assertRaises(IndexError, getitem, lst, -1)
|
||||
self.assertRaises(IndexError, getitem, lst, PY_SSIZE_T_MIN)
|
||||
self.assertRaises(IndexError, getitem, lst, PY_SSIZE_T_MAX)
|
||||
self.assertRaises(exctype, getitem, 42, 1)
|
||||
self.assertRaises(exctype, getitem, (1, 2, 3), 1)
|
||||
self.assertRaises(exctype, getitem, {1: 2}, 1)
|
||||
# CRASHES getitem(NULL, 1)
|
||||
|
||||
def test_list_getitem(self):
|
||||
# Test PyList_GetItem()
|
||||
self.check_list_get_item(_testlimitedcapi.list_getitem, SystemError)
|
||||
|
||||
def test_list_get_item_ref(self):
|
||||
# Test PyList_GetItemRef()
|
||||
self.check_list_get_item(_testlimitedcapi.list_get_item_ref, TypeError)
|
||||
|
||||
def test_list_get_item(self):
|
||||
# Test PyList_GET_ITEM()
|
||||
get_item = _testcapi.list_get_item
|
||||
lst = [1, 2, [1, 2, 3]]
|
||||
self.assertEqual(get_item(lst, 0), 1)
|
||||
self.assertEqual(get_item(lst, 2), [1, 2, 3])
|
||||
|
||||
# CRASHES for out of index: get_item(lst, 3)
|
||||
# CRASHES for get_item(lst, PY_SSIZE_T_MIN)
|
||||
# CRASHES for get_item(lst, PY_SSIZE_T_MAX)
|
||||
# CRASHES get_item(21, 2)
|
||||
# CRASHES get_item(NULL, 1)
|
||||
|
||||
def test_list_setitem(self):
|
||||
# Test PyList_SetItem()
|
||||
setitem = _testlimitedcapi.list_setitem
|
||||
lst = [1, 2, 3]
|
||||
setitem(lst, 0, 10)
|
||||
self.assertEqual(lst, [10, 2, 3])
|
||||
setitem(lst, 2, 12)
|
||||
self.assertEqual(lst, [10, 2, 12])
|
||||
self.assertRaises(IndexError, setitem, lst, 3 , 5)
|
||||
self.assertRaises(IndexError, setitem, lst, -1, 5)
|
||||
self.assertRaises(IndexError, setitem, lst, PY_SSIZE_T_MIN, 5)
|
||||
self.assertRaises(IndexError, setitem, lst, PY_SSIZE_T_MAX, 5)
|
||||
self.assertRaises(SystemError, setitem, (1, 2, 3), 1, 5)
|
||||
self.assertRaises(SystemError, setitem, {1: 2}, 1, 5)
|
||||
|
||||
# CRASHES setitem(NULL, 'a', 5)
|
||||
|
||||
def test_list_set_item(self):
|
||||
# Test PyList_SET_ITEM()
|
||||
set_item = _testcapi.list_set_item
|
||||
lst = [1, 2, 3]
|
||||
set_item(lst, 1, 10)
|
||||
set_item(lst, 2, [1, 2, 3])
|
||||
self.assertEqual(lst, [1, 10, [1, 2, 3]])
|
||||
|
||||
# CRASHES for set_item([1], -1, 5)
|
||||
# CRASHES for set_item([1], PY_SSIZE_T_MIN, 5)
|
||||
# CRASHES for set_item([1], PY_SSIZE_T_MAX, 5)
|
||||
# CRASHES for set_item([], 0, 1)
|
||||
# CRASHES for set_item(NULL, 0, 1)
|
||||
|
||||
|
||||
def test_list_insert(self):
|
||||
# Test PyList_Insert()
|
||||
insert = _testlimitedcapi.list_insert
|
||||
lst = [1, 2, 3]
|
||||
insert(lst, 0, 23)
|
||||
self.assertEqual(lst, [23, 1, 2, 3])
|
||||
insert(lst, -1, 22)
|
||||
self.assertEqual(lst, [23, 1, 2, 22, 3])
|
||||
insert(lst, PY_SSIZE_T_MIN, 1)
|
||||
self.assertEqual(lst[0], 1)
|
||||
insert(lst, len(lst), 123)
|
||||
self.assertEqual(lst[-1], 123)
|
||||
insert(lst, len(lst)-1, 124)
|
||||
self.assertEqual(lst[-2], 124)
|
||||
insert(lst, PY_SSIZE_T_MAX, 223)
|
||||
self.assertEqual(lst[-1], 223)
|
||||
|
||||
self.assertRaises(SystemError, insert, (1, 2, 3), 1, 5)
|
||||
self.assertRaises(SystemError, insert, {1: 2}, 1, 5)
|
||||
|
||||
# CRASHES insert(NULL, 1, 5)
|
||||
|
||||
def test_list_append(self):
|
||||
# Test PyList_Append()
|
||||
append = _testlimitedcapi.list_append
|
||||
lst = [1, 2, 3]
|
||||
append(lst, 10)
|
||||
self.assertEqual(lst, [1, 2, 3, 10])
|
||||
append(lst, [4, 5])
|
||||
self.assertEqual(lst, [1, 2, 3, 10, [4, 5]])
|
||||
self.assertRaises(SystemError, append, lst, NULL)
|
||||
self.assertRaises(SystemError, append, (), 0)
|
||||
self.assertRaises(SystemError, append, 42, 0)
|
||||
# CRASHES append(NULL, 0)
|
||||
|
||||
def test_list_getslice(self):
|
||||
# Test PyList_GetSlice()
|
||||
getslice = _testlimitedcapi.list_getslice
|
||||
lst = [1, 2, 3]
|
||||
|
||||
# empty
|
||||
self.assertEqual(getslice(lst, PY_SSIZE_T_MIN, 0), [])
|
||||
self.assertEqual(getslice(lst, -1, 0), [])
|
||||
self.assertEqual(getslice(lst, 3, PY_SSIZE_T_MAX), [])
|
||||
|
||||
# slice
|
||||
self.assertEqual(getslice(lst, 1, 3), [2, 3])
|
||||
|
||||
# whole
|
||||
self.assertEqual(getslice(lst, 0, len(lst)), lst)
|
||||
self.assertEqual(getslice(lst, 0, 100), lst)
|
||||
self.assertEqual(getslice(lst, -100, 100), lst)
|
||||
|
||||
self.assertRaises(SystemError, getslice, (1, 2, 3), 0, 0)
|
||||
self.assertRaises(SystemError, getslice, 'abc', 0, 0)
|
||||
self.assertRaises(SystemError, getslice, 42, 0, 0)
|
||||
|
||||
# CRASHES getslice(NULL, 0, 0)
|
||||
|
||||
def test_list_setslice(self):
|
||||
# Test PyList_SetSlice()
|
||||
list_setslice = _testlimitedcapi.list_setslice
|
||||
def set_slice(lst, low, high, value):
|
||||
lst = lst.copy()
|
||||
self.assertEqual(list_setslice(lst, low, high, value), 0)
|
||||
return lst
|
||||
|
||||
# insert items
|
||||
self.assertEqual(set_slice([], 0, 0, list("abc")), list("abc"))
|
||||
self.assertEqual(set_slice([], PY_SSIZE_T_MIN, PY_SSIZE_T_MIN, list("abc")), list("abc"))
|
||||
self.assertEqual(set_slice([], PY_SSIZE_T_MAX, PY_SSIZE_T_MAX, list("abc")), list("abc"))
|
||||
lst = list("abc")
|
||||
self.assertEqual(set_slice(lst, 0, 0, ["X"]), list("Xabc"))
|
||||
self.assertEqual(set_slice(lst, 1, 1, list("XY")), list("aXYbc"))
|
||||
self.assertEqual(set_slice(lst, len(lst), len(lst), ["X"]), list("abcX"))
|
||||
# self.assertEqual(set_slice(lst, PY_SSIZE_T_MAX, PY_SSIZE_T_MAX, ["X"]), list("abcX"))
|
||||
|
||||
# replace items
|
||||
lst = list("abc")
|
||||
self.assertEqual(set_slice(lst, -100, 1, list("X")), list("Xbc"))
|
||||
self.assertEqual(set_slice(lst, 1, 2, list("X")), list("aXc"))
|
||||
self.assertEqual(set_slice(lst, 1, 3, list("XY")), list("aXY"))
|
||||
self.assertEqual(set_slice(lst, 0, 3, list("XYZ")), list("XYZ"))
|
||||
|
||||
# delete items
|
||||
lst = list("abcdef")
|
||||
self.assertEqual(set_slice(lst, 0, len(lst), []), [])
|
||||
self.assertEqual(set_slice(lst, -100, 100, []), [])
|
||||
self.assertEqual(set_slice(lst, 1, 5, []), list("af"))
|
||||
self.assertEqual(set_slice(lst, 3, len(lst), []), list("abc"))
|
||||
|
||||
# delete items with NULL
|
||||
lst = list("abcdef")
|
||||
self.assertEqual(set_slice(lst, 0, len(lst), NULL), [])
|
||||
self.assertEqual(set_slice(lst, 3, len(lst), NULL), list("abc"))
|
||||
|
||||
self.assertRaises(SystemError, list_setslice, (), 0, 0, [])
|
||||
self.assertRaises(SystemError, list_setslice, 42, 0, 0, [])
|
||||
|
||||
# Item finalizer modify the list (clear the list)
|
||||
lst = []
|
||||
lst.append(DelAppend(lst, 'zombie'))
|
||||
self.assertEqual(list_setslice(lst, 0, len(lst), NULL), 0)
|
||||
self.assertEqual(lst, ['zombie'])
|
||||
|
||||
# Item finalizer modify the list (remove an list item)
|
||||
lst = []
|
||||
lst.append(DelAppend(lst, 'zombie'))
|
||||
lst.extend("abc")
|
||||
self.assertEqual(list_setslice(lst, 0, 1, NULL), 0)
|
||||
self.assertEqual(lst, ['a', 'b', 'c', 'zombie'])
|
||||
|
||||
# CRASHES setslice(NULL, 0, 0, [])
|
||||
|
||||
def test_list_sort(self):
|
||||
# Test PyList_Sort()
|
||||
sort = _testlimitedcapi.list_sort
|
||||
lst = [4, 6, 7, 3, 1, 5, 9, 2, 0, 8]
|
||||
sort(lst)
|
||||
self.assertEqual(lst, list(range(10)))
|
||||
|
||||
lst2 = ListSubclass([4, 6, 7, 3, 1, 5, 9, 2, 0, 8])
|
||||
sort(lst2)
|
||||
self.assertEqual(lst2, list(range(10)))
|
||||
|
||||
self.assertRaises(SystemError, sort, ())
|
||||
self.assertRaises(SystemError, sort, object())
|
||||
self.assertRaises(SystemError, sort, NULL)
|
||||
|
||||
|
||||
def test_list_reverse(self):
|
||||
# Test PyList_Reverse()
|
||||
reverse = _testlimitedcapi.list_reverse
|
||||
def list_reverse(lst):
|
||||
self.assertEqual(reverse(lst), 0)
|
||||
return lst
|
||||
|
||||
self.assertEqual(list_reverse([]), [])
|
||||
self.assertEqual(list_reverse([2, 5, 10]), [10, 5, 2])
|
||||
self.assertEqual(list_reverse(list_reverse([2, 5, 10])), [2, 5, 10])
|
||||
|
||||
self.assertRaises(SystemError, reverse, ())
|
||||
self.assertRaises(SystemError, reverse, object())
|
||||
self.assertRaises(SystemError, reverse, NULL)
|
||||
|
||||
def test_list_astuple(self):
|
||||
# Test PyList_AsTuple()
|
||||
astuple = _testlimitedcapi.list_astuple
|
||||
self.assertEqual(astuple([]), ())
|
||||
self.assertEqual(astuple([[]]), ([],))
|
||||
self.assertEqual(astuple([2, 5, 10]), (2, 5, 10))
|
||||
|
||||
self.assertRaises(SystemError, astuple, ())
|
||||
self.assertRaises(SystemError, astuple, object())
|
||||
self.assertRaises(SystemError, astuple, NULL)
|
||||
|
||||
def test_list_clear(self):
|
||||
# Test PyList_Clear()
|
||||
list_clear = _testcapi.list_clear
|
||||
|
||||
lst = [1, 2, 3]
|
||||
self.assertEqual(list_clear(lst), 0)
|
||||
self.assertEqual(lst, [])
|
||||
|
||||
lst = []
|
||||
self.assertEqual(list_clear(lst), 0)
|
||||
self.assertEqual(lst, [])
|
||||
|
||||
self.assertRaises(SystemError, list_clear, ())
|
||||
self.assertRaises(SystemError, list_clear, object())
|
||||
|
||||
# Item finalizer modify the list
|
||||
lst = []
|
||||
lst.append(DelAppend(lst, 'zombie'))
|
||||
list_clear(lst)
|
||||
self.assertEqual(lst, ['zombie'])
|
||||
|
||||
# CRASHES list_clear(NULL)
|
||||
|
||||
def test_list_extend(self):
|
||||
# Test PyList_Extend()
|
||||
list_extend = _testcapi.list_extend
|
||||
|
||||
for other_type in (list, tuple, str, iter):
|
||||
lst = list("ab")
|
||||
arg = other_type("def")
|
||||
self.assertEqual(list_extend(lst, arg), 0)
|
||||
self.assertEqual(lst, list("abdef"))
|
||||
|
||||
# PyList_Extend(lst, lst)
|
||||
lst = list("abc")
|
||||
self.assertEqual(list_extend(lst, lst), 0)
|
||||
self.assertEqual(lst, list("abcabc"))
|
||||
|
||||
self.assertRaises(TypeError, list_extend, [], object())
|
||||
self.assertRaises(SystemError, list_extend, (), list("abc"))
|
||||
|
||||
# CRASHES list_extend(NULL, [])
|
||||
# CRASHES list_extend([], NULL)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
619
Dependencies/Python/Lib/test/test_capi/test_long.py
vendored
Normal file
619
Dependencies/Python/Lib/test/test_capi/test_long.py
vendored
Normal file
@ -0,0 +1,619 @@
|
||||
import unittest
|
||||
import sys
|
||||
import test.support as support
|
||||
|
||||
from test.support import import_helper
|
||||
|
||||
# Skip this test if the _testcapi and _testlimitedcapi modules isn't available.
|
||||
_testcapi = import_helper.import_module('_testcapi')
|
||||
_testlimitedcapi = import_helper.import_module('_testlimitedcapi')
|
||||
|
||||
NULL = None
|
||||
|
||||
class IntSubclass(int):
|
||||
pass
|
||||
|
||||
class Index:
|
||||
def __init__(self, value):
|
||||
self.value = value
|
||||
|
||||
def __index__(self):
|
||||
return self.value
|
||||
|
||||
# use __index__(), not __int__()
|
||||
class MyIndexAndInt:
|
||||
def __index__(self):
|
||||
return 10
|
||||
def __int__(self):
|
||||
return 22
|
||||
|
||||
|
||||
class LongTests(unittest.TestCase):
|
||||
|
||||
def test_compact(self):
|
||||
for n in {
|
||||
# Edge cases
|
||||
*(2**n for n in range(66)),
|
||||
*(-2**n for n in range(66)),
|
||||
*(2**n - 1 for n in range(66)),
|
||||
*(-2**n + 1 for n in range(66)),
|
||||
# Essentially random
|
||||
*(37**n for n in range(14)),
|
||||
*(-37**n for n in range(14)),
|
||||
}:
|
||||
with self.subTest(n=n):
|
||||
is_compact, value = _testcapi.call_long_compact_api(n)
|
||||
if is_compact:
|
||||
self.assertEqual(n, value)
|
||||
|
||||
def test_compact_known(self):
|
||||
# Sanity-check some implementation details (we don't guarantee
|
||||
# that these are/aren't compact)
|
||||
self.assertEqual(_testcapi.call_long_compact_api(-1), (True, -1))
|
||||
self.assertEqual(_testcapi.call_long_compact_api(0), (True, 0))
|
||||
self.assertEqual(_testcapi.call_long_compact_api(256), (True, 256))
|
||||
self.assertEqual(_testcapi.call_long_compact_api(sys.maxsize),
|
||||
(False, -1))
|
||||
|
||||
def test_long_check(self):
|
||||
# Test PyLong_Check()
|
||||
check = _testlimitedcapi.pylong_check
|
||||
self.assertTrue(check(1))
|
||||
self.assertTrue(check(123456789012345678901234567890))
|
||||
self.assertTrue(check(-1))
|
||||
self.assertTrue(check(True))
|
||||
self.assertTrue(check(IntSubclass(1)))
|
||||
self.assertFalse(check(1.0))
|
||||
self.assertFalse(check(object()))
|
||||
# CRASHES check(NULL)
|
||||
|
||||
def test_long_checkexact(self):
|
||||
# Test PyLong_CheckExact()
|
||||
check = _testlimitedcapi.pylong_checkexact
|
||||
self.assertTrue(check(1))
|
||||
self.assertTrue(check(123456789012345678901234567890))
|
||||
self.assertTrue(check(-1))
|
||||
self.assertFalse(check(True))
|
||||
self.assertFalse(check(IntSubclass(1)))
|
||||
self.assertFalse(check(1.0))
|
||||
self.assertFalse(check(object()))
|
||||
# CRASHES check(NULL)
|
||||
|
||||
def test_long_fromdouble(self):
|
||||
# Test PyLong_FromDouble()
|
||||
fromdouble = _testlimitedcapi.pylong_fromdouble
|
||||
float_max = sys.float_info.max
|
||||
for value in (5.0, 5.1, 5.9, -5.1, -5.9, 0.0, -0.0, float_max, -float_max):
|
||||
with self.subTest(value=value):
|
||||
self.assertEqual(fromdouble(value), int(value))
|
||||
self.assertRaises(OverflowError, fromdouble, float('inf'))
|
||||
self.assertRaises(OverflowError, fromdouble, float('-inf'))
|
||||
self.assertRaises(ValueError, fromdouble, float('nan'))
|
||||
|
||||
def test_long_fromvoidptr(self):
|
||||
# Test PyLong_FromVoidPtr()
|
||||
fromvoidptr = _testlimitedcapi.pylong_fromvoidptr
|
||||
obj = object()
|
||||
x = fromvoidptr(obj)
|
||||
y = fromvoidptr(NULL)
|
||||
self.assertIsInstance(x, int)
|
||||
self.assertGreaterEqual(x, 0)
|
||||
self.assertIsInstance(y, int)
|
||||
self.assertEqual(y, 0)
|
||||
self.assertNotEqual(x, y)
|
||||
|
||||
def test_long_fromstring(self):
|
||||
# Test PyLong_FromString()
|
||||
fromstring = _testlimitedcapi.pylong_fromstring
|
||||
self.assertEqual(fromstring(b'123', 10), (123, 3))
|
||||
self.assertEqual(fromstring(b'cafe', 16), (0xcafe, 4))
|
||||
self.assertEqual(fromstring(b'xyz', 36), (44027, 3))
|
||||
self.assertEqual(fromstring(b'123', 0), (123, 3))
|
||||
self.assertEqual(fromstring(b'0xcafe', 0), (0xcafe, 6))
|
||||
self.assertRaises(ValueError, fromstring, b'cafe', 0)
|
||||
self.assertEqual(fromstring(b'-123', 10), (-123, 4))
|
||||
self.assertEqual(fromstring(b' -123 ', 10), (-123, 6))
|
||||
self.assertEqual(fromstring(b'1_23', 10), (123, 4))
|
||||
self.assertRaises(ValueError, fromstring, b'- 123', 10)
|
||||
self.assertRaises(ValueError, fromstring, b'', 10)
|
||||
|
||||
self.assertRaises(ValueError, fromstring, b'123', 1)
|
||||
self.assertRaises(ValueError, fromstring, b'123', -1)
|
||||
self.assertRaises(ValueError, fromstring, b'123', 37)
|
||||
|
||||
self.assertRaises(ValueError, fromstring, '١٢٣٤٥٦٧٨٩٠'.encode(), 0)
|
||||
self.assertRaises(ValueError, fromstring, '١٢٣٤٥٦٧٨٩٠'.encode(), 16)
|
||||
|
||||
self.assertEqual(fromstring(b'123\x00', 0), (123, 3))
|
||||
self.assertEqual(fromstring(b'123\x00456', 0), (123, 3))
|
||||
self.assertEqual(fromstring(b'123\x00', 16), (0x123, 3))
|
||||
self.assertEqual(fromstring(b'123\x00456', 16), (0x123, 3))
|
||||
|
||||
# CRASHES fromstring(NULL, 0)
|
||||
# CRASHES fromstring(NULL, 16)
|
||||
|
||||
def test_long_fromunicodeobject(self):
|
||||
# Test PyLong_FromUnicodeObject()
|
||||
fromunicodeobject = _testcapi.pylong_fromunicodeobject
|
||||
self.assertEqual(fromunicodeobject('123', 10), 123)
|
||||
self.assertEqual(fromunicodeobject('cafe', 16), 0xcafe)
|
||||
self.assertEqual(fromunicodeobject('xyz', 36), 44027)
|
||||
self.assertEqual(fromunicodeobject('123', 0), 123)
|
||||
self.assertEqual(fromunicodeobject('0xcafe', 0), 0xcafe)
|
||||
self.assertRaises(ValueError, fromunicodeobject, 'cafe', 0)
|
||||
self.assertEqual(fromunicodeobject('-123', 10), -123)
|
||||
self.assertEqual(fromunicodeobject(' -123 ', 10), -123)
|
||||
self.assertEqual(fromunicodeobject('1_23', 10), 123)
|
||||
self.assertRaises(ValueError, fromunicodeobject, '- 123', 10)
|
||||
self.assertRaises(ValueError, fromunicodeobject, '', 10)
|
||||
|
||||
self.assertRaises(ValueError, fromunicodeobject, '123', 1)
|
||||
self.assertRaises(ValueError, fromunicodeobject, '123', -1)
|
||||
self.assertRaises(ValueError, fromunicodeobject, '123', 37)
|
||||
|
||||
self.assertEqual(fromunicodeobject('١٢٣٤٥٦٧٨٩٠', 0), 1234567890)
|
||||
self.assertEqual(fromunicodeobject('١٢٣٤٥٦٧٨٩٠', 16), 0x1234567890)
|
||||
|
||||
self.assertRaises(ValueError, fromunicodeobject, '123\x00', 0)
|
||||
self.assertRaises(ValueError, fromunicodeobject, '123\x00456', 0)
|
||||
self.assertRaises(ValueError, fromunicodeobject, '123\x00', 16)
|
||||
self.assertRaises(ValueError, fromunicodeobject, '123\x00456', 16)
|
||||
|
||||
# CRASHES fromunicodeobject(NULL, 0)
|
||||
# CRASHES fromunicodeobject(NULL, 16)
|
||||
|
||||
def check_long_asint(self, func, min_val, max_val, *,
|
||||
use_index=True,
|
||||
mask=False,
|
||||
negative_value_error=OverflowError):
|
||||
# round trip (object -> C integer -> object)
|
||||
values = (0, 1, 1234, max_val)
|
||||
if min_val < 0:
|
||||
values += (-1, min_val)
|
||||
for value in values:
|
||||
with self.subTest(value=value):
|
||||
self.assertEqual(func(value), value)
|
||||
self.assertEqual(func(IntSubclass(value)), value)
|
||||
if use_index:
|
||||
self.assertEqual(func(Index(value)), value)
|
||||
|
||||
if use_index:
|
||||
self.assertEqual(func(MyIndexAndInt()), 10)
|
||||
else:
|
||||
self.assertRaises(TypeError, func, Index(42))
|
||||
self.assertRaises(TypeError, func, MyIndexAndInt())
|
||||
|
||||
if mask:
|
||||
self.assertEqual(func(min_val - 1), max_val)
|
||||
self.assertEqual(func(max_val + 1), min_val)
|
||||
self.assertEqual(func(-1 << 1000), 0)
|
||||
self.assertEqual(func(1 << 1000), 0)
|
||||
else:
|
||||
self.assertRaises(negative_value_error, func, min_val - 1)
|
||||
self.assertRaises(negative_value_error, func, -1 << 1000)
|
||||
self.assertRaises(OverflowError, func, max_val + 1)
|
||||
self.assertRaises(OverflowError, func, 1 << 1000)
|
||||
self.assertRaises(TypeError, func, 1.0)
|
||||
self.assertRaises(TypeError, func, b'2')
|
||||
self.assertRaises(TypeError, func, '3')
|
||||
self.assertRaises(SystemError, func, NULL)
|
||||
|
||||
def check_long_asintandoverflow(self, func, min_val, max_val):
|
||||
# round trip (object -> C integer -> object)
|
||||
for value in (min_val, max_val, -1, 0, 1, 1234):
|
||||
with self.subTest(value=value):
|
||||
self.assertEqual(func(value), (value, 0))
|
||||
self.assertEqual(func(IntSubclass(value)), (value, 0))
|
||||
self.assertEqual(func(Index(value)), (value, 0))
|
||||
|
||||
self.assertEqual(func(MyIndexAndInt()), (10, 0))
|
||||
|
||||
self.assertEqual(func(min_val - 1), (-1, -1))
|
||||
self.assertEqual(func(max_val + 1), (-1, +1))
|
||||
self.assertRaises(SystemError, func, None)
|
||||
self.assertRaises(TypeError, func, 1.0)
|
||||
|
||||
def test_long_asint(self):
|
||||
# Test PyLong_AsInt()
|
||||
PyLong_AsInt = _testlimitedcapi.PyLong_AsInt
|
||||
from _testcapi import INT_MIN, INT_MAX
|
||||
self.check_long_asint(PyLong_AsInt, INT_MIN, INT_MAX)
|
||||
|
||||
def test_long_aslong(self):
|
||||
# Test PyLong_AsLong() and PyLong_FromLong()
|
||||
aslong = _testlimitedcapi.pylong_aslong
|
||||
from _testcapi import LONG_MIN, LONG_MAX
|
||||
self.check_long_asint(aslong, LONG_MIN, LONG_MAX)
|
||||
|
||||
def test_long_aslongandoverflow(self):
|
||||
# Test PyLong_AsLongAndOverflow()
|
||||
aslongandoverflow = _testlimitedcapi.pylong_aslongandoverflow
|
||||
from _testcapi import LONG_MIN, LONG_MAX
|
||||
self.check_long_asintandoverflow(aslongandoverflow, LONG_MIN, LONG_MAX)
|
||||
|
||||
def test_long_asunsignedlong(self):
|
||||
# Test PyLong_AsUnsignedLong() and PyLong_FromUnsignedLong()
|
||||
asunsignedlong = _testlimitedcapi.pylong_asunsignedlong
|
||||
from _testcapi import ULONG_MAX
|
||||
self.check_long_asint(asunsignedlong, 0, ULONG_MAX,
|
||||
use_index=False)
|
||||
|
||||
def test_long_asunsignedlongmask(self):
|
||||
# Test PyLong_AsUnsignedLongMask()
|
||||
asunsignedlongmask = _testlimitedcapi.pylong_asunsignedlongmask
|
||||
from _testcapi import ULONG_MAX
|
||||
self.check_long_asint(asunsignedlongmask, 0, ULONG_MAX, mask=True)
|
||||
|
||||
def test_long_aslonglong(self):
|
||||
# Test PyLong_AsLongLong() and PyLong_FromLongLong()
|
||||
aslonglong = _testlimitedcapi.pylong_aslonglong
|
||||
from _testcapi import LLONG_MIN, LLONG_MAX
|
||||
self.check_long_asint(aslonglong, LLONG_MIN, LLONG_MAX)
|
||||
|
||||
def test_long_aslonglongandoverflow(self):
|
||||
# Test PyLong_AsLongLongAndOverflow()
|
||||
aslonglongandoverflow = _testlimitedcapi.pylong_aslonglongandoverflow
|
||||
from _testcapi import LLONG_MIN, LLONG_MAX
|
||||
self.check_long_asintandoverflow(aslonglongandoverflow, LLONG_MIN, LLONG_MAX)
|
||||
|
||||
def test_long_asunsignedlonglong(self):
|
||||
# Test PyLong_AsUnsignedLongLong() and PyLong_FromUnsignedLongLong()
|
||||
asunsignedlonglong = _testlimitedcapi.pylong_asunsignedlonglong
|
||||
from _testcapi import ULLONG_MAX
|
||||
self.check_long_asint(asunsignedlonglong, 0, ULLONG_MAX, use_index=False)
|
||||
|
||||
def test_long_asunsignedlonglongmask(self):
|
||||
# Test PyLong_AsUnsignedLongLongMask()
|
||||
asunsignedlonglongmask = _testlimitedcapi.pylong_asunsignedlonglongmask
|
||||
from _testcapi import ULLONG_MAX
|
||||
self.check_long_asint(asunsignedlonglongmask, 0, ULLONG_MAX, mask=True)
|
||||
|
||||
def test_long_as_ssize_t(self):
|
||||
# Test PyLong_AsSsize_t() and PyLong_FromSsize_t()
|
||||
as_ssize_t = _testlimitedcapi.pylong_as_ssize_t
|
||||
from _testcapi import PY_SSIZE_T_MIN, PY_SSIZE_T_MAX
|
||||
self.check_long_asint(as_ssize_t, PY_SSIZE_T_MIN, PY_SSIZE_T_MAX,
|
||||
use_index=False)
|
||||
|
||||
def test_long_as_size_t(self):
|
||||
# Test PyLong_AsSize_t() and PyLong_FromSize_t()
|
||||
as_size_t = _testlimitedcapi.pylong_as_size_t
|
||||
from _testcapi import SIZE_MAX
|
||||
self.check_long_asint(as_size_t, 0, SIZE_MAX, use_index=False)
|
||||
|
||||
def test_long_asdouble(self):
|
||||
# Test PyLong_AsDouble()
|
||||
asdouble = _testlimitedcapi.pylong_asdouble
|
||||
MAX = int(sys.float_info.max)
|
||||
for value in (-MAX, MAX, -1, 0, 1, 1234):
|
||||
with self.subTest(value=value):
|
||||
self.assertEqual(asdouble(value), float(value))
|
||||
self.assertIsInstance(asdouble(value), float)
|
||||
|
||||
self.assertEqual(asdouble(IntSubclass(42)), 42.0)
|
||||
self.assertRaises(TypeError, asdouble, Index(42))
|
||||
self.assertRaises(TypeError, asdouble, MyIndexAndInt())
|
||||
|
||||
self.assertRaises(OverflowError, asdouble, 2 * MAX)
|
||||
self.assertRaises(OverflowError, asdouble, -2 * MAX)
|
||||
self.assertRaises(TypeError, asdouble, 1.0)
|
||||
self.assertRaises(TypeError, asdouble, b'2')
|
||||
self.assertRaises(TypeError, asdouble, '3')
|
||||
self.assertRaises(SystemError, asdouble, NULL)
|
||||
|
||||
def test_long_asvoidptr(self):
|
||||
# Test PyLong_AsVoidPtr()
|
||||
fromvoidptr = _testlimitedcapi.pylong_fromvoidptr
|
||||
asvoidptr = _testlimitedcapi.pylong_asvoidptr
|
||||
obj = object()
|
||||
x = fromvoidptr(obj)
|
||||
y = fromvoidptr(NULL)
|
||||
self.assertIs(asvoidptr(x), obj)
|
||||
self.assertIs(asvoidptr(y), NULL)
|
||||
self.assertIs(asvoidptr(IntSubclass(x)), obj)
|
||||
|
||||
# negative values
|
||||
M = (1 << _testcapi.SIZEOF_VOID_P * 8)
|
||||
if x >= M//2:
|
||||
self.assertIs(asvoidptr(x - M), obj)
|
||||
if y >= M//2:
|
||||
self.assertIs(asvoidptr(y - M), NULL)
|
||||
|
||||
self.assertRaises(TypeError, asvoidptr, Index(x))
|
||||
self.assertRaises(TypeError, asvoidptr, object())
|
||||
self.assertRaises(OverflowError, asvoidptr, 2**1000)
|
||||
self.assertRaises(OverflowError, asvoidptr, -2**1000)
|
||||
# CRASHES asvoidptr(NULL)
|
||||
|
||||
def _test_long_aspid(self, aspid):
|
||||
# Test PyLong_AsPid()
|
||||
from _testcapi import SIZEOF_PID_T
|
||||
bits = 8 * SIZEOF_PID_T
|
||||
PID_T_MIN = -2**(bits-1)
|
||||
PID_T_MAX = 2**(bits-1) - 1
|
||||
self.check_long_asint(aspid, PID_T_MIN, PID_T_MAX)
|
||||
|
||||
def test_long_aspid(self):
|
||||
self._test_long_aspid(_testcapi.pylong_aspid)
|
||||
|
||||
def test_long_aspid_limited(self):
|
||||
self._test_long_aspid(_testlimitedcapi.pylong_aspid)
|
||||
|
||||
def test_long_asnativebytes(self):
|
||||
import math
|
||||
from _testcapi import (
|
||||
pylong_asnativebytes as asnativebytes,
|
||||
SIZE_MAX,
|
||||
)
|
||||
|
||||
# Abbreviate sizeof(Py_ssize_t) to SZ because we use it a lot
|
||||
SZ = int(math.ceil(math.log(SIZE_MAX + 1) / math.log(2)) / 8)
|
||||
MAX_SSIZE = 2 ** (SZ * 8 - 1) - 1
|
||||
MAX_USIZE = 2 ** (SZ * 8) - 1
|
||||
if support.verbose:
|
||||
print(f"SIZEOF_SIZE={SZ}\n{MAX_SSIZE=:016X}\n{MAX_USIZE=:016X}")
|
||||
|
||||
# These tests check that the requested buffer size is correct.
|
||||
# This matches our current implementation: We only specify that the
|
||||
# return value is a size *sufficient* to hold the result when queried
|
||||
# using n_bytes=0. If our implementation changes, feel free to update
|
||||
# the expectations here -- or loosen them to be range checks.
|
||||
# (i.e. 0 *could* be stored in 1 byte and 512 in 2)
|
||||
for v, expect in [
|
||||
(0, SZ),
|
||||
(512, SZ),
|
||||
(-512, SZ),
|
||||
(MAX_SSIZE, SZ),
|
||||
(MAX_USIZE, SZ + 1),
|
||||
(-MAX_SSIZE, SZ),
|
||||
(-MAX_USIZE, SZ + 1),
|
||||
(2**255-1, 32),
|
||||
(-(2**255-1), 32),
|
||||
(2**255, 33),
|
||||
(-(2**255), 33), # if you ask, we'll say 33, but 32 would do
|
||||
(2**256-1, 33),
|
||||
(-(2**256-1), 33),
|
||||
(2**256, 33),
|
||||
(-(2**256), 33),
|
||||
]:
|
||||
with self.subTest(f"sizeof-{v:X}"):
|
||||
buffer = bytearray(b"\x5a")
|
||||
self.assertEqual(expect, asnativebytes(v, buffer, 0, -1),
|
||||
"PyLong_AsNativeBytes(v, <unknown>, 0, -1)")
|
||||
self.assertEqual(buffer, b"\x5a",
|
||||
"buffer overwritten when it should not have been")
|
||||
# Also check via the __index__ path.
|
||||
# We pass Py_ASNATIVEBYTES_NATIVE_ENDIAN | ALLOW_INDEX
|
||||
self.assertEqual(expect, asnativebytes(Index(v), buffer, 0, 3 | 16),
|
||||
"PyLong_AsNativeBytes(Index(v), <unknown>, 0, -1)")
|
||||
self.assertEqual(buffer, b"\x5a",
|
||||
"buffer overwritten when it should not have been")
|
||||
|
||||
# Test that we populate n=2 bytes but do not overwrite more.
|
||||
buffer = bytearray(b"\x99"*3)
|
||||
self.assertEqual(2, asnativebytes(4, buffer, 2, 0), # BE
|
||||
"PyLong_AsNativeBytes(v, <3 byte buffer>, 2, 0) // BE")
|
||||
self.assertEqual(buffer, b"\x00\x04\x99")
|
||||
self.assertEqual(2, asnativebytes(4, buffer, 2, 1), # LE
|
||||
"PyLong_AsNativeBytes(v, <3 byte buffer>, 2, 1) // LE")
|
||||
self.assertEqual(buffer, b"\x04\x00\x99")
|
||||
|
||||
# We request as many bytes as `expect_be` contains, and always check
|
||||
# the result (both big and little endian). We check the return value
|
||||
# independently, since the buffer should always be filled correctly even
|
||||
# if we need more bytes
|
||||
for v, expect_be, expect_n in [
|
||||
(0, b'\x00', 1),
|
||||
(0, b'\x00' * 2, 2),
|
||||
(0, b'\x00' * 8, min(8, SZ)),
|
||||
(1, b'\x01', 1),
|
||||
(1, b'\x00' * 10 + b'\x01', min(11, SZ)),
|
||||
(42, b'\x2a', 1),
|
||||
(42, b'\x00' * 10 + b'\x2a', min(11, SZ)),
|
||||
(-1, b'\xff', 1),
|
||||
(-1, b'\xff' * 10, min(11, SZ)),
|
||||
(-42, b'\xd6', 1),
|
||||
(-42, b'\xff' * 10 + b'\xd6', min(11, SZ)),
|
||||
# Extracts 255 into a single byte, but requests 2
|
||||
# (this is currently a special case, and "should" request SZ)
|
||||
(255, b'\xff', 2),
|
||||
(255, b'\x00\xff', 2),
|
||||
(256, b'\x01\x00', 2),
|
||||
(0x80, b'\x00' * 7 + b'\x80', min(8, SZ)),
|
||||
# Extracts successfully (unsigned), but requests 9 bytes
|
||||
(2**63, b'\x80' + b'\x00' * 7, 9),
|
||||
(2**63, b'\x00\x80' + b'\x00' * 7, 9),
|
||||
# Extracts into 8 bytes, but if you provide 9 we'll say 9
|
||||
(-2**63, b'\x80' + b'\x00' * 7, 8),
|
||||
(-2**63, b'\xff\x80' + b'\x00' * 7, 9),
|
||||
|
||||
(2**255-1, b'\x7f' + b'\xff' * 31, 32),
|
||||
(-(2**255-1), b'\x80' + b'\x00' * 30 + b'\x01', 32),
|
||||
# Request extra bytes, but result says we only needed 32
|
||||
(-(2**255-1), b'\xff\x80' + b'\x00' * 30 + b'\x01', 32),
|
||||
(-(2**255-1), b'\xff\xff\x80' + b'\x00' * 30 + b'\x01', 32),
|
||||
|
||||
# Extracting 256 bits of integer will request 33 bytes, but still
|
||||
# copy as many bits as possible into the buffer. So we *can* copy
|
||||
# into a 32-byte buffer, though negative number may be unrecoverable
|
||||
(2**256-1, b'\xff' * 32, 33),
|
||||
(2**256-1, b'\x00' + b'\xff' * 32, 33),
|
||||
(-(2**256-1), b'\x00' * 31 + b'\x01', 33),
|
||||
(-(2**256-1), b'\xff' + b'\x00' * 31 + b'\x01', 33),
|
||||
(-(2**256-1), b'\xff\xff' + b'\x00' * 31 + b'\x01', 33),
|
||||
# However, -2**255 precisely will extract into 32 bytes and return
|
||||
# success. For bigger buffers, it will still succeed, but will
|
||||
# return 33
|
||||
(-(2**255), b'\x80' + b'\x00' * 31, 32),
|
||||
(-(2**255), b'\xff\x80' + b'\x00' * 31, 33),
|
||||
|
||||
# The classic "Windows HRESULT as negative number" case
|
||||
# HRESULT hr;
|
||||
# PyLong_AsNativeBytes(<-2147467259>, &hr, sizeof(HRESULT), -1)
|
||||
# assert(hr == E_FAIL)
|
||||
(-2147467259, b'\x80\x00\x40\x05', 4),
|
||||
]:
|
||||
with self.subTest(f"{v:X}-{len(expect_be)}bytes"):
|
||||
n = len(expect_be)
|
||||
# Fill the buffer with dummy data to ensure all bytes
|
||||
# are overwritten.
|
||||
buffer = bytearray(b"\xa5"*n)
|
||||
expect_le = expect_be[::-1]
|
||||
|
||||
self.assertEqual(expect_n, asnativebytes(v, buffer, n, 0),
|
||||
f"PyLong_AsNativeBytes(v, buffer, {n}, <big>)")
|
||||
self.assertEqual(expect_be, buffer[:n], "<big>")
|
||||
self.assertEqual(expect_n, asnativebytes(v, buffer, n, 1),
|
||||
f"PyLong_AsNativeBytes(v, buffer, {n}, <little>)")
|
||||
self.assertEqual(expect_le, buffer[:n], "<little>")
|
||||
|
||||
# Test cases that do not request size for a sign bit when we pass the
|
||||
# Py_ASNATIVEBYTES_UNSIGNED_BUFFER flag
|
||||
for v, expect_be, expect_n in [
|
||||
(255, b'\xff', 1),
|
||||
# We pass a 2 byte buffer so it just uses the whole thing
|
||||
(255, b'\x00\xff', 2),
|
||||
|
||||
(2**63, b'\x80' + b'\x00' * 7, 8),
|
||||
# We pass a 9 byte buffer so it uses the whole thing
|
||||
(2**63, b'\x00\x80' + b'\x00' * 7, 9),
|
||||
|
||||
(2**256-1, b'\xff' * 32, 32),
|
||||
# We pass a 33 byte buffer so it uses the whole thing
|
||||
(2**256-1, b'\x00' + b'\xff' * 32, 33),
|
||||
]:
|
||||
with self.subTest(f"{v:X}-{len(expect_be)}bytes-unsigned"):
|
||||
n = len(expect_be)
|
||||
buffer = bytearray(b"\xa5"*n)
|
||||
self.assertEqual(expect_n, asnativebytes(v, buffer, n, 4),
|
||||
f"PyLong_AsNativeBytes(v, buffer, {n}, <big|unsigned>)")
|
||||
self.assertEqual(expect_n, asnativebytes(v, buffer, n, 5),
|
||||
f"PyLong_AsNativeBytes(v, buffer, {n}, <little|unsigned>)")
|
||||
|
||||
# Ensure Py_ASNATIVEBYTES_REJECT_NEGATIVE raises on negative value
|
||||
with self.assertRaises(ValueError):
|
||||
asnativebytes(-1, buffer, 0, 8)
|
||||
|
||||
# Ensure omitting Py_ASNATIVEBYTES_ALLOW_INDEX raises on __index__ value
|
||||
with self.assertRaises(TypeError):
|
||||
asnativebytes(Index(1), buffer, 0, -1)
|
||||
with self.assertRaises(TypeError):
|
||||
asnativebytes(Index(1), buffer, 0, 3)
|
||||
|
||||
# Check a few error conditions. These are validated in code, but are
|
||||
# unspecified in docs, so if we make changes to the implementation, it's
|
||||
# fine to just update these tests rather than preserve the behaviour.
|
||||
with self.assertRaises(TypeError):
|
||||
asnativebytes('not a number', buffer, 0, -1)
|
||||
|
||||
def test_long_asnativebytes_fuzz(self):
|
||||
import math
|
||||
from random import Random
|
||||
from _testcapi import (
|
||||
pylong_asnativebytes as asnativebytes,
|
||||
SIZE_MAX,
|
||||
)
|
||||
|
||||
# Abbreviate sizeof(Py_ssize_t) to SZ because we use it a lot
|
||||
SZ = int(math.ceil(math.log(SIZE_MAX + 1) / math.log(2)) / 8)
|
||||
|
||||
rng = Random()
|
||||
# Allocate bigger buffer than actual values are going to be
|
||||
buffer = bytearray(260)
|
||||
|
||||
for _ in range(1000):
|
||||
n = rng.randrange(1, 256)
|
||||
bytes_be = bytes([
|
||||
# Ensure the most significant byte is nonzero
|
||||
rng.randrange(1, 256),
|
||||
*[rng.randrange(256) for _ in range(n - 1)]
|
||||
])
|
||||
bytes_le = bytes_be[::-1]
|
||||
v = int.from_bytes(bytes_le, 'little')
|
||||
|
||||
expect_1 = expect_2 = (SZ, n)
|
||||
if bytes_be[0] & 0x80:
|
||||
# All values are positive, so if MSB is set, expect extra bit
|
||||
# when we request the size or have a large enough buffer
|
||||
expect_1 = (SZ, n + 1)
|
||||
# When passing Py_ASNATIVEBYTES_UNSIGNED_BUFFER, we expect the
|
||||
# return to be exactly the right size.
|
||||
expect_2 = (n,)
|
||||
|
||||
try:
|
||||
actual = asnativebytes(v, buffer, 0, -1)
|
||||
self.assertIn(actual, expect_1)
|
||||
|
||||
actual = asnativebytes(v, buffer, len(buffer), 0)
|
||||
self.assertIn(actual, expect_1)
|
||||
self.assertEqual(bytes_be, buffer[-n:])
|
||||
|
||||
actual = asnativebytes(v, buffer, len(buffer), 1)
|
||||
self.assertIn(actual, expect_1)
|
||||
self.assertEqual(bytes_le, buffer[:n])
|
||||
|
||||
actual = asnativebytes(v, buffer, n, 4)
|
||||
self.assertIn(actual, expect_2, bytes_be.hex())
|
||||
actual = asnativebytes(v, buffer, n, 5)
|
||||
self.assertIn(actual, expect_2, bytes_be.hex())
|
||||
except AssertionError as ex:
|
||||
value_hex = ''.join(reversed([
|
||||
f'{b:02X}{"" if i % 8 else "_"}'
|
||||
for i, b in enumerate(bytes_le, start=1)
|
||||
])).strip('_')
|
||||
if support.verbose:
|
||||
print()
|
||||
print(n, 'bytes')
|
||||
print('hex =', value_hex)
|
||||
print('int =', v)
|
||||
raise
|
||||
raise AssertionError(f"Value: 0x{value_hex}") from ex
|
||||
|
||||
def test_long_fromnativebytes(self):
|
||||
import math
|
||||
from _testcapi import (
|
||||
pylong_fromnativebytes as fromnativebytes,
|
||||
SIZE_MAX,
|
||||
)
|
||||
|
||||
# Abbreviate sizeof(Py_ssize_t) to SZ because we use it a lot
|
||||
SZ = int(math.ceil(math.log(SIZE_MAX + 1) / math.log(2)) / 8)
|
||||
MAX_SSIZE = 2 ** (SZ * 8 - 1) - 1
|
||||
MAX_USIZE = 2 ** (SZ * 8) - 1
|
||||
|
||||
for v_be, expect_s, expect_u in [
|
||||
(b'\x00', 0, 0),
|
||||
(b'\x01', 1, 1),
|
||||
(b'\xff', -1, 255),
|
||||
(b'\x00\xff', 255, 255),
|
||||
(b'\xff\xff', -1, 65535),
|
||||
]:
|
||||
with self.subTest(f"{expect_s}-{expect_u:X}-{len(v_be)}bytes"):
|
||||
n = len(v_be)
|
||||
v_le = v_be[::-1]
|
||||
|
||||
self.assertEqual(expect_s, fromnativebytes(v_be, n, 0, 1),
|
||||
f"PyLong_FromNativeBytes(buffer, {n}, <big>)")
|
||||
self.assertEqual(expect_s, fromnativebytes(v_le, n, 1, 1),
|
||||
f"PyLong_FromNativeBytes(buffer, {n}, <little>)")
|
||||
self.assertEqual(expect_u, fromnativebytes(v_be, n, 0, 0),
|
||||
f"PyLong_FromUnsignedNativeBytes(buffer, {n}, <big>)")
|
||||
self.assertEqual(expect_u, fromnativebytes(v_le, n, 1, 0),
|
||||
f"PyLong_FromUnsignedNativeBytes(buffer, {n}, <little>)")
|
||||
|
||||
# Check native endian when the result would be the same either
|
||||
# way and we can test it.
|
||||
if v_be == v_le:
|
||||
self.assertEqual(expect_s, fromnativebytes(v_be, n, -1, 1),
|
||||
f"PyLong_FromNativeBytes(buffer, {n}, <native>)")
|
||||
self.assertEqual(expect_u, fromnativebytes(v_be, n, -1, 0),
|
||||
f"PyLong_FromUnsignedNativeBytes(buffer, {n}, <native>)")
|
||||
|
||||
# Swap the unsigned request for tests and use the
|
||||
# Py_ASNATIVEBYTES_UNSIGNED_BUFFER flag instead
|
||||
self.assertEqual(expect_u, fromnativebytes(v_be, n, 4, 1),
|
||||
f"PyLong_FromNativeBytes(buffer, {n}, <big|unsigned>)")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
178
Dependencies/Python/Lib/test/test_capi/test_mem.py
vendored
Normal file
178
Dependencies/Python/Lib/test/test_capi/test_mem.py
vendored
Normal file
@ -0,0 +1,178 @@
|
||||
import re
|
||||
import textwrap
|
||||
import unittest
|
||||
|
||||
|
||||
from test import support
|
||||
from test.support import import_helper, requires_subprocess
|
||||
from test.support.script_helper import assert_python_failure, assert_python_ok
|
||||
|
||||
|
||||
# Skip this test if the _testcapi and _testinternalcapi extensions are not
|
||||
# available.
|
||||
_testcapi = import_helper.import_module('_testcapi')
|
||||
_testinternalcapi = import_helper.import_module('_testinternalcapi')
|
||||
|
||||
@requires_subprocess()
|
||||
class PyMemDebugTests(unittest.TestCase):
|
||||
PYTHONMALLOC = 'debug'
|
||||
# '0x04c06e0' or '04C06E0'
|
||||
PTR_REGEX = r'(?:0x)?[0-9a-fA-F]+'
|
||||
|
||||
def check(self, code):
|
||||
with support.SuppressCrashReport():
|
||||
out = assert_python_failure(
|
||||
'-c', code,
|
||||
PYTHONMALLOC=self.PYTHONMALLOC,
|
||||
# FreeBSD: instruct jemalloc to not fill freed() memory
|
||||
# with junk byte 0x5a, see JEMALLOC(3)
|
||||
MALLOC_CONF="junk:false",
|
||||
)
|
||||
stderr = out.err
|
||||
return stderr.decode('ascii', 'replace')
|
||||
|
||||
def test_buffer_overflow(self):
|
||||
out = self.check('import _testcapi; _testcapi.pymem_buffer_overflow()')
|
||||
regex = (r"Debug memory block at address p={ptr}: API 'm'\n"
|
||||
r" 16 bytes originally requested\n"
|
||||
r" The [0-9] pad bytes at p-[0-9] are FORBIDDENBYTE, as expected.\n"
|
||||
r" The [0-9] pad bytes at tail={ptr} are not all FORBIDDENBYTE \(0x[0-9a-f]{{2}}\):\n"
|
||||
r" at tail\+0: 0x78 \*\*\* OUCH\n"
|
||||
r" at tail\+1: 0xfd\n"
|
||||
r" at tail\+2: 0xfd\n"
|
||||
r" .*\n"
|
||||
r"( The block was made by call #[0-9]+ to debug malloc/realloc.\n)?"
|
||||
r" Data at p: cd cd cd .*\n"
|
||||
r"\n"
|
||||
r"Enable tracemalloc to get the memory block allocation traceback\n"
|
||||
r"\n"
|
||||
r"Fatal Python error: _PyMem_DebugRawFree: bad trailing pad byte")
|
||||
regex = regex.format(ptr=self.PTR_REGEX)
|
||||
regex = re.compile(regex, flags=re.DOTALL)
|
||||
self.assertRegex(out, regex)
|
||||
|
||||
def test_api_misuse(self):
|
||||
out = self.check('import _testcapi; _testcapi.pymem_api_misuse()')
|
||||
regex = (r"Debug memory block at address p={ptr}: API 'm'\n"
|
||||
r" 16 bytes originally requested\n"
|
||||
r" The [0-9] pad bytes at p-[0-9] are FORBIDDENBYTE, as expected.\n"
|
||||
r" The [0-9] pad bytes at tail={ptr} are FORBIDDENBYTE, as expected.\n"
|
||||
r"( The block was made by call #[0-9]+ to debug malloc/realloc.\n)?"
|
||||
r" Data at p: cd cd cd .*\n"
|
||||
r"\n"
|
||||
r"Enable tracemalloc to get the memory block allocation traceback\n"
|
||||
r"\n"
|
||||
r"Fatal Python error: _PyMem_DebugRawFree: bad ID: Allocated using API 'm', verified using API 'r'\n")
|
||||
regex = regex.format(ptr=self.PTR_REGEX)
|
||||
self.assertRegex(out, regex)
|
||||
|
||||
def check_malloc_without_gil(self, code):
|
||||
out = self.check(code)
|
||||
expected = ('Fatal Python error: _PyMem_DebugMalloc: '
|
||||
'Python memory allocator called without holding the GIL')
|
||||
self.assertIn(expected, out)
|
||||
|
||||
def test_pymem_malloc_without_gil(self):
|
||||
# Debug hooks must raise an error if PyMem_Malloc() is called
|
||||
# without holding the GIL
|
||||
code = 'import _testcapi; _testcapi.pymem_malloc_without_gil()'
|
||||
self.check_malloc_without_gil(code)
|
||||
|
||||
def test_pyobject_malloc_without_gil(self):
|
||||
# Debug hooks must raise an error if PyObject_Malloc() is called
|
||||
# without holding the GIL
|
||||
code = 'import _testcapi; _testcapi.pyobject_malloc_without_gil()'
|
||||
self.check_malloc_without_gil(code)
|
||||
|
||||
def check_pyobject_is_freed(self, func_name):
|
||||
code = textwrap.dedent(f'''
|
||||
import gc, os, sys, _testinternalcapi
|
||||
# Disable the GC to avoid crash on GC collection
|
||||
gc.disable()
|
||||
_testinternalcapi.{func_name}()
|
||||
# Exit immediately to avoid a crash while deallocating
|
||||
# the invalid object
|
||||
os._exit(0)
|
||||
''')
|
||||
assert_python_ok(
|
||||
'-c', code,
|
||||
PYTHONMALLOC=self.PYTHONMALLOC,
|
||||
MALLOC_CONF="junk:false",
|
||||
)
|
||||
|
||||
def test_pyobject_null_is_freed(self):
|
||||
self.check_pyobject_is_freed('check_pyobject_null_is_freed')
|
||||
|
||||
def test_pyobject_uninitialized_is_freed(self):
|
||||
self.check_pyobject_is_freed('check_pyobject_uninitialized_is_freed')
|
||||
|
||||
def test_pyobject_forbidden_bytes_is_freed(self):
|
||||
self.check_pyobject_is_freed('check_pyobject_forbidden_bytes_is_freed')
|
||||
|
||||
def test_pyobject_freed_is_freed(self):
|
||||
self.check_pyobject_is_freed('check_pyobject_freed_is_freed')
|
||||
|
||||
# Python built with Py_TRACE_REFS fail with a fatal error in
|
||||
# _PyRefchain_Trace() on memory allocation error.
|
||||
@unittest.skipIf(support.Py_TRACE_REFS, 'cannot test Py_TRACE_REFS build')
|
||||
def test_set_nomemory(self):
|
||||
code = """if 1:
|
||||
import _testcapi
|
||||
|
||||
class C(): pass
|
||||
|
||||
# The first loop tests both functions and that remove_mem_hooks()
|
||||
# can be called twice in a row. The second loop checks a call to
|
||||
# set_nomemory() after a call to remove_mem_hooks(). The third
|
||||
# loop checks the start and stop arguments of set_nomemory().
|
||||
for outer_cnt in range(1, 4):
|
||||
start = 10 * outer_cnt
|
||||
for j in range(100):
|
||||
if j == 0:
|
||||
if outer_cnt != 3:
|
||||
_testcapi.set_nomemory(start)
|
||||
else:
|
||||
_testcapi.set_nomemory(start, start + 1)
|
||||
try:
|
||||
C()
|
||||
except MemoryError as e:
|
||||
if outer_cnt != 3:
|
||||
_testcapi.remove_mem_hooks()
|
||||
print('MemoryError', outer_cnt, j)
|
||||
_testcapi.remove_mem_hooks()
|
||||
break
|
||||
"""
|
||||
rc, out, err = assert_python_ok('-c', code)
|
||||
lines = out.splitlines()
|
||||
for i, line in enumerate(lines, 1):
|
||||
self.assertIn(b'MemoryError', out)
|
||||
*_, count = line.split(b' ')
|
||||
count = int(count)
|
||||
self.assertLessEqual(count, i*10)
|
||||
self.assertGreaterEqual(count, i*10-4)
|
||||
|
||||
|
||||
# free-threading requires mimalloc (not malloc)
|
||||
@support.requires_gil_enabled()
|
||||
class PyMemMallocDebugTests(PyMemDebugTests):
|
||||
PYTHONMALLOC = 'malloc_debug'
|
||||
|
||||
|
||||
@unittest.skipUnless(support.with_pymalloc(), 'need pymalloc')
|
||||
class PyMemPymallocDebugTests(PyMemDebugTests):
|
||||
PYTHONMALLOC = 'pymalloc_debug'
|
||||
|
||||
|
||||
@unittest.skipUnless(support.with_mimalloc(), 'need mimaloc')
|
||||
class PyMemMimallocDebugTests(PyMemDebugTests):
|
||||
PYTHONMALLOC = 'mimalloc_debug'
|
||||
|
||||
|
||||
@unittest.skipUnless(support.Py_DEBUG, 'need Py_DEBUG')
|
||||
class PyMemDefaultTests(PyMemDebugTests):
|
||||
# test default allocator of Python compiled in debug mode
|
||||
PYTHONMALLOC = ''
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
3207
Dependencies/Python/Lib/test/test_capi/test_misc.py
vendored
Normal file
3207
Dependencies/Python/Lib/test/test_capi/test_misc.py
vendored
Normal file
File diff suppressed because it is too large
Load Diff
369
Dependencies/Python/Lib/test/test_capi/test_number.py
vendored
Normal file
369
Dependencies/Python/Lib/test/test_capi/test_number.py
vendored
Normal file
@ -0,0 +1,369 @@
|
||||
import itertools
|
||||
import operator
|
||||
import sys
|
||||
import unittest
|
||||
import warnings
|
||||
|
||||
from test.support import cpython_only, import_helper
|
||||
|
||||
_testcapi = import_helper.import_module('_testcapi')
|
||||
from _testcapi import PY_SSIZE_T_MAX, PY_SSIZE_T_MIN
|
||||
|
||||
try:
|
||||
from _testbuffer import ndarray
|
||||
except ImportError:
|
||||
ndarray = None
|
||||
|
||||
NULL = None
|
||||
|
||||
class BadDescr:
|
||||
def __get__(self, obj, objtype=None):
|
||||
raise RuntimeError
|
||||
|
||||
class WithDunder:
|
||||
def _meth(self, *args):
|
||||
if self.val:
|
||||
return self.val
|
||||
if self.exc:
|
||||
raise self.exc
|
||||
@classmethod
|
||||
def with_val(cls, val):
|
||||
obj = super().__new__(cls)
|
||||
obj.val = val
|
||||
obj.exc = None
|
||||
setattr(cls, cls.methname, cls._meth)
|
||||
return obj
|
||||
|
||||
@classmethod
|
||||
def with_exc(cls, exc):
|
||||
obj = super().__new__(cls)
|
||||
obj.val = None
|
||||
obj.exc = exc
|
||||
setattr(cls, cls.methname, cls._meth)
|
||||
return obj
|
||||
|
||||
class HasBadAttr:
|
||||
def __new__(cls):
|
||||
obj = super().__new__(cls)
|
||||
setattr(cls, cls.methname, BadDescr())
|
||||
return obj
|
||||
|
||||
|
||||
class IndexLike(WithDunder):
|
||||
methname = '__index__'
|
||||
|
||||
class IntLike(WithDunder):
|
||||
methname = '__int__'
|
||||
|
||||
class FloatLike(WithDunder):
|
||||
methname = '__float__'
|
||||
|
||||
|
||||
def subclassof(base):
|
||||
return type(base.__name__ + 'Subclass', (base,), {})
|
||||
|
||||
|
||||
class SomeError(Exception):
|
||||
pass
|
||||
|
||||
class OtherError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class CAPITest(unittest.TestCase):
|
||||
def test_check(self):
|
||||
# Test PyNumber_Check()
|
||||
check = _testcapi.number_check
|
||||
|
||||
self.assertTrue(check(1))
|
||||
self.assertTrue(check(IndexLike.with_val(1)))
|
||||
self.assertTrue(check(IntLike.with_val(99)))
|
||||
self.assertTrue(check(0.5))
|
||||
self.assertTrue(check(FloatLike.with_val(4.25)))
|
||||
self.assertTrue(check(1+2j))
|
||||
|
||||
self.assertFalse(check([]))
|
||||
self.assertFalse(check("abc"))
|
||||
self.assertFalse(check(object()))
|
||||
self.assertFalse(check(NULL))
|
||||
|
||||
def test_unary_ops(self):
|
||||
methmap = {'__neg__': _testcapi.number_negative, # PyNumber_Negative()
|
||||
'__pos__': _testcapi.number_positive, # PyNumber_Positive()
|
||||
'__abs__': _testcapi.number_absolute, # PyNumber_Absolute()
|
||||
'__invert__': _testcapi.number_invert} # PyNumber_Invert()
|
||||
|
||||
for name, func in methmap.items():
|
||||
# Generic object, has no tp_as_number structure
|
||||
self.assertRaises(TypeError, func, object())
|
||||
|
||||
# C-API function accepts NULL
|
||||
self.assertRaises(SystemError, func, NULL)
|
||||
|
||||
# Behave as corresponding unary operation
|
||||
op = getattr(operator, name)
|
||||
for x in [0, 42, -1, 3.14, 1+2j]:
|
||||
try:
|
||||
op(x)
|
||||
except TypeError:
|
||||
self.assertRaises(TypeError, func, x)
|
||||
else:
|
||||
self.assertEqual(func(x), op(x))
|
||||
|
||||
def test_binary_ops(self):
|
||||
methmap = {'__add__': _testcapi.number_add, # PyNumber_Add()
|
||||
'__sub__': _testcapi.number_subtract, # PyNumber_Subtract()
|
||||
'__mul__': _testcapi.number_multiply, # PyNumber_Multiply()
|
||||
'__matmul__': _testcapi.number_matrixmultiply, # PyNumber_MatrixMultiply()
|
||||
'__floordiv__': _testcapi.number_floordivide, # PyNumber_FloorDivide()
|
||||
'__truediv__': _testcapi.number_truedivide, # PyNumber_TrueDivide()
|
||||
'__mod__': _testcapi.number_remainder, # PyNumber_Remainder()
|
||||
'__divmod__': _testcapi.number_divmod, # PyNumber_Divmod()
|
||||
'__lshift__': _testcapi.number_lshift, # PyNumber_Lshift()
|
||||
'__rshift__': _testcapi.number_rshift, # PyNumber_Rshift()
|
||||
'__and__': _testcapi.number_and, # PyNumber_And()
|
||||
'__xor__': _testcapi.number_xor, # PyNumber_Xor()
|
||||
'__or__': _testcapi.number_or, # PyNumber_Or()
|
||||
'__pow__': _testcapi.number_power, # PyNumber_Power()
|
||||
'__iadd__': _testcapi.number_inplaceadd, # PyNumber_InPlaceAdd()
|
||||
'__isub__': _testcapi.number_inplacesubtract, # PyNumber_InPlaceSubtract()
|
||||
'__imul__': _testcapi.number_inplacemultiply, # PyNumber_InPlaceMultiply()
|
||||
'__imatmul__': _testcapi.number_inplacematrixmultiply, # PyNumber_InPlaceMatrixMultiply()
|
||||
'__ifloordiv__': _testcapi.number_inplacefloordivide, # PyNumber_InPlaceFloorDivide()
|
||||
'__itruediv__': _testcapi.number_inplacetruedivide, # PyNumber_InPlaceTrueDivide()
|
||||
'__imod__': _testcapi.number_inplaceremainder, # PyNumber_InPlaceRemainder()
|
||||
'__ilshift__': _testcapi.number_inplacelshift, # PyNumber_InPlaceLshift()
|
||||
'__irshift__': _testcapi.number_inplacershift, # PyNumber_InPlaceRshift()
|
||||
'__iand__': _testcapi.number_inplaceand, # PyNumber_InPlaceAnd()
|
||||
'__ixor__': _testcapi.number_inplacexor, # PyNumber_InPlaceXor()
|
||||
'__ior__': _testcapi.number_inplaceor, # PyNumber_InPlaceOr()
|
||||
'__ipow__': _testcapi.number_inplacepower, # PyNumber_InPlacePower()
|
||||
}
|
||||
|
||||
for name, func in methmap.items():
|
||||
cases = [0, 42, 3.14, -1, 123, 1+2j]
|
||||
|
||||
# Generic object, has no tp_as_number structure
|
||||
for x in cases:
|
||||
self.assertRaises(TypeError, func, object(), x)
|
||||
self.assertRaises(TypeError, func, x, object())
|
||||
|
||||
# Behave as corresponding binary operation
|
||||
op = getattr(operator, name, divmod)
|
||||
for x, y in itertools.combinations(cases, 2):
|
||||
try:
|
||||
op(x, y)
|
||||
except (TypeError, ValueError, ZeroDivisionError) as exc:
|
||||
self.assertRaises(exc.__class__, func, x, y)
|
||||
else:
|
||||
self.assertEqual(func(x, y), op(x, y))
|
||||
|
||||
# CRASHES func(NULL, object())
|
||||
# CRASHES func(object(), NULL)
|
||||
|
||||
@unittest.skipIf(ndarray is None, "needs _testbuffer")
|
||||
def test_misc_add(self):
|
||||
# PyNumber_Add(), PyNumber_InPlaceAdd()
|
||||
add = _testcapi.number_add
|
||||
inplaceadd = _testcapi.number_inplaceadd
|
||||
|
||||
# test sq_concat/sq_inplace_concat slots
|
||||
a, b, r = [1, 2], [3, 4], [1, 2, 3, 4]
|
||||
self.assertEqual(add(a, b), r)
|
||||
self.assertEqual(a, [1, 2])
|
||||
self.assertRaises(TypeError, add, ndarray([1], (1,)), 2)
|
||||
a, b, r = [1, 2], [3, 4], [1, 2, 3, 4]
|
||||
self.assertEqual(inplaceadd(a, b), r)
|
||||
self.assertEqual(a, r)
|
||||
self.assertRaises(TypeError, inplaceadd, ndarray([1], (1,)), 2)
|
||||
|
||||
@unittest.skipIf(ndarray is None, "needs _testbuffer")
|
||||
def test_misc_multiply(self):
|
||||
# PyNumber_Multiply(), PyNumber_InPlaceMultiply()
|
||||
multiply = _testcapi.number_multiply
|
||||
inplacemultiply = _testcapi.number_inplacemultiply
|
||||
|
||||
# test sq_repeat/sq_inplace_repeat slots
|
||||
a, b, r = [1], 2, [1, 1]
|
||||
self.assertEqual(multiply(a, b), r)
|
||||
self.assertEqual((a, b), ([1], 2))
|
||||
self.assertEqual(multiply(b, a), r)
|
||||
self.assertEqual((a, b), ([1], 2))
|
||||
self.assertEqual(multiply([1], -1), [])
|
||||
self.assertRaises(TypeError, multiply, ndarray([1], (1,)), 2)
|
||||
self.assertRaises(TypeError, multiply, [1], 0.5)
|
||||
self.assertRaises(OverflowError, multiply, [1], PY_SSIZE_T_MAX + 1)
|
||||
self.assertRaises(MemoryError, multiply, [1, 2], PY_SSIZE_T_MAX//2 + 1)
|
||||
a, b, r = [1], 2, [1, 1]
|
||||
self.assertEqual(inplacemultiply(a, b), r)
|
||||
self.assertEqual((a, b), (r, 2))
|
||||
a = [1]
|
||||
self.assertEqual(inplacemultiply(b, a), r)
|
||||
self.assertEqual((a, b), ([1], 2))
|
||||
self.assertRaises(TypeError, inplacemultiply, ndarray([1], (1,)), 2)
|
||||
self.assertRaises(OverflowError, inplacemultiply, [1], PY_SSIZE_T_MAX + 1)
|
||||
self.assertRaises(MemoryError, inplacemultiply, [1, 2], PY_SSIZE_T_MAX//2 + 1)
|
||||
|
||||
def test_misc_power(self):
|
||||
# PyNumber_Power(), PyNumber_InPlacePower()
|
||||
power = _testcapi.number_power
|
||||
inplacepower = _testcapi.number_inplacepower
|
||||
|
||||
class HasPow(WithDunder):
|
||||
methname = '__pow__'
|
||||
|
||||
# ternary op
|
||||
self.assertEqual(power(4, 11, 5), pow(4, 11, 5))
|
||||
self.assertRaises(TypeError, power, 4, 11, 1.25)
|
||||
self.assertRaises(TypeError, power, 4, 11, HasPow.with_val(NotImplemented))
|
||||
self.assertRaises(TypeError, power, 4, 11, object())
|
||||
self.assertEqual(inplacepower(4, 11, 5), pow(4, 11, 5))
|
||||
self.assertRaises(TypeError, inplacepower, 4, 11, 1.25)
|
||||
self.assertRaises(TypeError, inplacepower, 4, 11, object())
|
||||
|
||||
class X:
|
||||
def __pow__(*args):
|
||||
return args
|
||||
|
||||
x = X()
|
||||
self.assertEqual(power(x, 11), (x, 11))
|
||||
self.assertEqual(inplacepower(x, 11), (x, 11))
|
||||
self.assertEqual(power(x, 11, 5), (x, 11, 5))
|
||||
self.assertEqual(inplacepower(x, 11, 5), (x, 11, 5))
|
||||
|
||||
class X:
|
||||
def __rpow__(*args):
|
||||
return args
|
||||
|
||||
x = X()
|
||||
self.assertEqual(power(4, x), (x, 4))
|
||||
self.assertEqual(inplacepower(4, x), (x, 4))
|
||||
# XXX: Three-arg power doesn't use __rpow__.
|
||||
self.assertRaises(TypeError, power, 4, x, 5)
|
||||
self.assertRaises(TypeError, inplacepower, 4, x, 5)
|
||||
|
||||
class X:
|
||||
def __ipow__(*args):
|
||||
return args
|
||||
|
||||
x = X()
|
||||
self.assertEqual(inplacepower(x, 11), (x, 11))
|
||||
# XXX: In-place power doesn't pass the third arg to __ipow__.
|
||||
self.assertEqual(inplacepower(x, 11, 5), (x, 11))
|
||||
|
||||
@cpython_only
|
||||
def test_rshift_print(self):
|
||||
# This tests correct syntax hint for py2 redirection (>>).
|
||||
rshift = _testcapi.number_rshift
|
||||
|
||||
with self.assertRaises(TypeError) as context:
|
||||
rshift(print, 42)
|
||||
self.assertIn('Did you mean "print(<message>, '
|
||||
'file=<output_stream>)"?', str(context.exception))
|
||||
with self.assertRaises(TypeError) as context:
|
||||
rshift(max, sys.stderr)
|
||||
self.assertNotIn('Did you mean ', str(context.exception))
|
||||
with self.assertRaises(TypeError) as context:
|
||||
rshift(1, "spam")
|
||||
|
||||
def test_long(self):
|
||||
# Test PyNumber_Long()
|
||||
long = _testcapi.number_long
|
||||
|
||||
self.assertEqual(long(42), 42)
|
||||
self.assertEqual(long(1.25), 1)
|
||||
self.assertEqual(long("42"), 42)
|
||||
self.assertEqual(long(b"42"), 42)
|
||||
self.assertEqual(long(bytearray(b"42")), 42)
|
||||
self.assertEqual(long(memoryview(b"42")), 42)
|
||||
self.assertEqual(long(IndexLike.with_val(99)), 99)
|
||||
self.assertEqual(long(IntLike.with_val(99)), 99)
|
||||
|
||||
self.assertRaises(TypeError, long, IntLike.with_val(1.0))
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("error", DeprecationWarning)
|
||||
self.assertRaises(DeprecationWarning, long, IntLike.with_val(True))
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
self.assertEqual(long(IntLike.with_val(True)), 1)
|
||||
self.assertRaises(RuntimeError, long, IntLike.with_exc(RuntimeError))
|
||||
|
||||
self.assertRaises(TypeError, long, 1j)
|
||||
self.assertRaises(TypeError, long, object())
|
||||
self.assertRaises(SystemError, long, NULL)
|
||||
|
||||
def test_float(self):
|
||||
# Test PyNumber_Float()
|
||||
float_ = _testcapi.number_float
|
||||
|
||||
self.assertEqual(float_(1.25), 1.25)
|
||||
self.assertEqual(float_(123), 123.)
|
||||
self.assertEqual(float_("1.25"), 1.25)
|
||||
|
||||
self.assertEqual(float_(FloatLike.with_val(4.25)), 4.25)
|
||||
self.assertEqual(float_(IndexLike.with_val(99)), 99.0)
|
||||
self.assertEqual(float_(IndexLike.with_val(-1)), -1.0)
|
||||
|
||||
self.assertRaises(TypeError, float_, FloatLike.with_val(687))
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("error", DeprecationWarning)
|
||||
self.assertRaises(DeprecationWarning, float_, FloatLike.with_val(subclassof(float)(4.25)))
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
self.assertEqual(float_(FloatLike.with_val(subclassof(float)(4.25))), 4.25)
|
||||
self.assertRaises(RuntimeError, float_, FloatLike.with_exc(RuntimeError))
|
||||
|
||||
self.assertRaises(TypeError, float_, IndexLike.with_val(1.25))
|
||||
self.assertRaises(OverflowError, float_, IndexLike.with_val(2**2000))
|
||||
|
||||
self.assertRaises(TypeError, float_, 1j)
|
||||
self.assertRaises(TypeError, float_, object())
|
||||
self.assertRaises(SystemError, float_, NULL)
|
||||
|
||||
def test_index(self):
|
||||
# Test PyNumber_Index()
|
||||
index = _testcapi.number_index
|
||||
|
||||
self.assertEqual(index(11), 11)
|
||||
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("error", DeprecationWarning)
|
||||
self.assertRaises(DeprecationWarning, index, IndexLike.with_val(True))
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
self.assertEqual(index(IndexLike.with_val(True)), 1)
|
||||
self.assertRaises(TypeError, index, IndexLike.with_val(1.0))
|
||||
self.assertRaises(RuntimeError, index, IndexLike.with_exc(RuntimeError))
|
||||
|
||||
self.assertRaises(TypeError, index, 1.25)
|
||||
self.assertRaises(TypeError, index, "42")
|
||||
self.assertRaises(TypeError, index, object())
|
||||
self.assertRaises(SystemError, index, NULL)
|
||||
|
||||
def test_tobase(self):
|
||||
# Test PyNumber_ToBase()
|
||||
tobase = _testcapi.number_tobase
|
||||
|
||||
self.assertEqual(tobase(10, 2), bin(10))
|
||||
self.assertEqual(tobase(11, 8), oct(11))
|
||||
self.assertEqual(tobase(16, 10), str(16))
|
||||
self.assertEqual(tobase(13, 16), hex(13))
|
||||
|
||||
self.assertRaises(SystemError, tobase, NULL, 2)
|
||||
self.assertRaises(SystemError, tobase, 2, 3)
|
||||
self.assertRaises(TypeError, tobase, 1.25, 2)
|
||||
self.assertRaises(TypeError, tobase, "42", 2)
|
||||
|
||||
def test_asssizet(self):
|
||||
# Test PyNumber_AsSsize_t()
|
||||
asssizet = _testcapi.number_asssizet
|
||||
|
||||
for n in [*range(-6, 7), PY_SSIZE_T_MIN, PY_SSIZE_T_MAX]:
|
||||
self.assertEqual(asssizet(n, OverflowError), n)
|
||||
self.assertEqual(asssizet(PY_SSIZE_T_MAX+10, NULL), PY_SSIZE_T_MAX)
|
||||
self.assertEqual(asssizet(PY_SSIZE_T_MIN-10, NULL), PY_SSIZE_T_MIN)
|
||||
|
||||
self.assertRaises(OverflowError, asssizet, PY_SSIZE_T_MAX + 10, OverflowError)
|
||||
self.assertRaises(RuntimeError, asssizet, PY_SSIZE_T_MAX + 10, RuntimeError)
|
||||
self.assertRaises(SystemError, asssizet, NULL, TypeError)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
135
Dependencies/Python/Lib/test/test_capi/test_object.py
vendored
Normal file
135
Dependencies/Python/Lib/test/test_capi/test_object.py
vendored
Normal file
@ -0,0 +1,135 @@
|
||||
import enum
|
||||
import unittest
|
||||
from test.support import import_helper
|
||||
from test.support import os_helper
|
||||
|
||||
_testlimitedcapi = import_helper.import_module('_testlimitedcapi')
|
||||
_testcapi = import_helper.import_module('_testcapi')
|
||||
|
||||
|
||||
class Constant(enum.IntEnum):
|
||||
Py_CONSTANT_NONE = 0
|
||||
Py_CONSTANT_FALSE = 1
|
||||
Py_CONSTANT_TRUE = 2
|
||||
Py_CONSTANT_ELLIPSIS = 3
|
||||
Py_CONSTANT_NOT_IMPLEMENTED = 4
|
||||
Py_CONSTANT_ZERO = 5
|
||||
Py_CONSTANT_ONE = 6
|
||||
Py_CONSTANT_EMPTY_STR = 7
|
||||
Py_CONSTANT_EMPTY_BYTES = 8
|
||||
Py_CONSTANT_EMPTY_TUPLE = 9
|
||||
|
||||
INVALID_CONSTANT = Py_CONSTANT_EMPTY_TUPLE + 1
|
||||
|
||||
|
||||
class GetConstantTest(unittest.TestCase):
|
||||
def check_get_constant(self, get_constant):
|
||||
self.assertIs(get_constant(Constant.Py_CONSTANT_NONE), None)
|
||||
self.assertIs(get_constant(Constant.Py_CONSTANT_FALSE), False)
|
||||
self.assertIs(get_constant(Constant.Py_CONSTANT_TRUE), True)
|
||||
self.assertIs(get_constant(Constant.Py_CONSTANT_ELLIPSIS), Ellipsis)
|
||||
self.assertIs(get_constant(Constant.Py_CONSTANT_NOT_IMPLEMENTED), NotImplemented)
|
||||
|
||||
for constant_id, constant_type, value in (
|
||||
(Constant.Py_CONSTANT_ZERO, int, 0),
|
||||
(Constant.Py_CONSTANT_ONE, int, 1),
|
||||
(Constant.Py_CONSTANT_EMPTY_STR, str, ""),
|
||||
(Constant.Py_CONSTANT_EMPTY_BYTES, bytes, b""),
|
||||
(Constant.Py_CONSTANT_EMPTY_TUPLE, tuple, ()),
|
||||
):
|
||||
with self.subTest(constant_id=constant_id):
|
||||
obj = get_constant(constant_id)
|
||||
self.assertEqual(type(obj), constant_type, obj)
|
||||
self.assertEqual(obj, value)
|
||||
|
||||
with self.assertRaises(SystemError):
|
||||
get_constant(Constant.INVALID_CONSTANT)
|
||||
|
||||
def test_get_constant(self):
|
||||
self.check_get_constant(_testlimitedcapi.get_constant)
|
||||
|
||||
def test_get_constant_borrowed(self):
|
||||
self.check_get_constant(_testlimitedcapi.get_constant_borrowed)
|
||||
|
||||
|
||||
class PrintTest(unittest.TestCase):
|
||||
def testPyObjectPrintObject(self):
|
||||
|
||||
class PrintableObject:
|
||||
|
||||
def __repr__(self):
|
||||
return "spam spam spam"
|
||||
|
||||
def __str__(self):
|
||||
return "egg egg egg"
|
||||
|
||||
obj = PrintableObject()
|
||||
output_filename = os_helper.TESTFN
|
||||
self.addCleanup(os_helper.unlink, output_filename)
|
||||
|
||||
# Test repr printing
|
||||
_testcapi.call_pyobject_print(obj, output_filename, False)
|
||||
with open(output_filename, 'r') as output_file:
|
||||
self.assertEqual(output_file.read(), repr(obj))
|
||||
|
||||
# Test str printing
|
||||
_testcapi.call_pyobject_print(obj, output_filename, True)
|
||||
with open(output_filename, 'r') as output_file:
|
||||
self.assertEqual(output_file.read(), str(obj))
|
||||
|
||||
def testPyObjectPrintNULL(self):
|
||||
output_filename = os_helper.TESTFN
|
||||
self.addCleanup(os_helper.unlink, output_filename)
|
||||
|
||||
# Test repr printing
|
||||
_testcapi.pyobject_print_null(output_filename)
|
||||
with open(output_filename, 'r') as output_file:
|
||||
self.assertEqual(output_file.read(), '<nil>')
|
||||
|
||||
def testPyObjectPrintNoRefObject(self):
|
||||
output_filename = os_helper.TESTFN
|
||||
self.addCleanup(os_helper.unlink, output_filename)
|
||||
|
||||
# Test repr printing
|
||||
correct_output = _testcapi.pyobject_print_noref_object(output_filename)
|
||||
with open(output_filename, 'r') as output_file:
|
||||
self.assertEqual(output_file.read(), correct_output)
|
||||
|
||||
def testPyObjectPrintOSError(self):
|
||||
output_filename = os_helper.TESTFN
|
||||
self.addCleanup(os_helper.unlink, output_filename)
|
||||
|
||||
open(output_filename, "w+").close()
|
||||
with self.assertRaises(OSError):
|
||||
_testcapi.pyobject_print_os_error(output_filename)
|
||||
|
||||
|
||||
class ClearWeakRefsNoCallbacksTest(unittest.TestCase):
|
||||
"""Test PyUnstable_Object_ClearWeakRefsNoCallbacks"""
|
||||
def test_ClearWeakRefsNoCallbacks(self):
|
||||
"""Ensure PyUnstable_Object_ClearWeakRefsNoCallbacks works"""
|
||||
import weakref
|
||||
import gc
|
||||
class C:
|
||||
pass
|
||||
obj = C()
|
||||
messages = []
|
||||
ref = weakref.ref(obj, lambda: messages.append("don't add this"))
|
||||
self.assertIs(ref(), obj)
|
||||
self.assertFalse(messages)
|
||||
_testcapi.pyobject_clear_weakrefs_no_callbacks(obj)
|
||||
self.assertIsNone(ref())
|
||||
gc.collect()
|
||||
self.assertFalse(messages)
|
||||
|
||||
def test_ClearWeakRefsNoCallbacks_no_weakref_support(self):
|
||||
"""Don't fail on objects that don't support weakrefs"""
|
||||
import weakref
|
||||
obj = object()
|
||||
with self.assertRaises(TypeError):
|
||||
ref = weakref.ref(obj)
|
||||
_testcapi.pyobject_clear_weakrefs_no_callbacks(obj)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
1338
Dependencies/Python/Lib/test/test_capi/test_opt.py
vendored
Normal file
1338
Dependencies/Python/Lib/test/test_capi/test_opt.py
vendored
Normal file
File diff suppressed because it is too large
Load Diff
15
Dependencies/Python/Lib/test/test_capi/test_pyatomic.py
vendored
Normal file
15
Dependencies/Python/Lib/test/test_capi/test_pyatomic.py
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
import unittest
|
||||
from test.support import import_helper
|
||||
|
||||
# Skip this test if the _testcapi module isn't available.
|
||||
_testcapi = import_helper.import_module('_testcapi')
|
||||
|
||||
class PyAtomicTests(unittest.TestCase):
|
||||
pass
|
||||
|
||||
for name in sorted(dir(_testcapi)):
|
||||
if name.startswith('test_atomic'):
|
||||
setattr(PyAtomicTests, name, getattr(_testcapi, name))
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
118
Dependencies/Python/Lib/test/test_capi/test_run.py
vendored
Normal file
118
Dependencies/Python/Lib/test/test_capi/test_run.py
vendored
Normal file
@ -0,0 +1,118 @@
|
||||
import os
|
||||
import unittest
|
||||
from collections import UserDict
|
||||
from test.support import import_helper
|
||||
from test.support.os_helper import unlink, TESTFN, TESTFN_ASCII, TESTFN_UNDECODABLE
|
||||
|
||||
NULL = None
|
||||
_testcapi = import_helper.import_module('_testcapi')
|
||||
Py_single_input = _testcapi.Py_single_input
|
||||
Py_file_input = _testcapi.Py_file_input
|
||||
Py_eval_input = _testcapi.Py_eval_input
|
||||
|
||||
|
||||
class DictSubclass(dict):
|
||||
pass
|
||||
|
||||
|
||||
class CAPITest(unittest.TestCase):
|
||||
# TODO: Test the following functions:
|
||||
#
|
||||
# PyRun_SimpleStringFlags
|
||||
# PyRun_AnyFileExFlags
|
||||
# PyRun_SimpleFileExFlags
|
||||
# PyRun_InteractiveOneFlags
|
||||
# PyRun_InteractiveOneObject
|
||||
# PyRun_InteractiveLoopFlags
|
||||
# PyRun_String (may be a macro)
|
||||
# PyRun_AnyFile (may be a macro)
|
||||
# PyRun_AnyFileEx (may be a macro)
|
||||
# PyRun_AnyFileFlags (may be a macro)
|
||||
# PyRun_SimpleString (may be a macro)
|
||||
# PyRun_SimpleFile (may be a macro)
|
||||
# PyRun_SimpleFileEx (may be a macro)
|
||||
# PyRun_InteractiveOne (may be a macro)
|
||||
# PyRun_InteractiveLoop (may be a macro)
|
||||
# PyRun_File (may be a macro)
|
||||
# PyRun_FileEx (may be a macro)
|
||||
# PyRun_FileFlags (may be a macro)
|
||||
|
||||
def test_run_stringflags(self):
|
||||
# Test PyRun_StringFlags().
|
||||
# XXX: fopen() uses different path encoding than Python on Windows.
|
||||
def run(s, *args):
|
||||
return _testcapi.run_stringflags(s, Py_file_input, *args)
|
||||
source = b'a\n'
|
||||
|
||||
self.assertIsNone(run(b'a\n', dict(a=1)))
|
||||
self.assertIsNone(run(b'a\n', dict(a=1), {}))
|
||||
self.assertIsNone(run(b'a\n', {}, dict(a=1)))
|
||||
self.assertIsNone(run(b'a\n', {}, UserDict(a=1)))
|
||||
|
||||
self.assertRaises(NameError, run, b'a\n', {})
|
||||
self.assertRaises(NameError, run, b'a\n', {}, {})
|
||||
self.assertRaises(TypeError, run, b'a\n', dict(a=1), [])
|
||||
self.assertRaises(TypeError, run, b'a\n', dict(a=1), 1)
|
||||
|
||||
self.assertIsNone(run(b'a\n', DictSubclass(a=1)))
|
||||
self.assertIsNone(run(b'a\n', DictSubclass(), dict(a=1)))
|
||||
self.assertRaises(NameError, run, b'a\n', DictSubclass())
|
||||
|
||||
self.assertIsNone(run(b'\xc3\xa4\n', {'\xe4': 1}))
|
||||
self.assertRaises(SyntaxError, run, b'\xe4\n', {})
|
||||
|
||||
self.assertRaises(SystemError, run, b'a\n', NULL)
|
||||
self.assertRaises(SystemError, run, b'a\n', NULL, {})
|
||||
self.assertRaises(SystemError, run, b'a\n', NULL, dict(a=1))
|
||||
self.assertRaises(SystemError, run, b'a\n', UserDict())
|
||||
self.assertRaises(SystemError, run, b'a\n', UserDict(), {})
|
||||
self.assertRaises(SystemError, run, b'a\n', UserDict(), dict(a=1))
|
||||
|
||||
# CRASHES run(NULL, {})
|
||||
|
||||
def test_run_fileexflags(self):
|
||||
# Test PyRun_FileExFlags().
|
||||
filename = os.fsencode(TESTFN if os.name != 'nt' else TESTFN_ASCII)
|
||||
with open(filename, 'wb') as fp:
|
||||
fp.write(b'a\n')
|
||||
self.addCleanup(unlink, filename)
|
||||
def run(*args):
|
||||
return _testcapi.run_fileexflags(filename, Py_file_input, *args)
|
||||
|
||||
self.assertIsNone(run(dict(a=1)))
|
||||
self.assertIsNone(run(dict(a=1), {}))
|
||||
self.assertIsNone(run({}, dict(a=1)))
|
||||
self.assertIsNone(run({}, UserDict(a=1)))
|
||||
self.assertIsNone(run(dict(a=1), {}, 1)) # closeit = True
|
||||
|
||||
self.assertRaises(NameError, run, {})
|
||||
self.assertRaises(NameError, run, {}, {})
|
||||
self.assertRaises(TypeError, run, dict(a=1), [])
|
||||
self.assertRaises(TypeError, run, dict(a=1), 1)
|
||||
|
||||
self.assertIsNone(run(DictSubclass(a=1)))
|
||||
self.assertIsNone(run(DictSubclass(), dict(a=1)))
|
||||
self.assertRaises(NameError, run, DictSubclass())
|
||||
|
||||
self.assertRaises(SystemError, run, NULL)
|
||||
self.assertRaises(SystemError, run, NULL, {})
|
||||
self.assertRaises(SystemError, run, NULL, dict(a=1))
|
||||
self.assertRaises(SystemError, run, UserDict())
|
||||
self.assertRaises(SystemError, run, UserDict(), {})
|
||||
self.assertRaises(SystemError, run, UserDict(), dict(a=1))
|
||||
|
||||
@unittest.skipUnless(TESTFN_UNDECODABLE, 'only works if there are undecodable paths')
|
||||
@unittest.skipIf(os.name == 'nt', 'does not work on Windows')
|
||||
def test_run_fileexflags_with_undecodable_filename(self):
|
||||
run = _testcapi.run_fileexflags
|
||||
try:
|
||||
with open(TESTFN_UNDECODABLE, 'wb') as fp:
|
||||
fp.write(b'a\n')
|
||||
self.addCleanup(unlink, TESTFN_UNDECODABLE)
|
||||
except OSError:
|
||||
self.skipTest('undecodable paths are not supported')
|
||||
self.assertIsNone(run(TESTFN_UNDECODABLE, Py_file_input, dict(a=1)))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
271
Dependencies/Python/Lib/test/test_capi/test_set.py
vendored
Normal file
271
Dependencies/Python/Lib/test/test_capi/test_set.py
vendored
Normal file
@ -0,0 +1,271 @@
|
||||
import unittest
|
||||
|
||||
from test.support import import_helper
|
||||
|
||||
# Skip this test if the _testcapi, _testlimitedcapi or _testinternalcapi
|
||||
# modules aren't available.
|
||||
_testcapi = import_helper.import_module('_testcapi')
|
||||
_testlimitedcapi = import_helper.import_module('_testlimitedcapi')
|
||||
_testinternalcapi = import_helper.import_module('_testinternalcapi')
|
||||
|
||||
class set_subclass(set):
|
||||
pass
|
||||
|
||||
class frozenset_subclass(frozenset):
|
||||
pass
|
||||
|
||||
|
||||
class BaseSetTests:
|
||||
def assertImmutable(self, action, *args):
|
||||
self.assertRaises(SystemError, action, frozenset(), *args)
|
||||
self.assertRaises(SystemError, action, frozenset({1}), *args)
|
||||
self.assertRaises(SystemError, action, frozenset_subclass(), *args)
|
||||
self.assertRaises(SystemError, action, frozenset_subclass({1}), *args)
|
||||
|
||||
|
||||
class TestSetCAPI(BaseSetTests, unittest.TestCase):
|
||||
def test_set_check(self):
|
||||
check = _testlimitedcapi.set_check
|
||||
self.assertTrue(check(set()))
|
||||
self.assertTrue(check({1, 2}))
|
||||
self.assertFalse(check(frozenset()))
|
||||
self.assertTrue(check(set_subclass()))
|
||||
self.assertFalse(check(frozenset_subclass()))
|
||||
self.assertFalse(check(object()))
|
||||
# CRASHES: check(NULL)
|
||||
|
||||
def test_set_check_exact(self):
|
||||
check = _testlimitedcapi.set_checkexact
|
||||
self.assertTrue(check(set()))
|
||||
self.assertTrue(check({1, 2}))
|
||||
self.assertFalse(check(frozenset()))
|
||||
self.assertFalse(check(set_subclass()))
|
||||
self.assertFalse(check(frozenset_subclass()))
|
||||
self.assertFalse(check(object()))
|
||||
# CRASHES: check(NULL)
|
||||
|
||||
def test_frozenset_check(self):
|
||||
check = _testlimitedcapi.frozenset_check
|
||||
self.assertFalse(check(set()))
|
||||
self.assertTrue(check(frozenset()))
|
||||
self.assertTrue(check(frozenset({1, 2})))
|
||||
self.assertFalse(check(set_subclass()))
|
||||
self.assertTrue(check(frozenset_subclass()))
|
||||
self.assertFalse(check(object()))
|
||||
# CRASHES: check(NULL)
|
||||
|
||||
def test_frozenset_check_exact(self):
|
||||
check = _testlimitedcapi.frozenset_checkexact
|
||||
self.assertFalse(check(set()))
|
||||
self.assertTrue(check(frozenset()))
|
||||
self.assertTrue(check(frozenset({1, 2})))
|
||||
self.assertFalse(check(set_subclass()))
|
||||
self.assertFalse(check(frozenset_subclass()))
|
||||
self.assertFalse(check(object()))
|
||||
# CRASHES: check(NULL)
|
||||
|
||||
def test_anyset_check(self):
|
||||
check = _testlimitedcapi.anyset_check
|
||||
self.assertTrue(check(set()))
|
||||
self.assertTrue(check({1, 2}))
|
||||
self.assertTrue(check(frozenset()))
|
||||
self.assertTrue(check(frozenset({1, 2})))
|
||||
self.assertTrue(check(set_subclass()))
|
||||
self.assertTrue(check(frozenset_subclass()))
|
||||
self.assertFalse(check(object()))
|
||||
# CRASHES: check(NULL)
|
||||
|
||||
def test_anyset_check_exact(self):
|
||||
check = _testlimitedcapi.anyset_checkexact
|
||||
self.assertTrue(check(set()))
|
||||
self.assertTrue(check({1, 2}))
|
||||
self.assertTrue(check(frozenset()))
|
||||
self.assertTrue(check(frozenset({1, 2})))
|
||||
self.assertFalse(check(set_subclass()))
|
||||
self.assertFalse(check(frozenset_subclass()))
|
||||
self.assertFalse(check(object()))
|
||||
# CRASHES: check(NULL)
|
||||
|
||||
def test_set_new(self):
|
||||
set_new = _testlimitedcapi.set_new
|
||||
self.assertEqual(set_new().__class__, set)
|
||||
self.assertEqual(set_new(), set())
|
||||
self.assertEqual(set_new((1, 1, 2)), {1, 2})
|
||||
self.assertEqual(set_new([1, 1, 2]), {1, 2})
|
||||
with self.assertRaisesRegex(TypeError, 'object is not iterable'):
|
||||
set_new(object())
|
||||
with self.assertRaisesRegex(TypeError, 'object is not iterable'):
|
||||
set_new(1)
|
||||
with self.assertRaisesRegex(TypeError, "unhashable type: 'dict'"):
|
||||
set_new((1, {}))
|
||||
|
||||
def test_frozenset_new(self):
|
||||
frozenset_new = _testlimitedcapi.frozenset_new
|
||||
self.assertEqual(frozenset_new().__class__, frozenset)
|
||||
self.assertEqual(frozenset_new(), frozenset())
|
||||
self.assertEqual(frozenset_new((1, 1, 2)), frozenset({1, 2}))
|
||||
self.assertEqual(frozenset_new([1, 1, 2]), frozenset({1, 2}))
|
||||
with self.assertRaisesRegex(TypeError, 'object is not iterable'):
|
||||
frozenset_new(object())
|
||||
with self.assertRaisesRegex(TypeError, 'object is not iterable'):
|
||||
frozenset_new(1)
|
||||
with self.assertRaisesRegex(TypeError, "unhashable type: 'dict'"):
|
||||
frozenset_new((1, {}))
|
||||
|
||||
def test_set_size(self):
|
||||
get_size = _testlimitedcapi.set_size
|
||||
self.assertEqual(get_size(set()), 0)
|
||||
self.assertEqual(get_size(frozenset()), 0)
|
||||
self.assertEqual(get_size({1, 1, 2}), 2)
|
||||
self.assertEqual(get_size(frozenset({1, 1, 2})), 2)
|
||||
self.assertEqual(get_size(set_subclass((1, 2, 3))), 3)
|
||||
self.assertEqual(get_size(frozenset_subclass((1, 2, 3))), 3)
|
||||
with self.assertRaises(SystemError):
|
||||
get_size(object())
|
||||
# CRASHES: get_size(NULL)
|
||||
|
||||
def test_set_get_size(self):
|
||||
get_size = _testcapi.set_get_size
|
||||
self.assertEqual(get_size(set()), 0)
|
||||
self.assertEqual(get_size(frozenset()), 0)
|
||||
self.assertEqual(get_size({1, 1, 2}), 2)
|
||||
self.assertEqual(get_size(frozenset({1, 1, 2})), 2)
|
||||
self.assertEqual(get_size(set_subclass((1, 2, 3))), 3)
|
||||
self.assertEqual(get_size(frozenset_subclass((1, 2, 3))), 3)
|
||||
# CRASHES: get_size(NULL)
|
||||
# CRASHES: get_size(object())
|
||||
|
||||
def test_set_contains(self):
|
||||
contains = _testlimitedcapi.set_contains
|
||||
for cls in (set, frozenset, set_subclass, frozenset_subclass):
|
||||
with self.subTest(cls=cls):
|
||||
instance = cls((1, 2))
|
||||
self.assertTrue(contains(instance, 1))
|
||||
self.assertFalse(contains(instance, 'missing'))
|
||||
with self.assertRaisesRegex(TypeError, "unhashable type: 'list'"):
|
||||
contains(instance, [])
|
||||
# CRASHES: contains(instance, NULL)
|
||||
# CRASHES: contains(NULL, object())
|
||||
# CRASHES: contains(NULL, NULL)
|
||||
|
||||
def test_add(self):
|
||||
add = _testlimitedcapi.set_add
|
||||
for cls in (set, set_subclass):
|
||||
with self.subTest(cls=cls):
|
||||
instance = cls((1, 2))
|
||||
self.assertEqual(add(instance, 1), 0)
|
||||
self.assertEqual(instance, {1, 2})
|
||||
self.assertEqual(add(instance, 3), 0)
|
||||
self.assertEqual(instance, {1, 2, 3})
|
||||
with self.assertRaisesRegex(TypeError, "unhashable type: 'list'"):
|
||||
add(instance, [])
|
||||
with self.assertRaises(SystemError):
|
||||
add(object(), 1)
|
||||
self.assertImmutable(add, 1)
|
||||
# CRASHES: add(NULL, object())
|
||||
# CRASHES: add(instance, NULL)
|
||||
# CRASHES: add(NULL, NULL)
|
||||
|
||||
def test_discard(self):
|
||||
discard = _testlimitedcapi.set_discard
|
||||
for cls in (set, set_subclass):
|
||||
with self.subTest(cls=cls):
|
||||
instance = cls((1, 2))
|
||||
self.assertEqual(discard(instance, 3), 0)
|
||||
self.assertEqual(instance, {1, 2})
|
||||
self.assertEqual(discard(instance, 1), 1)
|
||||
self.assertEqual(instance, {2})
|
||||
self.assertEqual(discard(instance, 2), 1)
|
||||
self.assertEqual(instance, set())
|
||||
self.assertEqual(discard(instance, 2), 0)
|
||||
self.assertEqual(instance, set())
|
||||
with self.assertRaisesRegex(TypeError, "unhashable type: 'list'"):
|
||||
discard(instance, [])
|
||||
with self.assertRaises(SystemError):
|
||||
discard(object(), 1)
|
||||
self.assertImmutable(discard, 1)
|
||||
# CRASHES: discard(NULL, object())
|
||||
# CRASHES: discard(instance, NULL)
|
||||
# CRASHES: discard(NULL, NULL)
|
||||
|
||||
def test_pop(self):
|
||||
pop = _testlimitedcapi.set_pop
|
||||
orig = (1, 2)
|
||||
for cls in (set, set_subclass):
|
||||
with self.subTest(cls=cls):
|
||||
instance = cls(orig)
|
||||
self.assertIn(pop(instance), orig)
|
||||
self.assertEqual(len(instance), 1)
|
||||
self.assertIn(pop(instance), orig)
|
||||
self.assertEqual(len(instance), 0)
|
||||
with self.assertRaises(KeyError):
|
||||
pop(instance)
|
||||
with self.assertRaises(SystemError):
|
||||
pop(object())
|
||||
self.assertImmutable(pop)
|
||||
# CRASHES: pop(NULL)
|
||||
|
||||
def test_clear(self):
|
||||
clear = _testlimitedcapi.set_clear
|
||||
for cls in (set, set_subclass):
|
||||
with self.subTest(cls=cls):
|
||||
instance = cls((1, 2))
|
||||
self.assertEqual(clear(instance), 0)
|
||||
self.assertEqual(instance, set())
|
||||
self.assertEqual(clear(instance), 0)
|
||||
self.assertEqual(instance, set())
|
||||
with self.assertRaises(SystemError):
|
||||
clear(object())
|
||||
self.assertImmutable(clear)
|
||||
# CRASHES: clear(NULL)
|
||||
|
||||
|
||||
class TestInternalCAPI(BaseSetTests, unittest.TestCase):
|
||||
def test_set_update(self):
|
||||
update = _testinternalcapi.set_update
|
||||
for cls in (set, set_subclass):
|
||||
for it in ('ab', ('a', 'b'), ['a', 'b'],
|
||||
set('ab'), set_subclass('ab'),
|
||||
frozenset('ab'), frozenset_subclass('ab')):
|
||||
with self.subTest(cls=cls, it=it):
|
||||
instance = cls()
|
||||
self.assertEqual(update(instance, it), 0)
|
||||
self.assertEqual(instance, {'a', 'b'})
|
||||
instance = cls(it)
|
||||
self.assertEqual(update(instance, it), 0)
|
||||
self.assertEqual(instance, {'a', 'b'})
|
||||
with self.assertRaisesRegex(TypeError, 'object is not iterable'):
|
||||
update(cls(), 1)
|
||||
with self.assertRaisesRegex(TypeError, "unhashable type: 'dict'"):
|
||||
update(cls(), [{}])
|
||||
with self.assertRaises(SystemError):
|
||||
update(object(), 'ab')
|
||||
self.assertImmutable(update, 'ab')
|
||||
# CRASHES: update(NULL, object())
|
||||
# CRASHES: update(instance, NULL)
|
||||
# CRASHES: update(NULL, NULL)
|
||||
|
||||
def test_set_next_entry(self):
|
||||
set_next = _testinternalcapi.set_next_entry
|
||||
for cls in (set, set_subclass, frozenset, frozenset_subclass):
|
||||
with self.subTest(cls=cls):
|
||||
instance = cls('abc')
|
||||
pos = 0
|
||||
items = []
|
||||
while True:
|
||||
res = set_next(instance, pos)
|
||||
if res is None:
|
||||
break
|
||||
rc, pos, hash_, item = res
|
||||
items.append(item)
|
||||
self.assertEqual(rc, 1)
|
||||
self.assertIn(item, instance)
|
||||
self.assertEqual(hash(item), hash_)
|
||||
self.assertEqual(items, list(instance))
|
||||
with self.assertRaises(SystemError):
|
||||
set_next(object(), 0)
|
||||
# CRASHES: set_next(NULL, 0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
174
Dependencies/Python/Lib/test/test_capi/test_structmembers.py
vendored
Normal file
174
Dependencies/Python/Lib/test/test_capi/test_structmembers.py
vendored
Normal file
@ -0,0 +1,174 @@
|
||||
import unittest
|
||||
from test.support import import_helper
|
||||
from test.support import warnings_helper
|
||||
|
||||
# Skip this test if the _testcapi module isn't available.
|
||||
import_helper.import_module('_testcapi')
|
||||
from _testcapi import (_test_structmembersType_OldAPI,
|
||||
_test_structmembersType_NewAPI,
|
||||
CHAR_MAX, CHAR_MIN, UCHAR_MAX,
|
||||
SHRT_MAX, SHRT_MIN, USHRT_MAX,
|
||||
INT_MAX, INT_MIN, UINT_MAX,
|
||||
LONG_MAX, LONG_MIN, ULONG_MAX,
|
||||
LLONG_MAX, LLONG_MIN, ULLONG_MAX,
|
||||
PY_SSIZE_T_MAX, PY_SSIZE_T_MIN,
|
||||
)
|
||||
|
||||
|
||||
class Index:
|
||||
def __init__(self, value):
|
||||
self.value = value
|
||||
def __index__(self):
|
||||
return self.value
|
||||
|
||||
# There are two classes: one using <structmember.h> and another using
|
||||
# `Py_`-prefixed API. They should behave the same in Python
|
||||
|
||||
def _make_test_object(cls):
|
||||
return cls(False, # T_BOOL
|
||||
1, # T_BYTE
|
||||
2, # T_UBYTE
|
||||
3, # T_SHORT
|
||||
4, # T_USHORT
|
||||
5, # T_INT
|
||||
6, # T_UINT
|
||||
7, # T_LONG
|
||||
8, # T_ULONG
|
||||
23, # T_PYSSIZET
|
||||
9.99999,# T_FLOAT
|
||||
10.1010101010, # T_DOUBLE
|
||||
"hi", # T_STRING_INPLACE
|
||||
)
|
||||
|
||||
|
||||
class ReadWriteTests:
|
||||
def setUp(self):
|
||||
self.ts = _make_test_object(self.cls)
|
||||
|
||||
def _test_write(self, name, value, expected=None):
|
||||
if expected is None:
|
||||
expected = value
|
||||
ts = self.ts
|
||||
setattr(ts, name, value)
|
||||
self.assertEqual(getattr(ts, name), expected)
|
||||
|
||||
def _test_warn(self, name, value, expected=None):
|
||||
ts = self.ts
|
||||
self.assertWarns(RuntimeWarning, setattr, ts, name, value)
|
||||
if expected is not None:
|
||||
self.assertEqual(getattr(ts, name), expected)
|
||||
|
||||
def _test_overflow(self, name, value):
|
||||
ts = self.ts
|
||||
self.assertRaises(OverflowError, setattr, ts, name, value)
|
||||
|
||||
def _test_int_range(self, name, minval, maxval, *, hardlimit=None,
|
||||
indexlimit=None):
|
||||
if hardlimit is None:
|
||||
hardlimit = (minval, maxval)
|
||||
ts = self.ts
|
||||
self._test_write(name, minval)
|
||||
self._test_write(name, maxval)
|
||||
hardminval, hardmaxval = hardlimit
|
||||
self._test_overflow(name, hardminval-1)
|
||||
self._test_overflow(name, hardmaxval+1)
|
||||
self._test_overflow(name, 2**1000)
|
||||
self._test_overflow(name, -2**1000)
|
||||
if hardminval < minval:
|
||||
self._test_warn(name, hardminval)
|
||||
self._test_warn(name, minval-1, maxval)
|
||||
if maxval < hardmaxval:
|
||||
self._test_warn(name, maxval+1, minval)
|
||||
self._test_warn(name, hardmaxval)
|
||||
|
||||
if indexlimit is False:
|
||||
self.assertRaises(TypeError, setattr, ts, name, Index(minval))
|
||||
self.assertRaises(TypeError, setattr, ts, name, Index(maxval))
|
||||
else:
|
||||
self._test_write(name, Index(minval), minval)
|
||||
self._test_write(name, Index(maxval), maxval)
|
||||
self._test_overflow(name, Index(hardminval-1))
|
||||
self._test_overflow(name, Index(hardmaxval+1))
|
||||
self._test_overflow(name, Index(2**1000))
|
||||
self._test_overflow(name, Index(-2**1000))
|
||||
if hardminval < minval:
|
||||
self._test_warn(name, Index(hardminval))
|
||||
self._test_warn(name, Index(minval-1), maxval)
|
||||
if maxval < hardmaxval:
|
||||
self._test_warn(name, Index(maxval+1), minval)
|
||||
self._test_warn(name, Index(hardmaxval))
|
||||
|
||||
def test_bool(self):
|
||||
ts = self.ts
|
||||
ts.T_BOOL = True
|
||||
self.assertIs(ts.T_BOOL, True)
|
||||
ts.T_BOOL = False
|
||||
self.assertIs(ts.T_BOOL, False)
|
||||
self.assertRaises(TypeError, setattr, ts, 'T_BOOL', 1)
|
||||
self.assertRaises(TypeError, setattr, ts, 'T_BOOL', 0)
|
||||
self.assertRaises(TypeError, setattr, ts, 'T_BOOL', None)
|
||||
|
||||
def test_byte(self):
|
||||
self._test_int_range('T_BYTE', CHAR_MIN, CHAR_MAX,
|
||||
hardlimit=(LONG_MIN, LONG_MAX))
|
||||
self._test_int_range('T_UBYTE', 0, UCHAR_MAX,
|
||||
hardlimit=(LONG_MIN, LONG_MAX))
|
||||
|
||||
def test_short(self):
|
||||
self._test_int_range('T_SHORT', SHRT_MIN, SHRT_MAX,
|
||||
hardlimit=(LONG_MIN, LONG_MAX))
|
||||
self._test_int_range('T_USHORT', 0, USHRT_MAX,
|
||||
hardlimit=(LONG_MIN, LONG_MAX))
|
||||
|
||||
def test_int(self):
|
||||
self._test_int_range('T_INT', INT_MIN, INT_MAX,
|
||||
hardlimit=(LONG_MIN, LONG_MAX))
|
||||
self._test_int_range('T_UINT', 0, UINT_MAX,
|
||||
hardlimit=(LONG_MIN, ULONG_MAX))
|
||||
|
||||
def test_long(self):
|
||||
self._test_int_range('T_LONG', LONG_MIN, LONG_MAX)
|
||||
self._test_int_range('T_ULONG', 0, ULONG_MAX,
|
||||
hardlimit=(LONG_MIN, ULONG_MAX))
|
||||
|
||||
def test_py_ssize_t(self):
|
||||
self._test_int_range('T_PYSSIZET', PY_SSIZE_T_MIN, PY_SSIZE_T_MAX, indexlimit=False)
|
||||
|
||||
def test_longlong(self):
|
||||
self._test_int_range('T_LONGLONG', LLONG_MIN, LLONG_MAX)
|
||||
self._test_int_range('T_ULONGLONG', 0, ULLONG_MAX,
|
||||
hardlimit=(LONG_MIN, ULLONG_MAX))
|
||||
|
||||
def test_bad_assignments(self):
|
||||
ts = self.ts
|
||||
integer_attributes = [
|
||||
'T_BOOL',
|
||||
'T_BYTE', 'T_UBYTE',
|
||||
'T_SHORT', 'T_USHORT',
|
||||
'T_INT', 'T_UINT',
|
||||
'T_LONG', 'T_ULONG',
|
||||
'T_LONGLONG', 'T_ULONGLONG',
|
||||
'T_PYSSIZET'
|
||||
]
|
||||
|
||||
# issue8014: this produced 'bad argument to internal function'
|
||||
# internal error
|
||||
for nonint in None, 3.2j, "full of eels", {}, []:
|
||||
for attr in integer_attributes:
|
||||
self.assertRaises(TypeError, setattr, ts, attr, nonint)
|
||||
|
||||
def test_inplace_string(self):
|
||||
ts = self.ts
|
||||
self.assertEqual(ts.T_STRING_INPLACE, "hi")
|
||||
self.assertRaises(TypeError, setattr, ts, "T_STRING_INPLACE", "s")
|
||||
self.assertRaises(TypeError, delattr, ts, "T_STRING_INPLACE")
|
||||
|
||||
class ReadWriteTests_OldAPI(ReadWriteTests, unittest.TestCase):
|
||||
cls = _test_structmembersType_OldAPI
|
||||
|
||||
class ReadWriteTests_NewAPI(ReadWriteTests, unittest.TestCase):
|
||||
cls = _test_structmembersType_NewAPI
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
154
Dependencies/Python/Lib/test/test_capi/test_sys.py
vendored
Normal file
154
Dependencies/Python/Lib/test/test_capi/test_sys.py
vendored
Normal file
@ -0,0 +1,154 @@
|
||||
import unittest
|
||||
import contextlib
|
||||
import sys
|
||||
from test import support
|
||||
from test.support import import_helper
|
||||
|
||||
try:
|
||||
import _testlimitedcapi
|
||||
except ImportError:
|
||||
_testlimitedcapi = None
|
||||
|
||||
NULL = None
|
||||
|
||||
class CAPITest(unittest.TestCase):
|
||||
# TODO: Test the following functions:
|
||||
#
|
||||
# PySys_Audit()
|
||||
# PySys_AuditTuple()
|
||||
|
||||
maxDiff = None
|
||||
|
||||
@support.cpython_only
|
||||
@unittest.skipIf(_testlimitedcapi is None, 'need _testlimitedcapi module')
|
||||
def test_sys_getobject(self):
|
||||
# Test PySys_GetObject()
|
||||
getobject = _testlimitedcapi.sys_getobject
|
||||
|
||||
self.assertIs(getobject(b'stdout'), sys.stdout)
|
||||
with support.swap_attr(sys, '\U0001f40d', 42):
|
||||
self.assertEqual(getobject('\U0001f40d'.encode()), 42)
|
||||
|
||||
self.assertIs(getobject(b'nonexisting'), AttributeError)
|
||||
with support.catch_unraisable_exception() as cm:
|
||||
self.assertIs(getobject(b'\xff'), AttributeError)
|
||||
self.assertEqual(cm.unraisable.exc_type, UnicodeDecodeError)
|
||||
self.assertRegex(str(cm.unraisable.exc_value),
|
||||
"'utf-8' codec can't decode")
|
||||
# CRASHES getobject(NULL)
|
||||
|
||||
@support.cpython_only
|
||||
@unittest.skipIf(_testlimitedcapi is None, 'need _testlimitedcapi module')
|
||||
def test_sys_setobject(self):
|
||||
# Test PySys_SetObject()
|
||||
setobject = _testlimitedcapi.sys_setobject
|
||||
|
||||
value = ['value']
|
||||
value2 = ['value2']
|
||||
try:
|
||||
self.assertEqual(setobject(b'newattr', value), 0)
|
||||
self.assertIs(sys.newattr, value)
|
||||
self.assertEqual(setobject(b'newattr', value2), 0)
|
||||
self.assertIs(sys.newattr, value2)
|
||||
self.assertEqual(setobject(b'newattr', NULL), 0)
|
||||
self.assertFalse(hasattr(sys, 'newattr'))
|
||||
self.assertEqual(setobject(b'newattr', NULL), 0)
|
||||
finally:
|
||||
with contextlib.suppress(AttributeError):
|
||||
del sys.newattr
|
||||
try:
|
||||
self.assertEqual(setobject('\U0001f40d'.encode(), value), 0)
|
||||
self.assertIs(getattr(sys, '\U0001f40d'), value)
|
||||
self.assertEqual(setobject('\U0001f40d'.encode(), NULL), 0)
|
||||
self.assertFalse(hasattr(sys, '\U0001f40d'))
|
||||
finally:
|
||||
with contextlib.suppress(AttributeError):
|
||||
delattr(sys, '\U0001f40d')
|
||||
|
||||
with self.assertRaises(UnicodeDecodeError):
|
||||
setobject(b'\xff', value)
|
||||
# CRASHES setobject(NULL, value)
|
||||
|
||||
@support.cpython_only
|
||||
@unittest.skipIf(_testlimitedcapi is None, 'need _testlimitedcapi module')
|
||||
def test_sys_getxoptions(self):
|
||||
# Test PySys_GetXOptions()
|
||||
getxoptions = _testlimitedcapi.sys_getxoptions
|
||||
|
||||
self.assertIs(getxoptions(), sys._xoptions)
|
||||
|
||||
xoptions = sys._xoptions
|
||||
try:
|
||||
sys._xoptions = 'non-dict'
|
||||
self.assertEqual(getxoptions(), {})
|
||||
self.assertIs(getxoptions(), sys._xoptions)
|
||||
|
||||
del sys._xoptions
|
||||
self.assertEqual(getxoptions(), {})
|
||||
self.assertIs(getxoptions(), sys._xoptions)
|
||||
finally:
|
||||
sys._xoptions = xoptions
|
||||
self.assertIs(getxoptions(), sys._xoptions)
|
||||
|
||||
def _test_sys_formatstream(self, funname, streamname):
|
||||
import_helper.import_module('ctypes')
|
||||
from ctypes import pythonapi, c_char_p, py_object
|
||||
func = getattr(pythonapi, funname)
|
||||
func.argtypes = (c_char_p,)
|
||||
|
||||
# Supports plain C types.
|
||||
with support.captured_output(streamname) as stream:
|
||||
func(b'Hello, %s!', c_char_p(b'world'))
|
||||
self.assertEqual(stream.getvalue(), 'Hello, world!')
|
||||
|
||||
# Supports Python objects.
|
||||
with support.captured_output(streamname) as stream:
|
||||
func(b'Hello, %R!', py_object('world'))
|
||||
self.assertEqual(stream.getvalue(), "Hello, 'world'!")
|
||||
|
||||
# The total length is not limited.
|
||||
with support.captured_output(streamname) as stream:
|
||||
func(b'Hello, %s!', c_char_p(b'world'*200))
|
||||
self.assertEqual(stream.getvalue(), 'Hello, ' + 'world'*200 + '!')
|
||||
|
||||
def test_sys_formatstdout(self):
|
||||
# Test PySys_FormatStdout()
|
||||
self._test_sys_formatstream('PySys_FormatStdout', 'stdout')
|
||||
|
||||
def test_sys_formatstderr(self):
|
||||
# Test PySys_FormatStderr()
|
||||
self._test_sys_formatstream('PySys_FormatStderr', 'stderr')
|
||||
|
||||
def _test_sys_writestream(self, funname, streamname):
|
||||
import_helper.import_module('ctypes')
|
||||
from ctypes import pythonapi, c_char_p
|
||||
func = getattr(pythonapi, funname)
|
||||
func.argtypes = (c_char_p,)
|
||||
|
||||
# Supports plain C types.
|
||||
with support.captured_output(streamname) as stream:
|
||||
func(b'Hello, %s!', c_char_p(b'world'))
|
||||
self.assertEqual(stream.getvalue(), 'Hello, world!')
|
||||
|
||||
# There is a limit on the total length.
|
||||
with support.captured_output(streamname) as stream:
|
||||
func(b'Hello, %s!', c_char_p(b'world'*100))
|
||||
self.assertEqual(stream.getvalue(), 'Hello, ' + 'world'*100 + '!')
|
||||
with support.captured_output(streamname) as stream:
|
||||
func(b'Hello, %s!', c_char_p(b'world'*200))
|
||||
out = stream.getvalue()
|
||||
self.assertEqual(out[:20], 'Hello, worldworldwor')
|
||||
self.assertEqual(out[-13:], '... truncated')
|
||||
self.assertGreater(len(out), 1000)
|
||||
|
||||
def test_sys_writestdout(self):
|
||||
# Test PySys_WriteStdout()
|
||||
self._test_sys_writestream('PySys_WriteStdout', 'stdout')
|
||||
|
||||
def test_sys_writestderr(self):
|
||||
# Test PySys_WriteStderr()
|
||||
self._test_sys_writestream('PySys_WriteStderr', 'stderr')
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
78
Dependencies/Python/Lib/test/test_capi/test_time.py
vendored
Normal file
78
Dependencies/Python/Lib/test/test_capi/test_time.py
vendored
Normal file
@ -0,0 +1,78 @@
|
||||
import time
|
||||
import unittest
|
||||
from test.support import import_helper
|
||||
_testcapi = import_helper.import_module('_testcapi')
|
||||
|
||||
|
||||
PyTime_MIN = _testcapi.PyTime_MIN
|
||||
PyTime_MAX = _testcapi.PyTime_MAX
|
||||
SEC_TO_NS = 10 ** 9
|
||||
DAY_TO_SEC = (24 * 60 * 60)
|
||||
# Worst clock resolution: maximum delta between two clock reads.
|
||||
CLOCK_RES = 0.050
|
||||
|
||||
|
||||
class CAPITest(unittest.TestCase):
|
||||
def test_min_max(self):
|
||||
# PyTime_t is just int64_t
|
||||
self.assertEqual(PyTime_MIN, -2**63)
|
||||
self.assertEqual(PyTime_MAX, 2**63 - 1)
|
||||
|
||||
def test_assecondsdouble(self):
|
||||
# Test PyTime_AsSecondsDouble()
|
||||
def ns_to_sec(ns):
|
||||
if abs(ns) % SEC_TO_NS == 0:
|
||||
return float(ns // SEC_TO_NS)
|
||||
else:
|
||||
return float(ns) / SEC_TO_NS
|
||||
|
||||
seconds = (
|
||||
0,
|
||||
1,
|
||||
DAY_TO_SEC,
|
||||
365 * DAY_TO_SEC,
|
||||
)
|
||||
values = {
|
||||
PyTime_MIN,
|
||||
PyTime_MIN + 1,
|
||||
PyTime_MAX - 1,
|
||||
PyTime_MAX,
|
||||
}
|
||||
for second in seconds:
|
||||
ns = second * SEC_TO_NS
|
||||
values.add(ns)
|
||||
# test nanosecond before/after to test rounding
|
||||
values.add(ns - 1)
|
||||
values.add(ns + 1)
|
||||
for ns in list(values):
|
||||
if (-ns) > PyTime_MAX:
|
||||
continue
|
||||
values.add(-ns)
|
||||
for ns in sorted(values):
|
||||
with self.subTest(ns=ns):
|
||||
self.assertEqual(_testcapi.PyTime_AsSecondsDouble(ns),
|
||||
ns_to_sec(ns))
|
||||
|
||||
def check_clock(self, c_func, py_func):
|
||||
t1 = c_func()
|
||||
t2 = py_func()
|
||||
self.assertAlmostEqual(t1, t2, delta=CLOCK_RES)
|
||||
|
||||
def test_monotonic(self):
|
||||
# Test PyTime_Monotonic() and PyTime_MonotonicRaw()
|
||||
self.check_clock(_testcapi.PyTime_Monotonic, time.monotonic)
|
||||
self.check_clock(_testcapi.PyTime_MonotonicRaw, time.monotonic)
|
||||
|
||||
def test_perf_counter(self):
|
||||
# Test PyTime_PerfCounter() and PyTime_PerfCounterRaw()
|
||||
self.check_clock(_testcapi.PyTime_PerfCounter, time.perf_counter)
|
||||
self.check_clock(_testcapi.PyTime_PerfCounterRaw, time.perf_counter)
|
||||
|
||||
def test_time(self):
|
||||
# Test PyTime_Time() and PyTime_TimeRaw()
|
||||
self.check_clock(_testcapi.PyTime_Time, time.time)
|
||||
self.check_clock(_testcapi.PyTime_TimeRaw, time.time)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
261
Dependencies/Python/Lib/test/test_capi/test_tuple.py
vendored
Normal file
261
Dependencies/Python/Lib/test/test_capi/test_tuple.py
vendored
Normal file
@ -0,0 +1,261 @@
|
||||
import unittest
|
||||
import sys
|
||||
from collections import namedtuple
|
||||
from test.support import import_helper
|
||||
|
||||
_testcapi = import_helper.import_module('_testcapi')
|
||||
_testlimitedcapi = import_helper.import_module('_testlimitedcapi')
|
||||
|
||||
NULL = None
|
||||
PY_SSIZE_T_MIN = _testcapi.PY_SSIZE_T_MIN
|
||||
PY_SSIZE_T_MAX = _testcapi.PY_SSIZE_T_MAX
|
||||
|
||||
class TupleSubclass(tuple):
|
||||
pass
|
||||
|
||||
|
||||
class CAPITest(unittest.TestCase):
|
||||
def test_check(self):
|
||||
# Test PyTuple_Check()
|
||||
check = _testlimitedcapi.tuple_check
|
||||
|
||||
self.assertTrue(check((1, 2)))
|
||||
self.assertTrue(check(()))
|
||||
self.assertTrue(check(TupleSubclass((1, 2))))
|
||||
self.assertFalse(check({1: 2}))
|
||||
self.assertFalse(check([1, 2]))
|
||||
self.assertFalse(check(42))
|
||||
self.assertFalse(check(object()))
|
||||
|
||||
# CRASHES check(NULL)
|
||||
|
||||
def test_tuple_checkexact(self):
|
||||
# Test PyTuple_CheckExact()
|
||||
check = _testlimitedcapi.tuple_checkexact
|
||||
|
||||
self.assertTrue(check((1, 2)))
|
||||
self.assertTrue(check(()))
|
||||
self.assertFalse(check(TupleSubclass((1, 2))))
|
||||
self.assertFalse(check({1: 2}))
|
||||
self.assertFalse(check([1, 2]))
|
||||
self.assertFalse(check(42))
|
||||
self.assertFalse(check(object()))
|
||||
|
||||
# CRASHES check(NULL)
|
||||
|
||||
def test_tuple_new(self):
|
||||
# Test PyTuple_New()
|
||||
tuple_new = _testlimitedcapi.tuple_new
|
||||
size = _testlimitedcapi.tuple_size
|
||||
checknull = _testcapi._check_tuple_item_is_NULL
|
||||
|
||||
tup1 = tuple_new(0)
|
||||
self.assertEqual(tup1, ())
|
||||
self.assertEqual(size(tup1), 0)
|
||||
self.assertIs(type(tup1), tuple)
|
||||
tup2 = tuple_new(1)
|
||||
self.assertIs(type(tup2), tuple)
|
||||
self.assertEqual(size(tup2), 1)
|
||||
self.assertIsNot(tup2, tup1)
|
||||
self.assertTrue(checknull(tup2, 0))
|
||||
|
||||
self.assertRaises(SystemError, tuple_new, -1)
|
||||
self.assertRaises(SystemError, tuple_new, PY_SSIZE_T_MIN)
|
||||
self.assertRaises(MemoryError, tuple_new, PY_SSIZE_T_MAX)
|
||||
|
||||
def test_tuple_pack(self):
|
||||
# Test PyTuple_Pack()
|
||||
pack = _testlimitedcapi.tuple_pack
|
||||
|
||||
self.assertEqual(pack(0), ())
|
||||
self.assertEqual(pack(1, [1]), ([1],))
|
||||
self.assertEqual(pack(2, [1], [2]), ([1], [2]))
|
||||
|
||||
self.assertRaises(SystemError, pack, PY_SSIZE_T_MIN)
|
||||
self.assertRaises(SystemError, pack, -1)
|
||||
self.assertRaises(MemoryError, pack, PY_SSIZE_T_MAX)
|
||||
|
||||
# CRASHES pack(1, NULL)
|
||||
# CRASHES pack(2, [1])
|
||||
|
||||
def test_tuple_size(self):
|
||||
# Test PyTuple_Size()
|
||||
size = _testlimitedcapi.tuple_size
|
||||
|
||||
self.assertEqual(size(()), 0)
|
||||
self.assertEqual(size((1, 2)), 2)
|
||||
self.assertEqual(size(TupleSubclass((1, 2))), 2)
|
||||
|
||||
self.assertRaises(SystemError, size, [])
|
||||
self.assertRaises(SystemError, size, 42)
|
||||
self.assertRaises(SystemError, size, object())
|
||||
|
||||
# CRASHES size(NULL)
|
||||
|
||||
def test_tuple_get_size(self):
|
||||
# Test PyTuple_GET_SIZE()
|
||||
size = _testcapi.tuple_get_size
|
||||
|
||||
self.assertEqual(size(()), 0)
|
||||
self.assertEqual(size((1, 2)), 2)
|
||||
self.assertEqual(size(TupleSubclass((1, 2))), 2)
|
||||
|
||||
def test_tuple_getitem(self):
|
||||
# Test PyTuple_GetItem()
|
||||
getitem = _testlimitedcapi.tuple_getitem
|
||||
|
||||
tup = ([1], [2], [3])
|
||||
self.assertEqual(getitem(tup, 0), [1])
|
||||
self.assertEqual(getitem(tup, 2), [3])
|
||||
|
||||
tup2 = TupleSubclass(([1], [2], [3]))
|
||||
self.assertEqual(getitem(tup2, 0), [1])
|
||||
self.assertEqual(getitem(tup2, 2), [3])
|
||||
|
||||
self.assertRaises(IndexError, getitem, tup, PY_SSIZE_T_MIN)
|
||||
self.assertRaises(IndexError, getitem, tup, -1)
|
||||
self.assertRaises(IndexError, getitem, tup, len(tup))
|
||||
self.assertRaises(IndexError, getitem, tup, PY_SSIZE_T_MAX)
|
||||
self.assertRaises(SystemError, getitem, [1, 2, 3], 1)
|
||||
self.assertRaises(SystemError, getitem, 42, 1)
|
||||
|
||||
# CRASHES getitem(NULL, 0)
|
||||
|
||||
def test_tuple_get_item(self):
|
||||
# Test PyTuple_GET_ITEM()
|
||||
get_item = _testcapi.tuple_get_item
|
||||
|
||||
tup = ([1], [2], [3])
|
||||
self.assertEqual(get_item(tup, 0), [1])
|
||||
self.assertEqual(get_item(tup, 2), [3])
|
||||
|
||||
tup2 = TupleSubclass(([1], [2], [3]))
|
||||
self.assertEqual(get_item(tup2, 0), [1])
|
||||
self.assertEqual(get_item(tup2, 2), [3])
|
||||
|
||||
# CRASHES get_item(NULL, 0)
|
||||
|
||||
def test_tuple_getslice(self):
|
||||
# Test PyTuple_GetSlice()
|
||||
getslice = _testlimitedcapi.tuple_getslice
|
||||
|
||||
# empty
|
||||
tup = ([1], [2], [3])
|
||||
self.assertEqual(getslice(tup, PY_SSIZE_T_MIN, 0), ())
|
||||
self.assertEqual(getslice(tup, -1, 0), ())
|
||||
self.assertEqual(getslice(tup, 3, PY_SSIZE_T_MAX), ())
|
||||
self.assertEqual(getslice(tup, 1, 1), ())
|
||||
self.assertEqual(getslice(tup, 2, 1), ())
|
||||
tup = TupleSubclass(([1], [2], [3]))
|
||||
self.assertEqual(getslice(tup, PY_SSIZE_T_MIN, 0), ())
|
||||
self.assertEqual(getslice(tup, -1, 0), ())
|
||||
self.assertEqual(getslice(tup, 3, PY_SSIZE_T_MAX), ())
|
||||
self.assertEqual(getslice(tup, 1, 1), ())
|
||||
self.assertEqual(getslice(tup, 2, 1), ())
|
||||
|
||||
# slice
|
||||
tup = ([1], [2], [3], [4])
|
||||
self.assertEqual(getslice(tup, 1, 3), ([2], [3]))
|
||||
tup = TupleSubclass(([1], [2], [3], [4]))
|
||||
self.assertEqual(getslice(tup, 1, 3), ([2], [3]))
|
||||
|
||||
# whole
|
||||
tup = ([1], [2], [3])
|
||||
self.assertEqual(getslice(tup, 0, 3), tup)
|
||||
self.assertEqual(getslice(tup, 0, 100), tup)
|
||||
self.assertEqual(getslice(tup, -100, 100), tup)
|
||||
tup = TupleSubclass(([1], [2], [3]))
|
||||
self.assertEqual(getslice(tup, 0, 3), tup)
|
||||
self.assertEqual(getslice(tup, 0, 100), tup)
|
||||
self.assertEqual(getslice(tup, -100, 100), tup)
|
||||
|
||||
self.assertRaises(SystemError, getslice, [[1], [2], [3]], 0, 0)
|
||||
self.assertRaises(SystemError, getslice, 42, 0, 0)
|
||||
|
||||
# CRASHES getslice(NULL, 0, 0)
|
||||
|
||||
def test_tuple_setitem(self):
|
||||
# Test PyTuple_SetItem()
|
||||
setitem = _testlimitedcapi.tuple_setitem
|
||||
checknull = _testcapi._check_tuple_item_is_NULL
|
||||
|
||||
tup = ([1], [2])
|
||||
self.assertEqual(setitem(tup, 0, []), ([], [2]))
|
||||
self.assertEqual(setitem(tup, 1, []), ([1], []))
|
||||
|
||||
tup2 = setitem(tup, 1, NULL)
|
||||
self.assertTrue(checknull(tup2, 1))
|
||||
|
||||
tup2 = TupleSubclass(([1], [2]))
|
||||
self.assertRaises(SystemError, setitem, tup2, 0, [])
|
||||
|
||||
self.assertRaises(IndexError, setitem, tup, PY_SSIZE_T_MIN, [])
|
||||
self.assertRaises(IndexError, setitem, tup, -1, [])
|
||||
self.assertRaises(IndexError, setitem, tup, len(tup), [])
|
||||
self.assertRaises(IndexError, setitem, tup, PY_SSIZE_T_MAX, [])
|
||||
self.assertRaises(SystemError, setitem, [1], 0, [])
|
||||
self.assertRaises(SystemError, setitem, 42, 0, [])
|
||||
|
||||
# CRASHES setitem(NULL, 0, [])
|
||||
|
||||
def test_tuple_set_item(self):
|
||||
# Test PyTuple_SET_ITEM()
|
||||
set_item = _testcapi.tuple_set_item
|
||||
checknull = _testcapi._check_tuple_item_is_NULL
|
||||
|
||||
tup = ([1], [2])
|
||||
self.assertEqual(set_item(tup, 0, []), ([], [2]))
|
||||
self.assertEqual(set_item(tup, 1, []), ([1], []))
|
||||
|
||||
tup2 = set_item(tup, 1, NULL)
|
||||
self.assertTrue(checknull(tup2, 1))
|
||||
|
||||
tup2 = TupleSubclass(([1], [2]))
|
||||
self.assertIs(set_item(tup2, 0, []), tup2)
|
||||
self.assertEqual(tup2, ([], [2]))
|
||||
|
||||
# CRASHES set_item(tup, -1, [])
|
||||
# CRASHES set_item(tup, len(tup), [])
|
||||
# CRASHES set_item([1], 0, [])
|
||||
# CRASHES set_item(NULL, 0, [])
|
||||
|
||||
def test__tuple_resize(self):
|
||||
# Test _PyTuple_Resize()
|
||||
resize = _testcapi._tuple_resize
|
||||
checknull = _testcapi._check_tuple_item_is_NULL
|
||||
|
||||
a = ()
|
||||
b = resize(a, 0, False)
|
||||
self.assertEqual(len(a), 0)
|
||||
self.assertEqual(len(b), 0)
|
||||
b = resize(a, 2, False)
|
||||
self.assertEqual(len(a), 0)
|
||||
self.assertEqual(len(b), 2)
|
||||
self.assertTrue(checknull(b, 0))
|
||||
self.assertTrue(checknull(b, 1))
|
||||
|
||||
a = ([1], [2], [3])
|
||||
b = resize(a, 3)
|
||||
self.assertEqual(b, a)
|
||||
b = resize(a, 2)
|
||||
self.assertEqual(b, a[:2])
|
||||
b = resize(a, 5)
|
||||
self.assertEqual(len(b), 5)
|
||||
self.assertEqual(b[:3], a)
|
||||
self.assertTrue(checknull(b, 3))
|
||||
self.assertTrue(checknull(b, 4))
|
||||
|
||||
a = ()
|
||||
self.assertRaises(MemoryError, resize, a, PY_SSIZE_T_MAX)
|
||||
self.assertRaises(SystemError, resize, a, -1)
|
||||
self.assertRaises(SystemError, resize, a, PY_SSIZE_T_MIN)
|
||||
# refcount > 1
|
||||
a = (1, 2, 3)
|
||||
self.assertRaises(SystemError, resize, a, 3, False)
|
||||
self.assertRaises(SystemError, resize, a, 0, False)
|
||||
# non-tuple
|
||||
self.assertRaises(SystemError, resize, [1, 2, 3], 0, False)
|
||||
self.assertRaises(SystemError, resize, NULL, 0, False)
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
1698
Dependencies/Python/Lib/test/test_capi/test_unicode.py
vendored
Normal file
1698
Dependencies/Python/Lib/test/test_capi/test_unicode.py
vendored
Normal file
File diff suppressed because it is too large
Load Diff
590
Dependencies/Python/Lib/test/test_capi/test_watchers.py
vendored
Normal file
590
Dependencies/Python/Lib/test/test_capi/test_watchers.py
vendored
Normal file
@ -0,0 +1,590 @@
|
||||
import unittest
|
||||
|
||||
from contextlib import contextmanager, ExitStack
|
||||
from test.support import (
|
||||
catch_unraisable_exception, import_helper,
|
||||
gc_collect, suppress_immortalization)
|
||||
|
||||
|
||||
# Skip this test if the _testcapi module isn't available.
|
||||
_testcapi = import_helper.import_module('_testcapi')
|
||||
|
||||
|
||||
class TestDictWatchers(unittest.TestCase):
|
||||
# types of watchers testcapimodule can add:
|
||||
EVENTS = 0 # appends dict events as strings to global event list
|
||||
ERROR = 1 # unconditionally sets and signals a RuntimeException
|
||||
SECOND = 2 # always appends "second" to global event list
|
||||
|
||||
def add_watcher(self, kind=EVENTS):
|
||||
return _testcapi.add_dict_watcher(kind)
|
||||
|
||||
def clear_watcher(self, watcher_id):
|
||||
_testcapi.clear_dict_watcher(watcher_id)
|
||||
|
||||
@contextmanager
|
||||
def watcher(self, kind=EVENTS):
|
||||
wid = self.add_watcher(kind)
|
||||
try:
|
||||
yield wid
|
||||
finally:
|
||||
self.clear_watcher(wid)
|
||||
|
||||
def assert_events(self, expected):
|
||||
actual = _testcapi.get_dict_watcher_events()
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
def watch(self, wid, d):
|
||||
_testcapi.watch_dict(wid, d)
|
||||
|
||||
def unwatch(self, wid, d):
|
||||
_testcapi.unwatch_dict(wid, d)
|
||||
|
||||
def test_set_new_item(self):
|
||||
d = {}
|
||||
with self.watcher() as wid:
|
||||
self.watch(wid, d)
|
||||
d["foo"] = "bar"
|
||||
self.assert_events(["new:foo:bar"])
|
||||
|
||||
def test_set_existing_item(self):
|
||||
d = {"foo": "bar"}
|
||||
with self.watcher() as wid:
|
||||
self.watch(wid, d)
|
||||
d["foo"] = "baz"
|
||||
self.assert_events(["mod:foo:baz"])
|
||||
|
||||
def test_clone(self):
|
||||
d = {}
|
||||
d2 = {"foo": "bar"}
|
||||
with self.watcher() as wid:
|
||||
self.watch(wid, d)
|
||||
d.update(d2)
|
||||
self.assert_events(["clone"])
|
||||
|
||||
def test_no_event_if_not_watched(self):
|
||||
d = {}
|
||||
with self.watcher() as wid:
|
||||
d["foo"] = "bar"
|
||||
self.assert_events([])
|
||||
|
||||
def test_del(self):
|
||||
d = {"foo": "bar"}
|
||||
with self.watcher() as wid:
|
||||
self.watch(wid, d)
|
||||
del d["foo"]
|
||||
self.assert_events(["del:foo"])
|
||||
|
||||
def test_pop(self):
|
||||
d = {"foo": "bar"}
|
||||
with self.watcher() as wid:
|
||||
self.watch(wid, d)
|
||||
d.pop("foo")
|
||||
self.assert_events(["del:foo"])
|
||||
|
||||
def test_clear(self):
|
||||
d = {"foo": "bar"}
|
||||
with self.watcher() as wid:
|
||||
self.watch(wid, d)
|
||||
d.clear()
|
||||
self.assert_events(["clear"])
|
||||
|
||||
def test_dealloc(self):
|
||||
d = {"foo": "bar"}
|
||||
with self.watcher() as wid:
|
||||
self.watch(wid, d)
|
||||
del d
|
||||
self.assert_events(["dealloc"])
|
||||
|
||||
def test_object_dict(self):
|
||||
class MyObj: pass
|
||||
o = MyObj()
|
||||
|
||||
with self.watcher() as wid:
|
||||
self.watch(wid, o.__dict__)
|
||||
o.foo = "bar"
|
||||
o.foo = "baz"
|
||||
del o.foo
|
||||
self.assert_events(["new:foo:bar", "mod:foo:baz", "del:foo"])
|
||||
|
||||
with self.watcher() as wid:
|
||||
self.watch(wid, o.__dict__)
|
||||
for _ in range(100):
|
||||
o.foo = "bar"
|
||||
self.assert_events(["new:foo:bar"] + ["mod:foo:bar"] * 99)
|
||||
|
||||
def test_unwatch(self):
|
||||
d = {}
|
||||
with self.watcher() as wid:
|
||||
self.watch(wid, d)
|
||||
d["foo"] = "bar"
|
||||
self.unwatch(wid, d)
|
||||
d["hmm"] = "baz"
|
||||
self.assert_events(["new:foo:bar"])
|
||||
|
||||
def test_error(self):
|
||||
d = {}
|
||||
with self.watcher(kind=self.ERROR) as wid:
|
||||
self.watch(wid, d)
|
||||
with catch_unraisable_exception() as cm:
|
||||
d["foo"] = "bar"
|
||||
self.assertIn(
|
||||
"Exception ignored in "
|
||||
"PyDict_EVENT_ADDED watcher callback for <dict at ",
|
||||
cm.unraisable.err_msg
|
||||
)
|
||||
self.assertIsNone(cm.unraisable.object)
|
||||
self.assertEqual(str(cm.unraisable.exc_value), "boom!")
|
||||
self.assert_events([])
|
||||
|
||||
def test_dealloc_error(self):
|
||||
d = {}
|
||||
with self.watcher(kind=self.ERROR) as wid:
|
||||
self.watch(wid, d)
|
||||
with catch_unraisable_exception() as cm:
|
||||
del d
|
||||
self.assertEqual(str(cm.unraisable.exc_value), "boom!")
|
||||
|
||||
def test_two_watchers(self):
|
||||
d1 = {}
|
||||
d2 = {}
|
||||
with self.watcher() as wid1:
|
||||
with self.watcher(kind=self.SECOND) as wid2:
|
||||
self.watch(wid1, d1)
|
||||
self.watch(wid2, d2)
|
||||
d1["foo"] = "bar"
|
||||
d2["hmm"] = "baz"
|
||||
self.assert_events(["new:foo:bar", "second"])
|
||||
|
||||
def test_watch_non_dict(self):
|
||||
with self.watcher() as wid:
|
||||
with self.assertRaisesRegex(ValueError, r"Cannot watch non-dictionary"):
|
||||
self.watch(wid, 1)
|
||||
|
||||
def test_watch_out_of_range_watcher_id(self):
|
||||
d = {}
|
||||
with self.assertRaisesRegex(ValueError, r"Invalid dict watcher ID -1"):
|
||||
self.watch(-1, d)
|
||||
with self.assertRaisesRegex(ValueError, r"Invalid dict watcher ID 8"):
|
||||
self.watch(8, d) # DICT_MAX_WATCHERS = 8
|
||||
|
||||
def test_watch_unassigned_watcher_id(self):
|
||||
d = {}
|
||||
with self.assertRaisesRegex(ValueError, r"No dict watcher set for ID 3"):
|
||||
self.watch(3, d)
|
||||
|
||||
def test_unwatch_non_dict(self):
|
||||
with self.watcher() as wid:
|
||||
with self.assertRaisesRegex(ValueError, r"Cannot watch non-dictionary"):
|
||||
self.unwatch(wid, 1)
|
||||
|
||||
def test_unwatch_out_of_range_watcher_id(self):
|
||||
d = {}
|
||||
with self.assertRaisesRegex(ValueError, r"Invalid dict watcher ID -1"):
|
||||
self.unwatch(-1, d)
|
||||
with self.assertRaisesRegex(ValueError, r"Invalid dict watcher ID 8"):
|
||||
self.unwatch(8, d) # DICT_MAX_WATCHERS = 8
|
||||
|
||||
def test_unwatch_unassigned_watcher_id(self):
|
||||
d = {}
|
||||
with self.assertRaisesRegex(ValueError, r"No dict watcher set for ID 3"):
|
||||
self.unwatch(3, d)
|
||||
|
||||
def test_clear_out_of_range_watcher_id(self):
|
||||
with self.assertRaisesRegex(ValueError, r"Invalid dict watcher ID -1"):
|
||||
self.clear_watcher(-1)
|
||||
with self.assertRaisesRegex(ValueError, r"Invalid dict watcher ID 8"):
|
||||
self.clear_watcher(8) # DICT_MAX_WATCHERS = 8
|
||||
|
||||
def test_clear_unassigned_watcher_id(self):
|
||||
with self.assertRaisesRegex(ValueError, r"No dict watcher set for ID 3"):
|
||||
self.clear_watcher(3)
|
||||
|
||||
|
||||
class TestTypeWatchers(unittest.TestCase):
|
||||
# types of watchers testcapimodule can add:
|
||||
TYPES = 0 # appends modified types to global event list
|
||||
ERROR = 1 # unconditionally sets and signals a RuntimeException
|
||||
WRAP = 2 # appends modified type wrapped in list to global event list
|
||||
|
||||
# duplicating the C constant
|
||||
TYPE_MAX_WATCHERS = 8
|
||||
|
||||
def add_watcher(self, kind=TYPES):
|
||||
return _testcapi.add_type_watcher(kind)
|
||||
|
||||
def clear_watcher(self, watcher_id):
|
||||
_testcapi.clear_type_watcher(watcher_id)
|
||||
|
||||
@contextmanager
|
||||
def watcher(self, kind=TYPES):
|
||||
wid = self.add_watcher(kind)
|
||||
try:
|
||||
yield wid
|
||||
finally:
|
||||
self.clear_watcher(wid)
|
||||
|
||||
def assert_events(self, expected):
|
||||
actual = _testcapi.get_type_modified_events()
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
def watch(self, wid, t):
|
||||
_testcapi.watch_type(wid, t)
|
||||
|
||||
def unwatch(self, wid, t):
|
||||
_testcapi.unwatch_type(wid, t)
|
||||
|
||||
def test_watch_type(self):
|
||||
class C: pass
|
||||
with self.watcher() as wid:
|
||||
self.watch(wid, C)
|
||||
C.foo = "bar"
|
||||
self.assert_events([C])
|
||||
|
||||
def test_event_aggregation(self):
|
||||
class C: pass
|
||||
with self.watcher() as wid:
|
||||
self.watch(wid, C)
|
||||
C.foo = "bar"
|
||||
C.bar = "baz"
|
||||
# only one event registered for both modifications
|
||||
self.assert_events([C])
|
||||
|
||||
def test_lookup_resets_aggregation(self):
|
||||
class C: pass
|
||||
with self.watcher() as wid:
|
||||
self.watch(wid, C)
|
||||
C.foo = "bar"
|
||||
# lookup resets type version tag
|
||||
self.assertEqual(C.foo, "bar")
|
||||
C.bar = "baz"
|
||||
# both events registered
|
||||
self.assert_events([C, C])
|
||||
|
||||
def test_unwatch_type(self):
|
||||
class C: pass
|
||||
with self.watcher() as wid:
|
||||
self.watch(wid, C)
|
||||
C.foo = "bar"
|
||||
self.assertEqual(C.foo, "bar")
|
||||
self.assert_events([C])
|
||||
self.unwatch(wid, C)
|
||||
C.bar = "baz"
|
||||
self.assert_events([C])
|
||||
|
||||
def test_clear_watcher(self):
|
||||
class C: pass
|
||||
# outer watcher is unused, it's just to keep events list alive
|
||||
with self.watcher() as _:
|
||||
with self.watcher() as wid:
|
||||
self.watch(wid, C)
|
||||
C.foo = "bar"
|
||||
self.assertEqual(C.foo, "bar")
|
||||
self.assert_events([C])
|
||||
C.bar = "baz"
|
||||
# Watcher on C has been cleared, no new event
|
||||
self.assert_events([C])
|
||||
|
||||
def test_watch_type_subclass(self):
|
||||
class C: pass
|
||||
class D(C): pass
|
||||
with self.watcher() as wid:
|
||||
self.watch(wid, D)
|
||||
C.foo = "bar"
|
||||
self.assert_events([D])
|
||||
|
||||
def test_error(self):
|
||||
class C: pass
|
||||
with self.watcher(kind=self.ERROR) as wid:
|
||||
self.watch(wid, C)
|
||||
with catch_unraisable_exception() as cm:
|
||||
C.foo = "bar"
|
||||
self.assertEqual(cm.unraisable.err_msg,
|
||||
f"Exception ignored in type watcher callback #0 for {C!r}")
|
||||
self.assertIs(cm.unraisable.object, None)
|
||||
self.assertEqual(str(cm.unraisable.exc_value), "boom!")
|
||||
self.assert_events([])
|
||||
|
||||
def test_two_watchers(self):
|
||||
class C1: pass
|
||||
class C2: pass
|
||||
with self.watcher() as wid1:
|
||||
with self.watcher(kind=self.WRAP) as wid2:
|
||||
self.assertNotEqual(wid1, wid2)
|
||||
self.watch(wid1, C1)
|
||||
self.watch(wid2, C2)
|
||||
C1.foo = "bar"
|
||||
C2.hmm = "baz"
|
||||
self.assert_events([C1, [C2]])
|
||||
|
||||
def test_all_watchers(self):
|
||||
class C: pass
|
||||
with ExitStack() as stack:
|
||||
last_wid = -1
|
||||
# don't make assumptions about how many watchers are already
|
||||
# registered, just go until we reach the max ID
|
||||
while last_wid < self.TYPE_MAX_WATCHERS - 1:
|
||||
last_wid = stack.enter_context(self.watcher())
|
||||
self.watch(last_wid, C)
|
||||
C.foo = "bar"
|
||||
self.assert_events([C])
|
||||
|
||||
def test_watch_non_type(self):
|
||||
with self.watcher() as wid:
|
||||
with self.assertRaisesRegex(ValueError, r"Cannot watch non-type"):
|
||||
self.watch(wid, 1)
|
||||
|
||||
def test_watch_out_of_range_watcher_id(self):
|
||||
class C: pass
|
||||
with self.assertRaisesRegex(ValueError, r"Invalid type watcher ID -1"):
|
||||
self.watch(-1, C)
|
||||
with self.assertRaisesRegex(ValueError, r"Invalid type watcher ID 8"):
|
||||
self.watch(self.TYPE_MAX_WATCHERS, C)
|
||||
|
||||
def test_watch_unassigned_watcher_id(self):
|
||||
class C: pass
|
||||
with self.assertRaisesRegex(ValueError, r"No type watcher set for ID 1"):
|
||||
self.watch(1, C)
|
||||
|
||||
def test_unwatch_non_type(self):
|
||||
with self.watcher() as wid:
|
||||
with self.assertRaisesRegex(ValueError, r"Cannot watch non-type"):
|
||||
self.unwatch(wid, 1)
|
||||
|
||||
def test_unwatch_out_of_range_watcher_id(self):
|
||||
class C: pass
|
||||
with self.assertRaisesRegex(ValueError, r"Invalid type watcher ID -1"):
|
||||
self.unwatch(-1, C)
|
||||
with self.assertRaisesRegex(ValueError, r"Invalid type watcher ID 8"):
|
||||
self.unwatch(self.TYPE_MAX_WATCHERS, C)
|
||||
|
||||
def test_unwatch_unassigned_watcher_id(self):
|
||||
class C: pass
|
||||
with self.assertRaisesRegex(ValueError, r"No type watcher set for ID 1"):
|
||||
self.unwatch(1, C)
|
||||
|
||||
def test_clear_out_of_range_watcher_id(self):
|
||||
with self.assertRaisesRegex(ValueError, r"Invalid type watcher ID -1"):
|
||||
self.clear_watcher(-1)
|
||||
with self.assertRaisesRegex(ValueError, r"Invalid type watcher ID 8"):
|
||||
self.clear_watcher(self.TYPE_MAX_WATCHERS)
|
||||
|
||||
def test_clear_unassigned_watcher_id(self):
|
||||
with self.assertRaisesRegex(ValueError, r"No type watcher set for ID 1"):
|
||||
self.clear_watcher(1)
|
||||
|
||||
def test_no_more_ids_available(self):
|
||||
with self.assertRaisesRegex(RuntimeError, r"no more type watcher IDs"):
|
||||
with ExitStack() as stack:
|
||||
for _ in range(self.TYPE_MAX_WATCHERS + 1):
|
||||
stack.enter_context(self.watcher())
|
||||
|
||||
|
||||
class TestCodeObjectWatchers(unittest.TestCase):
|
||||
@contextmanager
|
||||
def code_watcher(self, which_watcher):
|
||||
wid = _testcapi.add_code_watcher(which_watcher)
|
||||
try:
|
||||
yield wid
|
||||
finally:
|
||||
_testcapi.clear_code_watcher(wid)
|
||||
|
||||
def assert_event_counts(self, exp_created_0, exp_destroyed_0,
|
||||
exp_created_1, exp_destroyed_1):
|
||||
gc_collect() # code objects are collected by GC in free-threaded build
|
||||
self.assertEqual(
|
||||
exp_created_0, _testcapi.get_code_watcher_num_created_events(0))
|
||||
self.assertEqual(
|
||||
exp_destroyed_0, _testcapi.get_code_watcher_num_destroyed_events(0))
|
||||
self.assertEqual(
|
||||
exp_created_1, _testcapi.get_code_watcher_num_created_events(1))
|
||||
self.assertEqual(
|
||||
exp_destroyed_1, _testcapi.get_code_watcher_num_destroyed_events(1))
|
||||
|
||||
@suppress_immortalization()
|
||||
def test_code_object_events_dispatched(self):
|
||||
# verify that all counts are zero before any watchers are registered
|
||||
self.assert_event_counts(0, 0, 0, 0)
|
||||
|
||||
# verify that all counts remain zero when a code object is
|
||||
# created and destroyed with no watchers registered
|
||||
co1 = _testcapi.code_newempty("test_watchers", "dummy1", 0)
|
||||
self.assert_event_counts(0, 0, 0, 0)
|
||||
del co1
|
||||
self.assert_event_counts(0, 0, 0, 0)
|
||||
|
||||
# verify counts are as expected when first watcher is registered
|
||||
with self.code_watcher(0):
|
||||
self.assert_event_counts(0, 0, 0, 0)
|
||||
co2 = _testcapi.code_newempty("test_watchers", "dummy2", 0)
|
||||
self.assert_event_counts(1, 0, 0, 0)
|
||||
del co2
|
||||
self.assert_event_counts(1, 1, 0, 0)
|
||||
|
||||
# again with second watcher registered
|
||||
with self.code_watcher(1):
|
||||
self.assert_event_counts(1, 1, 0, 0)
|
||||
co3 = _testcapi.code_newempty("test_watchers", "dummy3", 0)
|
||||
self.assert_event_counts(2, 1, 1, 0)
|
||||
del co3
|
||||
self.assert_event_counts(2, 2, 1, 1)
|
||||
|
||||
# verify counts are reset and don't change after both watchers are cleared
|
||||
co4 = _testcapi.code_newempty("test_watchers", "dummy4", 0)
|
||||
self.assert_event_counts(0, 0, 0, 0)
|
||||
del co4
|
||||
self.assert_event_counts(0, 0, 0, 0)
|
||||
|
||||
def test_error(self):
|
||||
with self.code_watcher(2):
|
||||
with catch_unraisable_exception() as cm:
|
||||
co = _testcapi.code_newempty("test_watchers", "dummy0", 0)
|
||||
|
||||
self.assertEqual(
|
||||
cm.unraisable.err_msg,
|
||||
f"Exception ignored in "
|
||||
f"PY_CODE_EVENT_CREATE watcher callback for {co!r}"
|
||||
)
|
||||
self.assertIsNone(cm.unraisable.object)
|
||||
self.assertEqual(str(cm.unraisable.exc_value), "boom!")
|
||||
|
||||
@suppress_immortalization()
|
||||
def test_dealloc_error(self):
|
||||
co = _testcapi.code_newempty("test_watchers", "dummy0", 0)
|
||||
with self.code_watcher(2):
|
||||
with catch_unraisable_exception() as cm:
|
||||
del co
|
||||
gc_collect()
|
||||
|
||||
self.assertEqual(str(cm.unraisable.exc_value), "boom!")
|
||||
|
||||
def test_clear_out_of_range_watcher_id(self):
|
||||
with self.assertRaisesRegex(ValueError, r"Invalid code watcher ID -1"):
|
||||
_testcapi.clear_code_watcher(-1)
|
||||
with self.assertRaisesRegex(ValueError, r"Invalid code watcher ID 8"):
|
||||
_testcapi.clear_code_watcher(8) # CODE_MAX_WATCHERS = 8
|
||||
|
||||
def test_clear_unassigned_watcher_id(self):
|
||||
with self.assertRaisesRegex(ValueError, r"No code watcher set for ID 1"):
|
||||
_testcapi.clear_code_watcher(1)
|
||||
|
||||
def test_allocate_too_many_watchers(self):
|
||||
with self.assertRaisesRegex(RuntimeError, r"no more code watcher IDs available"):
|
||||
_testcapi.allocate_too_many_code_watchers()
|
||||
|
||||
|
||||
class TestFuncWatchers(unittest.TestCase):
|
||||
@contextmanager
|
||||
def add_watcher(self, func):
|
||||
wid = _testcapi.add_func_watcher(func)
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
_testcapi.clear_func_watcher(wid)
|
||||
|
||||
def test_func_events_dispatched(self):
|
||||
events = []
|
||||
def watcher(*args):
|
||||
events.append(args)
|
||||
|
||||
with self.add_watcher(watcher):
|
||||
def myfunc():
|
||||
pass
|
||||
self.assertIn((_testcapi.PYFUNC_EVENT_CREATE, myfunc, None), events)
|
||||
myfunc_id = id(myfunc)
|
||||
|
||||
new_code = self.test_func_events_dispatched.__code__
|
||||
myfunc.__code__ = new_code
|
||||
self.assertIn((_testcapi.PYFUNC_EVENT_MODIFY_CODE, myfunc, new_code), events)
|
||||
|
||||
new_defaults = (123,)
|
||||
myfunc.__defaults__ = new_defaults
|
||||
self.assertIn((_testcapi.PYFUNC_EVENT_MODIFY_DEFAULTS, myfunc, new_defaults), events)
|
||||
|
||||
new_defaults = (456,)
|
||||
_testcapi.set_func_defaults_via_capi(myfunc, new_defaults)
|
||||
self.assertIn((_testcapi.PYFUNC_EVENT_MODIFY_DEFAULTS, myfunc, new_defaults), events)
|
||||
|
||||
new_kwdefaults = {"self": 123}
|
||||
myfunc.__kwdefaults__ = new_kwdefaults
|
||||
self.assertIn((_testcapi.PYFUNC_EVENT_MODIFY_KWDEFAULTS, myfunc, new_kwdefaults), events)
|
||||
|
||||
new_kwdefaults = {"self": 456}
|
||||
_testcapi.set_func_kwdefaults_via_capi(myfunc, new_kwdefaults)
|
||||
self.assertIn((_testcapi.PYFUNC_EVENT_MODIFY_KWDEFAULTS, myfunc, new_kwdefaults), events)
|
||||
|
||||
# Clear events reference to func
|
||||
events = []
|
||||
del myfunc
|
||||
self.assertIn((_testcapi.PYFUNC_EVENT_DESTROY, myfunc_id, None), events)
|
||||
|
||||
def test_multiple_watchers(self):
|
||||
events0 = []
|
||||
def first_watcher(*args):
|
||||
events0.append(args)
|
||||
|
||||
events1 = []
|
||||
def second_watcher(*args):
|
||||
events1.append(args)
|
||||
|
||||
with self.add_watcher(first_watcher):
|
||||
with self.add_watcher(second_watcher):
|
||||
def myfunc():
|
||||
pass
|
||||
|
||||
event = (_testcapi.PYFUNC_EVENT_CREATE, myfunc, None)
|
||||
self.assertIn(event, events0)
|
||||
self.assertIn(event, events1)
|
||||
|
||||
def test_watcher_raises_error(self):
|
||||
class MyError(Exception):
|
||||
pass
|
||||
|
||||
def watcher(*args):
|
||||
raise MyError("testing 123")
|
||||
|
||||
with self.add_watcher(watcher):
|
||||
with catch_unraisable_exception() as cm:
|
||||
def myfunc():
|
||||
pass
|
||||
|
||||
self.assertEqual(
|
||||
cm.unraisable.err_msg,
|
||||
f"Exception ignored in "
|
||||
f"PyFunction_EVENT_CREATE watcher callback for {repr(myfunc)[1:-1]}"
|
||||
)
|
||||
self.assertIsNone(cm.unraisable.object)
|
||||
|
||||
def test_dealloc_watcher_raises_error(self):
|
||||
class MyError(Exception):
|
||||
pass
|
||||
|
||||
def watcher(*args):
|
||||
raise MyError("testing 123")
|
||||
|
||||
def myfunc():
|
||||
pass
|
||||
|
||||
with self.add_watcher(watcher):
|
||||
with catch_unraisable_exception() as cm:
|
||||
del myfunc
|
||||
|
||||
self.assertIsInstance(cm.unraisable.exc_value, MyError)
|
||||
|
||||
def test_clear_out_of_range_watcher_id(self):
|
||||
with self.assertRaisesRegex(ValueError, r"invalid func watcher ID -1"):
|
||||
_testcapi.clear_func_watcher(-1)
|
||||
with self.assertRaisesRegex(ValueError, r"invalid func watcher ID 8"):
|
||||
_testcapi.clear_func_watcher(8) # FUNC_MAX_WATCHERS = 8
|
||||
|
||||
def test_clear_unassigned_watcher_id(self):
|
||||
with self.assertRaisesRegex(ValueError, r"no func watcher set for ID 1"):
|
||||
_testcapi.clear_func_watcher(1)
|
||||
|
||||
def test_allocate_too_many_watchers(self):
|
||||
with self.assertRaisesRegex(RuntimeError, r"no more func watcher IDs"):
|
||||
_testcapi.allocate_too_many_func_watchers()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
Reference in New Issue
Block a user