ยปCore Development>Code coverage>Lib/ctypes/test/test_callbacks.py

Python code coverage for Lib/ctypes/test/test_callbacks.py

#countcontent
1n/aimport functools
2n/aimport unittest
3n/afrom ctypes import *
4n/afrom ctypes.test import need_symbol
5n/aimport _ctypes_test
6n/a
7n/aclass Callbacks(unittest.TestCase):
8n/a functype = CFUNCTYPE
9n/a
10n/a## def tearDown(self):
11n/a## import gc
12n/a## gc.collect()
13n/a
14n/a def callback(self, *args):
15n/a self.got_args = args
16n/a return args[-1]
17n/a
18n/a def check_type(self, typ, arg):
19n/a PROTO = self.functype.__func__(typ, typ)
20n/a result = PROTO(self.callback)(arg)
21n/a if typ == c_float:
22n/a self.assertAlmostEqual(result, arg, places=5)
23n/a else:
24n/a self.assertEqual(self.got_args, (arg,))
25n/a self.assertEqual(result, arg)
26n/a
27n/a PROTO = self.functype.__func__(typ, c_byte, typ)
28n/a result = PROTO(self.callback)(-3, arg)
29n/a if typ == c_float:
30n/a self.assertAlmostEqual(result, arg, places=5)
31n/a else:
32n/a self.assertEqual(self.got_args, (-3, arg))
33n/a self.assertEqual(result, arg)
34n/a
35n/a ################
36n/a
37n/a def test_byte(self):
38n/a self.check_type(c_byte, 42)
39n/a self.check_type(c_byte, -42)
40n/a
41n/a def test_ubyte(self):
42n/a self.check_type(c_ubyte, 42)
43n/a
44n/a def test_short(self):
45n/a self.check_type(c_short, 42)
46n/a self.check_type(c_short, -42)
47n/a
48n/a def test_ushort(self):
49n/a self.check_type(c_ushort, 42)
50n/a
51n/a def test_int(self):
52n/a self.check_type(c_int, 42)
53n/a self.check_type(c_int, -42)
54n/a
55n/a def test_uint(self):
56n/a self.check_type(c_uint, 42)
57n/a
58n/a def test_long(self):
59n/a self.check_type(c_long, 42)
60n/a self.check_type(c_long, -42)
61n/a
62n/a def test_ulong(self):
63n/a self.check_type(c_ulong, 42)
64n/a
65n/a def test_longlong(self):
66n/a self.check_type(c_longlong, 42)
67n/a self.check_type(c_longlong, -42)
68n/a
69n/a def test_ulonglong(self):
70n/a self.check_type(c_ulonglong, 42)
71n/a
72n/a def test_float(self):
73n/a # only almost equal: double -> float -> double
74n/a import math
75n/a self.check_type(c_float, math.e)
76n/a self.check_type(c_float, -math.e)
77n/a
78n/a def test_double(self):
79n/a self.check_type(c_double, 3.14)
80n/a self.check_type(c_double, -3.14)
81n/a
82n/a def test_longdouble(self):
83n/a self.check_type(c_longdouble, 3.14)
84n/a self.check_type(c_longdouble, -3.14)
85n/a
86n/a def test_char(self):
87n/a self.check_type(c_char, b"x")
88n/a self.check_type(c_char, b"a")
89n/a
90n/a # disabled: would now (correctly) raise a RuntimeWarning about
91n/a # a memory leak. A callback function cannot return a non-integral
92n/a # C type without causing a memory leak.
93n/a @unittest.skip('test disabled')
94n/a def test_char_p(self):
95n/a self.check_type(c_char_p, "abc")
96n/a self.check_type(c_char_p, "def")
97n/a
98n/a def test_pyobject(self):
99n/a o = ()
100n/a from sys import getrefcount as grc
101n/a for o in (), [], object():
102n/a initial = grc(o)
103n/a # This call leaks a reference to 'o'...
104n/a self.check_type(py_object, o)
105n/a before = grc(o)
106n/a # ...but this call doesn't leak any more. Where is the refcount?
107n/a self.check_type(py_object, o)
108n/a after = grc(o)
109n/a self.assertEqual((after, o), (before, o))
110n/a
111n/a def test_unsupported_restype_1(self):
112n/a # Only "fundamental" result types are supported for callback
113n/a # functions, the type must have a non-NULL stgdict->setfunc.
114n/a # POINTER(c_double), for example, is not supported.
115n/a
116n/a prototype = self.functype.__func__(POINTER(c_double))
117n/a # The type is checked when the prototype is called
118n/a self.assertRaises(TypeError, prototype, lambda: None)
119n/a
120n/a def test_unsupported_restype_2(self):
121n/a prototype = self.functype.__func__(object)
122n/a self.assertRaises(TypeError, prototype, lambda: None)
123n/a
124n/a def test_issue_7959(self):
125n/a proto = self.functype.__func__(None)
126n/a
127n/a class X(object):
128n/a def func(self): pass
129n/a def __init__(self):
130n/a self.v = proto(self.func)
131n/a
132n/a import gc
133n/a for i in range(32):
134n/a X()
135n/a gc.collect()
136n/a live = [x for x in gc.get_objects()
137n/a if isinstance(x, X)]
138n/a self.assertEqual(len(live), 0)
139n/a
140n/a def test_issue12483(self):
141n/a import gc
142n/a class Nasty:
143n/a def __del__(self):
144n/a gc.collect()
145n/a CFUNCTYPE(None)(lambda x=Nasty(): None)
146n/a
147n/a
148n/a@need_symbol('WINFUNCTYPE')
149n/aclass StdcallCallbacks(Callbacks):
150n/a try:
151n/a functype = WINFUNCTYPE
152n/a except NameError:
153n/a pass
154n/a
155n/a################################################################
156n/a
157n/aclass SampleCallbacksTestCase(unittest.TestCase):
158n/a
159n/a def test_integrate(self):
160n/a # Derived from some then non-working code, posted by David Foster
161n/a dll = CDLL(_ctypes_test.__file__)
162n/a
163n/a # The function prototype called by 'integrate': double func(double);
164n/a CALLBACK = CFUNCTYPE(c_double, c_double)
165n/a
166n/a # The integrate function itself, exposed from the _ctypes_test dll
167n/a integrate = dll.integrate
168n/a integrate.argtypes = (c_double, c_double, CALLBACK, c_long)
169n/a integrate.restype = c_double
170n/a
171n/a def func(x):
172n/a return x**2
173n/a
174n/a result = integrate(0.0, 1.0, CALLBACK(func), 10)
175n/a diff = abs(result - 1./3.)
176n/a
177n/a self.assertLess(diff, 0.01, "%s not less than 0.01" % diff)
178n/a
179n/a def test_issue_8959_a(self):
180n/a from ctypes.util import find_library
181n/a libc_path = find_library("c")
182n/a if not libc_path:
183n/a self.skipTest('could not find libc')
184n/a libc = CDLL(libc_path)
185n/a
186n/a @CFUNCTYPE(c_int, POINTER(c_int), POINTER(c_int))
187n/a def cmp_func(a, b):
188n/a return a[0] - b[0]
189n/a
190n/a array = (c_int * 5)(5, 1, 99, 7, 33)
191n/a
192n/a libc.qsort(array, len(array), sizeof(c_int), cmp_func)
193n/a self.assertEqual(array[:], [1, 5, 7, 33, 99])
194n/a
195n/a @need_symbol('WINFUNCTYPE')
196n/a def test_issue_8959_b(self):
197n/a from ctypes.wintypes import BOOL, HWND, LPARAM
198n/a global windowCount
199n/a windowCount = 0
200n/a
201n/a @WINFUNCTYPE(BOOL, HWND, LPARAM)
202n/a def EnumWindowsCallbackFunc(hwnd, lParam):
203n/a global windowCount
204n/a windowCount += 1
205n/a return True #Allow windows to keep enumerating
206n/a
207n/a windll.user32.EnumWindows(EnumWindowsCallbackFunc, 0)
208n/a
209n/a def test_callback_register_int(self):
210n/a # Issue #8275: buggy handling of callback args under Win64
211n/a # NOTE: should be run on release builds as well
212n/a dll = CDLL(_ctypes_test.__file__)
213n/a CALLBACK = CFUNCTYPE(c_int, c_int, c_int, c_int, c_int, c_int)
214n/a # All this function does is call the callback with its args squared
215n/a func = dll._testfunc_cbk_reg_int
216n/a func.argtypes = (c_int, c_int, c_int, c_int, c_int, CALLBACK)
217n/a func.restype = c_int
218n/a
219n/a def callback(a, b, c, d, e):
220n/a return a + b + c + d + e
221n/a
222n/a result = func(2, 3, 4, 5, 6, CALLBACK(callback))
223n/a self.assertEqual(result, callback(2*2, 3*3, 4*4, 5*5, 6*6))
224n/a
225n/a def test_callback_register_double(self):
226n/a # Issue #8275: buggy handling of callback args under Win64
227n/a # NOTE: should be run on release builds as well
228n/a dll = CDLL(_ctypes_test.__file__)
229n/a CALLBACK = CFUNCTYPE(c_double, c_double, c_double, c_double,
230n/a c_double, c_double)
231n/a # All this function does is call the callback with its args squared
232n/a func = dll._testfunc_cbk_reg_double
233n/a func.argtypes = (c_double, c_double, c_double,
234n/a c_double, c_double, CALLBACK)
235n/a func.restype = c_double
236n/a
237n/a def callback(a, b, c, d, e):
238n/a return a + b + c + d + e
239n/a
240n/a result = func(1.1, 2.2, 3.3, 4.4, 5.5, CALLBACK(callback))
241n/a self.assertEqual(result,
242n/a callback(1.1*1.1, 2.2*2.2, 3.3*3.3, 4.4*4.4, 5.5*5.5))
243n/a
244n/a def test_callback_large_struct(self):
245n/a class Check: pass
246n/a
247n/a class X(Structure):
248n/a _fields_ = [
249n/a ('first', c_ulong),
250n/a ('second', c_ulong),
251n/a ('third', c_ulong),
252n/a ]
253n/a
254n/a def callback(check, s):
255n/a check.first = s.first
256n/a check.second = s.second
257n/a check.third = s.third
258n/a
259n/a check = Check()
260n/a s = X()
261n/a s.first = 0xdeadbeef
262n/a s.second = 0xcafebabe
263n/a s.third = 0x0bad1dea
264n/a
265n/a CALLBACK = CFUNCTYPE(None, X)
266n/a dll = CDLL(_ctypes_test.__file__)
267n/a func = dll._testfunc_cbk_large_struct
268n/a func.argtypes = (X, CALLBACK)
269n/a func.restype = None
270n/a # the function just calls the callback with the passed structure
271n/a func(s, CALLBACK(functools.partial(callback, check)))
272n/a self.assertEqual(check.first, s.first)
273n/a self.assertEqual(check.second, s.second)
274n/a self.assertEqual(check.third, s.third)
275n/a self.assertEqual(check.first, 0xdeadbeef)
276n/a self.assertEqual(check.second, 0xcafebabe)
277n/a self.assertEqual(check.third, 0x0bad1dea)
278n/a
279n/a################################################################
280n/a
281n/aif __name__ == '__main__':
282n/a unittest.main()