Skip to content

Commit 23c8dd7

Browse files
bpo-34272: Reorganize C API tests.
Move most C API tests into Lib/test/test_capi/.
1 parent 8f7bb10 commit 23c8dd7

15 files changed

+689
-752
lines changed

Lib/test/test_bytes.py

Lines changed: 0 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -820,114 +820,6 @@ def __bytes__(self):
820820
self.assertEqual(BytesSubclass(A()), b'abc')
821821
self.assertIs(type(BytesSubclass(A())), BytesSubclass)
822822

823-
# Test PyBytes_FromFormat()
824-
def test_from_format(self):
825-
ctypes = test.support.import_module('ctypes')
826-
_testcapi = test.support.import_module('_testcapi')
827-
from ctypes import pythonapi, py_object
828-
from ctypes import (
829-
c_int, c_uint,
830-
c_long, c_ulong,
831-
c_size_t, c_ssize_t,
832-
c_char_p)
833-
834-
PyBytes_FromFormat = pythonapi.PyBytes_FromFormat
835-
PyBytes_FromFormat.restype = py_object
836-
837-
# basic tests
838-
self.assertEqual(PyBytes_FromFormat(b'format'),
839-
b'format')
840-
self.assertEqual(PyBytes_FromFormat(b'Hello %s !', b'world'),
841-
b'Hello world !')
842-
843-
# test formatters
844-
self.assertEqual(PyBytes_FromFormat(b'c=%c', c_int(0)),
845-
b'c=\0')
846-
self.assertEqual(PyBytes_FromFormat(b'c=%c', c_int(ord('@'))),
847-
b'c=@')
848-
self.assertEqual(PyBytes_FromFormat(b'c=%c', c_int(255)),
849-
b'c=\xff')
850-
self.assertEqual(PyBytes_FromFormat(b'd=%d ld=%ld zd=%zd',
851-
c_int(1), c_long(2),
852-
c_size_t(3)),
853-
b'd=1 ld=2 zd=3')
854-
self.assertEqual(PyBytes_FromFormat(b'd=%d ld=%ld zd=%zd',
855-
c_int(-1), c_long(-2),
856-
c_size_t(-3)),
857-
b'd=-1 ld=-2 zd=-3')
858-
self.assertEqual(PyBytes_FromFormat(b'u=%u lu=%lu zu=%zu',
859-
c_uint(123), c_ulong(456),
860-
c_size_t(789)),
861-
b'u=123 lu=456 zu=789')
862-
self.assertEqual(PyBytes_FromFormat(b'i=%i', c_int(123)),
863-
b'i=123')
864-
self.assertEqual(PyBytes_FromFormat(b'i=%i', c_int(-123)),
865-
b'i=-123')
866-
self.assertEqual(PyBytes_FromFormat(b'x=%x', c_int(0xabc)),
867-
b'x=abc')
868-
869-
sizeof_ptr = ctypes.sizeof(c_char_p)
870-
871-
if os.name == 'nt':
872-
# Windows (MSCRT)
873-
ptr_format = '0x%0{}X'.format(2 * sizeof_ptr)
874-
def ptr_formatter(ptr):
875-
return (ptr_format % ptr)
876-
else:
877-
# UNIX (glibc)
878-
def ptr_formatter(ptr):
879-
return '%#x' % ptr
880-
881-
ptr = 0xabcdef
882-
self.assertEqual(PyBytes_FromFormat(b'ptr=%p', c_char_p(ptr)),
883-
('ptr=' + ptr_formatter(ptr)).encode('ascii'))
884-
self.assertEqual(PyBytes_FromFormat(b's=%s', c_char_p(b'cstr')),
885-
b's=cstr')
886-
887-
# test minimum and maximum integer values
888-
size_max = c_size_t(-1).value
889-
for formatstr, ctypes_type, value, py_formatter in (
890-
(b'%d', c_int, _testcapi.INT_MIN, str),
891-
(b'%d', c_int, _testcapi.INT_MAX, str),
892-
(b'%ld', c_long, _testcapi.LONG_MIN, str),
893-
(b'%ld', c_long, _testcapi.LONG_MAX, str),
894-
(b'%lu', c_ulong, _testcapi.ULONG_MAX, str),
895-
(b'%zd', c_ssize_t, _testcapi.PY_SSIZE_T_MIN, str),
896-
(b'%zd', c_ssize_t, _testcapi.PY_SSIZE_T_MAX, str),
897-
(b'%zu', c_size_t, size_max, str),
898-
(b'%p', c_char_p, size_max, ptr_formatter),
899-
):
900-
self.assertEqual(PyBytes_FromFormat(formatstr, ctypes_type(value)),
901-
py_formatter(value).encode('ascii')),
902-
903-
# width and precision (width is currently ignored)
904-
self.assertEqual(PyBytes_FromFormat(b'%5s', b'a'),
905-
b'a')
906-
self.assertEqual(PyBytes_FromFormat(b'%.3s', b'abcdef'),
907-
b'abc')
908-
909-
# '%%' formatter
910-
self.assertEqual(PyBytes_FromFormat(b'%%'),
911-
b'%')
912-
self.assertEqual(PyBytes_FromFormat(b'[%%]'),
913-
b'[%]')
914-
self.assertEqual(PyBytes_FromFormat(b'%%%c', c_int(ord('_'))),
915-
b'%_')
916-
self.assertEqual(PyBytes_FromFormat(b'%%s'),
917-
b'%s')
918-
919-
# Invalid formats and partial formatting
920-
self.assertEqual(PyBytes_FromFormat(b'%'), b'%')
921-
self.assertEqual(PyBytes_FromFormat(b'x=%i y=%', c_int(2), c_int(3)),
922-
b'x=2 y=%')
923-
924-
# Issue #19969: %c must raise OverflowError for values
925-
# not in the range [0; 255]
926-
self.assertRaises(OverflowError,
927-
PyBytes_FromFormat, b'%c', c_int(-1))
928-
self.assertRaises(OverflowError,
929-
PyBytes_FromFormat, b'%c', c_int(256))
930-
931823
def test_bytes_blocking(self):
932824
class IterationBlocked(list):
933825
__bytes__ = None

