Skip to content

Commit 019be59

Browse files
committed
Add ctypes/test/*.py from CPython 3.11
1 parent 84caa50 commit 019be59

Some content is hidden

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

53 files changed

+7303
-0
lines changed

Lib/ctypes/test/__init__.py

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import os
2+
import unittest
3+
from test import support
4+
from test.support import import_helper
5+
6+
7+
# skip tests if _ctypes was not built
8+
ctypes = import_helper.import_module('ctypes')
9+
ctypes_symbols = dir(ctypes)
10+
11+
def need_symbol(name):
12+
return unittest.skipUnless(name in ctypes_symbols,
13+
'{!r} is required'.format(name))
14+
15+
def load_tests(*args):
16+
return support.load_package_tests(os.path.dirname(__file__), *args)

Lib/ctypes/test/__main__.py

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
from ctypes.test import load_tests
2+
import unittest
3+
4+
unittest.main()

Lib/ctypes/test/test_anon.py

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import unittest
2+
import test.support
3+
from ctypes import *
4+
5+
class AnonTest(unittest.TestCase):
6+
7+
def test_anon(self):
8+
class ANON(Union):
9+
_fields_ = [("a", c_int),
10+
("b", c_int)]
11+
12+
class Y(Structure):
13+
_fields_ = [("x", c_int),
14+
("_", ANON),
15+
("y", c_int)]
16+
_anonymous_ = ["_"]
17+
18+
self.assertEqual(Y.a.offset, sizeof(c_int))
19+
self.assertEqual(Y.b.offset, sizeof(c_int))
20+
21+
self.assertEqual(ANON.a.offset, 0)
22+
self.assertEqual(ANON.b.offset, 0)
23+
24+
def test_anon_nonseq(self):
25+
# TypeError: _anonymous_ must be a sequence
26+
self.assertRaises(TypeError,
27+
lambda: type(Structure)("Name",
28+
(Structure,),
29+
{"_fields_": [], "_anonymous_": 42}))
30+
31+
def test_anon_nonmember(self):
32+
# AttributeError: type object 'Name' has no attribute 'x'
33+
self.assertRaises(AttributeError,
34+
lambda: type(Structure)("Name",
35+
(Structure,),
36+
{"_fields_": [],
37+
"_anonymous_": ["x"]}))
38+
39+
@test.support.cpython_only
40+
def test_issue31490(self):
41+
# There shouldn't be an assertion failure in case the class has an
42+
# attribute whose name is specified in _anonymous_ but not in _fields_.
43+
44+
# AttributeError: 'x' is specified in _anonymous_ but not in _fields_
45+
with self.assertRaises(AttributeError):
46+
class Name(Structure):
47+
_fields_ = []
48+
_anonymous_ = ["x"]
49+
x = 42
50+
51+
def test_nested(self):
52+
class ANON_S(Structure):
53+
_fields_ = [("a", c_int)]
54+
55+
class ANON_U(Union):
56+
_fields_ = [("_", ANON_S),
57+
("b", c_int)]
58+
_anonymous_ = ["_"]
59+
60+
class Y(Structure):
61+
_fields_ = [("x", c_int),
62+
("_", ANON_U),
63+
("y", c_int)]
64+
_anonymous_ = ["_"]
65+
66+
self.assertEqual(Y.x.offset, 0)
67+
self.assertEqual(Y.a.offset, sizeof(c_int))
68+
self.assertEqual(Y.b.offset, sizeof(c_int))
69+
self.assertEqual(Y._.offset, sizeof(c_int))
70+
self.assertEqual(Y.y.offset, sizeof(c_int) * 2)
71+
72+
if __name__ == "__main__":
73+
unittest.main()
+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import unittest
2+
from ctypes import *
3+
from binascii import hexlify
4+
import re
5+
6+
def dump(obj):
7+
# helper function to dump memory contents in hex, with a hyphen
8+
# between the bytes.
9+
h = hexlify(memoryview(obj)).decode()
10+
return re.sub(r"(..)", r"\1-", h)[:-1]
11+
12+
13+
class Value(Structure):
14+
_fields_ = [("val", c_byte)]
15+
16+
class Container(Structure):
17+
_fields_ = [("pvalues", POINTER(Value))]
18+
19+
class Test(unittest.TestCase):
20+
def test(self):
21+
# create an array of 4 values
22+
val_array = (Value * 4)()
23+
24+
# create a container, which holds a pointer to the pvalues array.
25+
c = Container()
26+
c.pvalues = val_array
27+
28+
# memory contains 4 NUL bytes now, that's correct
29+
self.assertEqual("00-00-00-00", dump(val_array))
30+
31+
# set the values of the array through the pointer:
32+
for i in range(4):
33+
c.pvalues[i].val = i + 1
34+
35+
values = [c.pvalues[i].val for i in range(4)]
36+
37+
# These are the expected results: here s the bug!
38+
self.assertEqual(
39+
(values, dump(val_array)),
40+
([1, 2, 3, 4], "01-02-03-04")
41+
)
42+
43+
def test_2(self):
44+
45+
val_array = (Value * 4)()
46+
47+
# memory contains 4 NUL bytes now, that's correct
48+
self.assertEqual("00-00-00-00", dump(val_array))
49+
50+
ptr = cast(val_array, POINTER(Value))
51+
# set the values of the array through the pointer:
52+
for i in range(4):
53+
ptr[i].val = i + 1
54+
55+
values = [ptr[i].val for i in range(4)]
56+
57+
# These are the expected results: here s the bug!
58+
self.assertEqual(
59+
(values, dump(val_array)),
60+
([1, 2, 3, 4], "01-02-03-04")
61+
)
62+
63+
if __name__ == "__main__":
64+
unittest.main()

Lib/ctypes/test/test_arrays.py

+238
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
import unittest
2+
from test.support import bigmemtest, _2G
3+
import sys
4+
from ctypes import *
5+
6+
from ctypes.test import need_symbol
7+
8+
formats = "bBhHiIlLqQfd"
9+
10+
formats = c_byte, c_ubyte, c_short, c_ushort, c_int, c_uint, \
11+
c_long, c_ulonglong, c_float, c_double, c_longdouble
12+
13+
class ArrayTestCase(unittest.TestCase):
14+
def test_simple(self):
15+
# create classes holding simple numeric types, and check
16+
# various properties.
17+
18+
init = list(range(15, 25))
19+
20+
for fmt in formats:
21+
alen = len(init)
22+
int_array = ARRAY(fmt, alen)
23+
24+
ia = int_array(*init)
25+
# length of instance ok?
26+
self.assertEqual(len(ia), alen)
27+
28+
# slot values ok?
29+
values = [ia[i] for i in range(alen)]
30+
self.assertEqual(values, init)
31+
32+
# out-of-bounds accesses should be caught
33+
with self.assertRaises(IndexError): ia[alen]
34+
with self.assertRaises(IndexError): ia[-alen-1]
35+
36+
# change the items
37+
from operator import setitem
38+
new_values = list(range(42, 42+alen))
39+
[setitem(ia, n, new_values[n]) for n in range(alen)]
40+
values = [ia[i] for i in range(alen)]
41+
self.assertEqual(values, new_values)
42+
43+
# are the items initialized to 0?
44+
ia = int_array()
45+
values = [ia[i] for i in range(alen)]
46+
self.assertEqual(values, [0] * alen)
47+
48+
# Too many initializers should be caught
49+
self.assertRaises(IndexError, int_array, *range(alen*2))
50+
51+
CharArray = ARRAY(c_char, 3)
52+
53+
ca = CharArray(b"a", b"b", b"c")
54+
55+
# Should this work? It doesn't:
56+
# CharArray("abc")
57+
self.assertRaises(TypeError, CharArray, "abc")
58+
59+
self.assertEqual(ca[0], b"a")
60+
self.assertEqual(ca[1], b"b")
61+
self.assertEqual(ca[2], b"c")
62+
self.assertEqual(ca[-3], b"a")
63+
self.assertEqual(ca[-2], b"b")
64+
self.assertEqual(ca[-1], b"c")
65+
66+
self.assertEqual(len(ca), 3)
67+
68+
# cannot delete items
69+
from operator import delitem
70+
self.assertRaises(TypeError, delitem, ca, 0)
71+
72+
def test_step_overflow(self):
73+
a = (c_int * 5)()
74+
a[3::sys.maxsize] = (1,)
75+
self.assertListEqual(a[3::sys.maxsize], [1])
76+
a = (c_char * 5)()
77+
a[3::sys.maxsize] = b"A"
78+
self.assertEqual(a[3::sys.maxsize], b"A")
79+
a = (c_wchar * 5)()
80+
a[3::sys.maxsize] = u"X"
81+
self.assertEqual(a[3::sys.maxsize], u"X")
82+
83+
def test_numeric_arrays(self):
84+
85+
alen = 5
86+
87+
numarray = ARRAY(c_int, alen)
88+
89+
na = numarray()
90+
values = [na[i] for i in range(alen)]
91+
self.assertEqual(values, [0] * alen)
92+
93+
na = numarray(*[c_int()] * alen)
94+
values = [na[i] for i in range(alen)]
95+
self.assertEqual(values, [0]*alen)
96+
97+
na = numarray(1, 2, 3, 4, 5)
98+
values = [i for i in na]
99+
self.assertEqual(values, [1, 2, 3, 4, 5])
100+
101+
na = numarray(*map(c_int, (1, 2, 3, 4, 5)))
102+
values = [i for i in na]
103+
self.assertEqual(values, [1, 2, 3, 4, 5])
104+
105+
def test_classcache(self):
106+
self.assertIsNot(ARRAY(c_int, 3), ARRAY(c_int, 4))
107+
self.assertIs(ARRAY(c_int, 3), ARRAY(c_int, 3))
108+
109+
def test_from_address(self):
110+
# Failed with 0.9.8, reported by JUrner
111+
p = create_string_buffer(b"foo")
112+
sz = (c_char * 3).from_address(addressof(p))
113+
self.assertEqual(sz[:], b"foo")
114+
self.assertEqual(sz[::], b"foo")
115+
self.assertEqual(sz[::-1], b"oof")
116+
self.assertEqual(sz[::3], b"f")
117+
self.assertEqual(sz[1:4:2], b"o")
118+
self.assertEqual(sz.value, b"foo")
119+
120+
@need_symbol('create_unicode_buffer')
121+
def test_from_addressW(self):
122+
p = create_unicode_buffer("foo")
123+
sz = (c_wchar * 3).from_address(addressof(p))
124+
self.assertEqual(sz[:], "foo")
125+
self.assertEqual(sz[::], "foo")
126+
self.assertEqual(sz[::-1], "oof")
127+
self.assertEqual(sz[::3], "f")
128+
self.assertEqual(sz[1:4:2], "o")
129+
self.assertEqual(sz.value, "foo")
130+
131+
def test_cache(self):
132+
# Array types are cached internally in the _ctypes extension,
133+
# in a WeakValueDictionary. Make sure the array type is
134+
# removed from the cache when the itemtype goes away. This
135+
# test will not fail, but will show a leak in the testsuite.
136+
137+
# Create a new type:
138+
class my_int(c_int):
139+
pass
140+
# Create a new array type based on it:
141+
t1 = my_int * 1
142+
t2 = my_int * 1
143+
self.assertIs(t1, t2)
144+
145+
def test_subclass(self):
146+
class T(Array):
147+
_type_ = c_int
148+
_length_ = 13
149+
class U(T):
150+
pass
151+
class V(U):
152+
pass
153+
class W(V):
154+
pass
155+
class X(T):
156+
_type_ = c_short
157+
class Y(T):
158+
_length_ = 187
159+
160+
for c in [T, U, V, W]:
161+
self.assertEqual(c._type_, c_int)
162+
self.assertEqual(c._length_, 13)
163+
self.assertEqual(c()._type_, c_int)
164+
self.assertEqual(c()._length_, 13)
165+
166+
self.assertEqual(X._type_, c_short)
167+
self.assertEqual(X._length_, 13)
168+
self.assertEqual(X()._type_, c_short)
169+
self.assertEqual(X()._length_, 13)
170+
171+
self.assertEqual(Y._type_, c_int)
172+
self.assertEqual(Y._length_, 187)
173+
self.assertEqual(Y()._type_, c_int)
174+
self.assertEqual(Y()._length_, 187)
175+
176+
def test_bad_subclass(self):
177+
with self.assertRaises(AttributeError):
178+
class T(Array):
179+
pass
180+
with self.assertRaises(AttributeError):
181+
class T(Array):
182+
_type_ = c_int
183+
with self.assertRaises(AttributeError):
184+
class T(Array):
185+
_length_ = 13
186+
187+
def test_bad_length(self):
188+
with self.assertRaises(ValueError):
189+
class T(Array):
190+
_type_ = c_int
191+
_length_ = - sys.maxsize * 2
192+
with self.assertRaises(ValueError):
193+
class T(Array):
194+
_type_ = c_int
195+
_length_ = -1
196+
with self.assertRaises(TypeError):
197+
class T(Array):
198+
_type_ = c_int
199+
_length_ = 1.87
200+
with self.assertRaises(OverflowError):
201+
class T(Array):
202+
_type_ = c_int
203+
_length_ = sys.maxsize * 2
204+
205+
def test_zero_length(self):
206+
# _length_ can be zero.
207+
class T(Array):
208+
_type_ = c_int
209+
_length_ = 0
210+
211+
def test_empty_element_struct(self):
212+
class EmptyStruct(Structure):
213+
_fields_ = []
214+
215+
obj = (EmptyStruct * 2)() # bpo37188: Floating point exception
216+
self.assertEqual(sizeof(obj), 0)
217+
218+
def test_empty_element_array(self):
219+
class EmptyArray(Array):
220+
_type_ = c_int
221+
_length_ = 0
222+
223+
obj = (EmptyArray * 2)() # bpo37188: Floating point exception
224+
self.assertEqual(sizeof(obj), 0)
225+
226+
def test_bpo36504_signed_int_overflow(self):
227+
# The overflow check in PyCArrayType_new() could cause signed integer
228+
# overflow.
229+
with self.assertRaises(OverflowError):
230+
c_char * sys.maxsize * 2
231+
232+
@unittest.skipUnless(sys.maxsize > 2**32, 'requires 64bit platform')
233+
@bigmemtest(size=_2G, memuse=1, dry_run=False)
234+
def test_large_array(self, size):
235+
c_char * size
236+
237+
if __name__ == '__main__':
238+
unittest.main()

0 commit comments

Comments
 (0)