Skip to content

Commit eb71413

Browse files
committed
test_ctypes from CPython 3.13.11
1 parent 1b6ae64 commit eb71413

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+8796
-10
lines changed

Lib/test/test_ctypes.py

Lines changed: 0 additions & 10 deletions
This file was deleted.

Lib/test/test_ctypes/__init__.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import os
2+
from test import support
3+
from test.support import import_helper
4+
5+
6+
# skip tests if the _ctypes extension was not built
7+
import_helper.import_module('ctypes')
8+
9+
def load_tests(*args):
10+
return support.load_package_tests(os.path.dirname(__file__), *args)

Lib/test/test_ctypes/__main__.py

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

Lib/test/test_ctypes/_support.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Some classes and types are not export to _ctypes module directly.
2+
3+
import ctypes
4+
from _ctypes import Structure, Union, _Pointer, Array, _SimpleCData, CFuncPtr
5+
6+
7+
_CData = Structure.__base__
8+
assert _CData.__name__ == "_CData"
9+
10+
class _X(Structure):
11+
_fields_ = [("x", ctypes.c_int)]
12+
CField = type(_X.x)
13+
14+
# metaclasses
15+
PyCStructType = type(Structure)
16+
UnionType = type(Union)
17+
PyCPointerType = type(_Pointer)
18+
PyCArrayType = type(Array)
19+
PyCSimpleType = type(_SimpleCData)
20+
PyCFuncPtrType = type(CFuncPtr)
21+
22+
# type flags
23+
Py_TPFLAGS_DISALLOW_INSTANTIATION = 1 << 7
24+
Py_TPFLAGS_IMMUTABLETYPE = 1 << 8
Lines changed: 321 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,321 @@
1+
from ctypes import (
2+
c_char, c_uint32, c_uint16, c_ubyte, c_byte, alignment, sizeof,
3+
BigEndianStructure, LittleEndianStructure,
4+
BigEndianUnion, LittleEndianUnion, Structure
5+
)
6+
import struct
7+
import unittest
8+
9+
10+
class TestAlignedStructures(unittest.TestCase):
11+
def test_aligned_string(self):
12+
for base, e in (
13+
(LittleEndianStructure, "<"),
14+
(BigEndianStructure, ">"),
15+
):
16+
data = bytearray(struct.pack(f"{e}i12x16s", 7, b"hello world!"))
17+
class Aligned(base):
18+
_align_ = 16
19+
_fields_ = [
20+
('value', c_char * 12)
21+
]
22+
23+
class Main(base):
24+
_fields_ = [
25+
('first', c_uint32),
26+
('string', Aligned),
27+
]
28+
29+
main = Main.from_buffer(data)
30+
self.assertEqual(main.first, 7)
31+
self.assertEqual(main.string.value, b'hello world!')
32+
self.assertEqual(bytes(main.string), b'hello world!\0\0\0\0')
33+
self.assertEqual(Main.string.offset, 16)
34+
self.assertEqual(Main.string.size, 16)
35+
self.assertEqual(alignment(main.string), 16)
36+
self.assertEqual(alignment(main), 16)
37+
38+
def test_aligned_structures(self):
39+
for base, data in (
40+
(LittleEndianStructure, bytearray(b"\1\0\0\0\1\0\0\0\7\0\0\0")),
41+
(BigEndianStructure, bytearray(b"\1\0\0\0\1\0\0\0\7\0\0\0")),
42+
):
43+
class SomeBools(base):
44+
_align_ = 4
45+
_fields_ = [
46+
("bool1", c_ubyte),
47+
("bool2", c_ubyte),
48+
]
49+
class Main(base):
50+
_fields_ = [
51+
("x", c_ubyte),
52+
("y", SomeBools),
53+
("z", c_ubyte),
54+
]
55+
56+
main = Main.from_buffer(data)
57+
self.assertEqual(alignment(SomeBools), 4)
58+
self.assertEqual(alignment(main), 4)
59+
self.assertEqual(alignment(main.y), 4)
60+
self.assertEqual(Main.x.size, 1)
61+
self.assertEqual(Main.y.offset, 4)
62+
self.assertEqual(Main.y.size, 4)
63+
self.assertEqual(main.y.bool1, True)
64+
self.assertEqual(main.y.bool2, False)
65+
self.assertEqual(Main.z.offset, 8)
66+
self.assertEqual(main.z, 7)
67+
68+
def test_oversized_structure(self):
69+
data = bytearray(b"\0" * 8)
70+
for base in (LittleEndianStructure, BigEndianStructure):
71+
class SomeBoolsTooBig(base):
72+
_align_ = 8
73+
_fields_ = [
74+
("bool1", c_ubyte),
75+
("bool2", c_ubyte),
76+
("bool3", c_ubyte),
77+
]
78+
class Main(base):
79+
_fields_ = [
80+
("y", SomeBoolsTooBig),
81+
("z", c_uint32),
82+
]
83+
with self.assertRaises(ValueError) as ctx:
84+
Main.from_buffer(data)
85+
self.assertEqual(
86+
ctx.exception.args[0],
87+
'Buffer size too small (4 instead of at least 8 bytes)'
88+
)
89+
90+
def test_aligned_subclasses(self):
91+
for base, e in (
92+
(LittleEndianStructure, "<"),
93+
(BigEndianStructure, ">"),
94+
):
95+
data = bytearray(struct.pack(f"{e}4i", 1, 2, 3, 4))
96+
class UnalignedSub(base):
97+
x: c_uint32
98+
_fields_ = [
99+
("x", c_uint32),
100+
]
101+
102+
class AlignedStruct(UnalignedSub):
103+
_align_ = 8
104+
_fields_ = [
105+
("y", c_uint32),
106+
]
107+
108+
class Main(base):
109+
_fields_ = [
110+
("a", c_uint32),
111+
("b", AlignedStruct)
112+
]
113+
114+
main = Main.from_buffer(data)
115+
self.assertEqual(alignment(main.b), 8)
116+
self.assertEqual(alignment(main), 8)
117+
self.assertEqual(sizeof(main.b), 8)
118+
self.assertEqual(sizeof(main), 16)
119+
self.assertEqual(main.a, 1)
120+
self.assertEqual(main.b.x, 3)
121+
self.assertEqual(main.b.y, 4)
122+
self.assertEqual(Main.b.offset, 8)
123+
self.assertEqual(Main.b.size, 8)
124+
125+
def test_aligned_union(self):
126+
for sbase, ubase, e in (
127+
(LittleEndianStructure, LittleEndianUnion, "<"),
128+
(BigEndianStructure, BigEndianUnion, ">"),
129+
):
130+
data = bytearray(struct.pack(f"{e}4i", 1, 2, 3, 4))
131+
class AlignedUnion(ubase):
132+
_align_ = 8
133+
_fields_ = [
134+
("a", c_uint32),
135+
("b", c_ubyte * 7),
136+
]
137+
138+
class Main(sbase):
139+
_fields_ = [
140+
("first", c_uint32),
141+
("union", AlignedUnion),
142+
]
143+
144+
main = Main.from_buffer(data)
145+
self.assertEqual(main.first, 1)
146+
self.assertEqual(main.union.a, 3)
147+
self.assertEqual(bytes(main.union.b), data[8:-1])
148+
self.assertEqual(Main.union.offset, 8)
149+
self.assertEqual(Main.union.size, 8)
150+
self.assertEqual(alignment(main.union), 8)
151+
self.assertEqual(alignment(main), 8)
152+
153+
def test_aligned_struct_in_union(self):
154+
for sbase, ubase, e in (
155+
(LittleEndianStructure, LittleEndianUnion, "<"),
156+
(BigEndianStructure, BigEndianUnion, ">"),
157+
):
158+
data = bytearray(struct.pack(f"{e}4i", 1, 2, 3, 4))
159+
class Sub(sbase):
160+
_align_ = 8
161+
_fields_ = [
162+
("x", c_uint32),
163+
("y", c_uint32),
164+
]
165+
166+
class MainUnion(ubase):
167+
_fields_ = [
168+
("a", c_uint32),
169+
("b", Sub),
170+
]
171+
172+
class Main(sbase):
173+
_fields_ = [
174+
("first", c_uint32),
175+
("union", MainUnion),
176+
]
177+
178+
main = Main.from_buffer(data)
179+
self.assertEqual(Main.first.size, 4)
180+
self.assertEqual(alignment(main.union), 8)
181+
self.assertEqual(alignment(main), 8)
182+
self.assertEqual(Main.union.offset, 8)
183+
self.assertEqual(Main.union.size, 8)
184+
self.assertEqual(main.first, 1)
185+
self.assertEqual(main.union.a, 3)
186+
self.assertEqual(main.union.b.x, 3)
187+
self.assertEqual(main.union.b.y, 4)
188+
189+
def test_smaller_aligned_subclassed_union(self):
190+
for sbase, ubase, e in (
191+
(LittleEndianStructure, LittleEndianUnion, "<"),
192+
(BigEndianStructure, BigEndianUnion, ">"),
193+
):
194+
data = bytearray(struct.pack(f"{e}H2xI", 1, 0xD60102D7))
195+
class SubUnion(ubase):
196+
_align_ = 2
197+
_fields_ = [
198+
("unsigned", c_ubyte),
199+
("signed", c_byte),
200+
]
201+
202+
class MainUnion(SubUnion):
203+
_fields_ = [
204+
("num", c_uint32)
205+
]
206+
207+
class Main(sbase):
208+
_fields_ = [
209+
("first", c_uint16),
210+
("union", MainUnion),
211+
]
212+
213+
main = Main.from_buffer(data)
214+
self.assertEqual(main.union.num, 0xD60102D7)
215+
self.assertEqual(main.union.unsigned, data[4])
216+
self.assertEqual(main.union.signed, data[4] - 256)
217+
self.assertEqual(alignment(main), 4)
218+
self.assertEqual(alignment(main.union), 4)
219+
self.assertEqual(Main.union.offset, 4)
220+
self.assertEqual(Main.union.size, 4)
221+
self.assertEqual(Main.first.size, 2)
222+
223+
def test_larger_aligned_subclassed_union(self):
224+
for ubase, e in (
225+
(LittleEndianUnion, "<"),
226+
(BigEndianUnion, ">"),
227+
):
228+
data = bytearray(struct.pack(f"{e}I4x", 0xD60102D6))
229+
class SubUnion(ubase):
230+
_align_ = 8
231+
_fields_ = [
232+
("unsigned", c_ubyte),
233+
("signed", c_byte),
234+
]
235+
236+
class Main(SubUnion):
237+
_fields_ = [
238+
("num", c_uint32)
239+
]
240+
241+
main = Main.from_buffer(data)
242+
self.assertEqual(alignment(main), 8)
243+
self.assertEqual(sizeof(main), 8)
244+
self.assertEqual(main.num, 0xD60102D6)
245+
self.assertEqual(main.unsigned, 0xD6)
246+
self.assertEqual(main.signed, -42)
247+
248+
def test_aligned_packed_structures(self):
249+
for sbase, e in (
250+
(LittleEndianStructure, "<"),
251+
(BigEndianStructure, ">"),
252+
):
253+
data = bytearray(struct.pack(f"{e}B2H4xB", 1, 2, 3, 4))
254+
255+
class Inner(sbase):
256+
_align_ = 8
257+
_fields_ = [
258+
("x", c_uint16),
259+
("y", c_uint16),
260+
]
261+
262+
class Main(sbase):
263+
_pack_ = 1
264+
_fields_ = [
265+
("a", c_ubyte),
266+
("b", Inner),
267+
("c", c_ubyte),
268+
]
269+
270+
main = Main.from_buffer(data)
271+
self.assertEqual(sizeof(main), 10)
272+
self.assertEqual(Main.b.offset, 1)
273+
# Alignment == 8 because _pack_ wins out.
274+
self.assertEqual(alignment(main.b), 8)
275+
# Size is still 8 though since inside this Structure, it will have
276+
# effect.
277+
self.assertEqual(sizeof(main.b), 8)
278+
self.assertEqual(Main.c.offset, 9)
279+
self.assertEqual(main.a, 1)
280+
self.assertEqual(main.b.x, 2)
281+
self.assertEqual(main.b.y, 3)
282+
self.assertEqual(main.c, 4)
283+
284+
def test_negative_align(self):
285+
for base in (Structure, LittleEndianStructure, BigEndianStructure):
286+
with (
287+
self.subTest(base=base),
288+
self.assertRaisesRegex(
289+
ValueError,
290+
'_align_ must be a non-negative integer',
291+
)
292+
):
293+
class MyStructure(base):
294+
_align_ = -1
295+
_fields_ = []
296+
297+
def test_zero_align_no_fields(self):
298+
for base in (Structure, LittleEndianStructure, BigEndianStructure):
299+
with self.subTest(base=base):
300+
class MyStructure(base):
301+
_align_ = 0
302+
_fields_ = []
303+
304+
self.assertEqual(alignment(MyStructure), 1)
305+
self.assertEqual(alignment(MyStructure()), 1)
306+
307+
def test_zero_align_with_fields(self):
308+
for base in (Structure, LittleEndianStructure, BigEndianStructure):
309+
with self.subTest(base=base):
310+
class MyStructure(base):
311+
_align_ = 0
312+
_fields_ = [
313+
("x", c_ubyte),
314+
]
315+
316+
self.assertEqual(alignment(MyStructure), 1)
317+
self.assertEqual(alignment(MyStructure()), 1)
318+
319+
320+
if __name__ == '__main__':
321+
unittest.main()

0 commit comments

Comments
 (0)