Lib/test/test_capi/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import os
2+
from test.support import load_package_tests
3+
4+
def load_tests(*args):
5+
return load_package_tests(os.path.dirname(__file__), *args)

Lib/test/test_capi/__main__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import unittest
2+
3+
unittest.main('test.test_capi')

Lib/test/test_capi/test_bytes.py

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
import os
2+
import unittest
3+
from test import support
4+
5+
6+
class CAPITest(unittest.TestCase):
7+
8+
# Test PyBytes_FromFormat()
9+
def test_from_format(self):
10+
ctypes = support.import_module('ctypes')
11+
_testcapi = support.import_module('_testcapi')
12+
from ctypes import pythonapi, py_object
13+
from ctypes import (
14+
c_int, c_uint,
15+
c_long, c_ulong,
16+
c_size_t, c_ssize_t,
17+
c_char_p)
18+
19+
PyBytes_FromFormat = pythonapi.PyBytes_FromFormat
20+
PyBytes_FromFormat.restype = py_object
21+
22+
# basic tests
23+
self.assertEqual(PyBytes_FromFormat(b'format'),
24+
b'format')
25+
self.assertEqual(PyBytes_FromFormat(b'Hello %s !', b'world'),
26+
b'Hello world !')
27+
28+
# test formatters
29+
self.assertEqual(PyBytes_FromFormat(b'c=%c', c_int(0)),
30+
b'c=\0')
31+
self.assertEqual(PyBytes_FromFormat(b'c=%c', c_int(ord('@'))),
32+
b'c=@')
33+
self.assertEqual(PyBytes_FromFormat(b'c=%c', c_int(255)),
34+
b'c=\xff')
35+
self.assertEqual(PyBytes_FromFormat(b'd=%d ld=%ld zd=%zd',
36+
c_int(1), c_long(2),
37+
c_size_t(3)),
38+
b'd=1 ld=2 zd=3')
39+
self.assertEqual(PyBytes_FromFormat(b'd=%d ld=%ld zd=%zd',
40+
c_int(-1), c_long(-2),
41+
c_size_t(-3)),
42+
b'd=-1 ld=-2 zd=-3')
43+
self.assertEqual(PyBytes_FromFormat(b'u=%u lu=%lu zu=%zu',
44+
c_uint(123), c_ulong(456),
45+
c_size_t(789)),
46+
b'u=123 lu=456 zu=789')
47+
self.assertEqual(PyBytes_FromFormat(b'i=%i', c_int(123)),
48+
b'i=123')
49+
self.assertEqual(PyBytes_FromFormat(b'i=%i', c_int(-123)),
50+
b'i=-123')
51+
self.assertEqual(PyBytes_FromFormat(b'x=%x', c_int(0xabc)),
52+
b'x=abc')
53+
54+
sizeof_ptr = ctypes.sizeof(c_char_p)
55+
56+
if os.name == 'nt':
57+
# Windows (MSCRT)
58+
ptr_format = '0x%0{}X'.format(2 * sizeof_ptr)
59+
def ptr_formatter(ptr):
60+
return (ptr_format % ptr)
61+
else:
62+
# UNIX (glibc)
63+
def ptr_formatter(ptr):
64+
return '%#x' % ptr
65+
66+
ptr = 0xabcdef
67+
self.assertEqual(PyBytes_FromFormat(b'ptr=%p', c_char_p(ptr)),
68+
('ptr=' + ptr_formatter(ptr)).encode('ascii'))
69+
self.assertEqual(PyBytes_FromFormat(b's=%s', c_char_p(b'cstr')),
70+
b's=cstr')
71+
72+
# test minimum and maximum integer values
73+
size_max = c_size_t(-1).value
74+
for formatstr, ctypes_type, value, py_formatter in (
75+
(b'%d', c_int, _testcapi.INT_MIN, str),
76+
(b'%d', c_int, _testcapi.INT_MAX, str),
77+
(b'%ld', c_long, _testcapi.LONG_MIN, str),
78+
(b'%ld', c_long, _testcapi.LONG_MAX, str),
79+
(b'%lu', c_ulong, _testcapi.ULONG_MAX, str),
80+
(b'%zd', c_ssize_t, _testcapi.PY_SSIZE_T_MIN, str),
81+
(b'%zd', c_ssize_t, _testcapi.PY_SSIZE_T_MAX, str),
82+
(b'%zu', c_size_t, size_max, str),
83+
(b'%p', c_char_p, size_max, ptr_formatter),
84+
):
85+
self.assertEqual(PyBytes_FromFormat(formatstr, ctypes_type(value)),
86+
py_formatter(value).encode('ascii')),
87+
88+
# width and precision (width is currently ignored)
89+
self.assertEqual(PyBytes_FromFormat(b'%5s', b'a'),
90+
b'a')
91+
self.assertEqual(PyBytes_FromFormat(b'%.3s', b'abcdef'),
92+
b'abc')
93+
94+
# '%%' formatter
95+
self.assertEqual(PyBytes_FromFormat(b'%%'),
96+
b'%')
97+
self.assertEqual(PyBytes_FromFormat(b'[%%]'),
98+
b'[%]')
99+
self.assertEqual(PyBytes_FromFormat(b'%%%c', c_int(ord('_'))),
100+
b'%_')
101+
self.assertEqual(PyBytes_FromFormat(b'%%s'),
102+
b'%s')
103+
104+
# Invalid formats and partial formatting
105+
self.assertEqual(PyBytes_FromFormat(b'%'), b'%')
106+
self.assertEqual(PyBytes_FromFormat(b'x=%i y=%', c_int(2), c_int(3)),
107+
b'x=2 y=%')
108+
109+
# Issue #19969: %c must raise OverflowError for values
110+
# not in the range [0; 255]
111+
self.assertRaises(OverflowError,
112+
PyBytes_FromFormat, b'%c', c_int(-1))
113+
self.assertRaises(OverflowError,
114+
PyBytes_FromFormat, b'%c', c_int(256))
115+
116+
117+
if __name__ == "__main__":
118+
unittest.main()

Lib/test/test_capi/test_dict.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import unittest
2+
from test import support
3+
4+
5+
class CAPITest(unittest.TestCase):
6+
7+
# Test _PyDict_GetItem_KnownHash()
8+
@support.cpython_only
9+
def test_getitem_knownhash(self):
10+
from _testcapi import dict_getitem_knownhash
11+
12+
d = {'x': 1, 'y': 2, 'z': 3}
13+
self.assertEqual(dict_getitem_knownhash(d, 'x', hash('x')), 1)
14+
self.assertEqual(dict_getitem_knownhash(d, 'y', hash('y')), 2)
15+
self.assertEqual(dict_getitem_knownhash(d, 'z', hash('z')), 3)
16+
17+
# not a dict
18+
self.assertRaises(SystemError, dict_getitem_knownhash, [], 1, hash(1))
19+
# key does not exist
20+
self.assertRaises(KeyError, dict_getitem_knownhash, {}, 1, hash(1))
21+
22+
class Exc(Exception): pass
23+
class BadEq:
24+
def __eq__(self, other):
25+
raise Exc
26+
def __hash__(self):
27+
return 7
28+
29+
k1, k2 = BadEq(), BadEq()
30+
d = {k1: 1}
31+
self.assertEqual(dict_getitem_knownhash(d, k1, hash(k1)), 1)
32+
self.assertRaises(Exc, dict_getitem_knownhash, d, k2, hash(k2))
33+
34+
35+
if __name__ == "__main__":
36+
unittest.main()
File renamed without changes.

Lib/test/test_capi/test_marshal.py

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
from test import support
2+
import marshal
3+
import unittest
4+
5+
try:
6+
import _testcapi
7+
except ImportError:
8+
_testcapi = None
9+
10+
@support.cpython_only
11+
@unittest.skipUnless(_testcapi, 'requires _testcapi')
12+
class CAPI_TestCase(unittest.TestCase):
13+
14+
def test_write_long_to_file(self):
15+
for v in range(marshal.version + 1):
16+
_testcapi.pymarshal_write_long_to_file(0x12345678, support.TESTFN, v)
17+
with open(support.TESTFN, 'rb') as f:
18+
data = f.read()
19+
support.unlink(support.TESTFN)
20+
self.assertEqual(data, b'\x78\x56\x34\x12')
21+
22+
def test_write_object_to_file(self):
23+
obj = ('\u20ac', b'abc', 123, 45.6, 7+8j, 'long line '*1000)
24+
for v in range(marshal.version + 1):
25+
_testcapi.pymarshal_write_object_to_file(obj, support.TESTFN, v)
26+
with open(support.TESTFN, 'rb') as f:
27+
data = f.read()
28+
support.unlink(support.TESTFN)
29+
self.assertEqual(marshal.loads(data), obj)
30+
31+
def test_read_short_from_file(self):
32+
with open(support.TESTFN, 'wb') as f:
33+
f.write(b'\x34\x12xxxx')
34+
r, p = _testcapi.pymarshal_read_short_from_file(support.TESTFN)
35+
support.unlink(support.TESTFN)
36+
self.assertEqual(r, 0x1234)
37+
self.assertEqual(p, 2)
38+
39+
with open(support.TESTFN, 'wb') as f:
40+
f.write(b'\x12')
41+
with self.assertRaises(EOFError):
42+
_testcapi.pymarshal_read_short_from_file(support.TESTFN)
43+
support.unlink(support.TESTFN)
44+
45+
def test_read_long_from_file(self):
46+
with open(support.TESTFN, 'wb') as f:
47+
f.write(b'\x78\x56\x34\x12xxxx')
48+
r, p = _testcapi.pymarshal_read_long_from_file(support.TESTFN)
49+
support.unlink(support.TESTFN)
50+
self.assertEqual(r, 0x12345678)
51+
self.assertEqual(p, 4)
52+
53+
with open(support.TESTFN, 'wb') as f:
54+
f.write(b'\x56\x34\x12')
55+
with self.assertRaises(EOFError):
56+
_testcapi.pymarshal_read_long_from_file(support.TESTFN)
57+
support.unlink(support.TESTFN)
58+
59+
def test_read_last_object_from_file(self):
60+
obj = ('\u20ac', b'abc', 123, 45.6, 7+8j)
61+
for v in range(marshal.version + 1):
62+
data = marshal.dumps(obj, v)
63+
with open(support.TESTFN, 'wb') as f:
64+
f.write(data + b'xxxx')
65+
r, p = _testcapi.pymarshal_read_last_object_from_file(support.TESTFN)
66+
support.unlink(support.TESTFN)
67+
self.assertEqual(r, obj)
68+
69+
with open(support.TESTFN, 'wb') as f:
70+
f.write(data[:1])
71+
with self.assertRaises(EOFError):
72+
_testcapi.pymarshal_read_last_object_from_file(support.TESTFN)
73+
support.unlink(support.TESTFN)
74+
75+
def test_read_object_from_file(self):
76+
obj = ('\u20ac', b'abc', 123, 45.6, 7+8j)
77+
for v in range(marshal.version + 1):
78+
data = marshal.dumps(obj, v)
79+
with open(support.TESTFN, 'wb') as f:
80+
f.write(data + b'xxxx')
81+
r, p = _testcapi.pymarshal_read_object_from_file(support.TESTFN)
82+
support.unlink(support.TESTFN)
83+
self.assertEqual(r, obj)
84+
self.assertEqual(p, len(data))
85+
86+
with open(support.TESTFN, 'wb') as f:
87+
f.write(data[:1])
88+
with self.assertRaises(EOFError):
89+
_testcapi.pymarshal_read_object_from_file(support.TESTFN)
90+
support.unlink(support.TESTFN)
91+
92+
93+
if __name__ == "__main__":
94+
unittest.main()
File renamed without changes.

0 commit comments

Comments
 (0)