From d82e0bfe8b98a122ca443b356d81998c804b686e Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 21 Jun 2022 10:24:33 +0200 Subject: gh-93839: Move Lib/ctypes/test/ to Lib/test/test_ctypes/ (#94041) * Move Lib/ctypes/test/ to Lib/test/test_ctypes/ * Remove Lib/test/test_ctypes.py * Update imports and build system. --- Lib/ctypes/test/__init__.py | 16 - Lib/ctypes/test/__main__.py | 4 - Lib/ctypes/test/test_anon.py | 73 -- Lib/ctypes/test/test_array_in_pointer.py | 64 -- Lib/ctypes/test/test_arrays.py | 238 ------ Lib/ctypes/test/test_as_parameter.py | 230 ------ Lib/ctypes/test/test_bitfields.py | 297 -------- Lib/ctypes/test/test_buffers.py | 73 -- Lib/ctypes/test/test_bytes.py | 66 -- Lib/ctypes/test/test_byteswap.py | 364 --------- Lib/ctypes/test/test_callbacks.py | 330 --------- Lib/ctypes/test/test_cast.py | 99 --- Lib/ctypes/test/test_cfuncs.py | 212 ------ Lib/ctypes/test/test_checkretval.py | 36 - Lib/ctypes/test/test_delattr.py | 21 - Lib/ctypes/test/test_errno.py | 76 -- Lib/ctypes/test/test_find.py | 127 ---- Lib/ctypes/test/test_frombuffer.py | 141 ---- Lib/ctypes/test/test_funcptr.py | 132 ---- Lib/ctypes/test/test_functions.py | 383 ---------- Lib/ctypes/test/test_incomplete.py | 42 -- Lib/ctypes/test/test_init.py | 40 - Lib/ctypes/test/test_internals.py | 100 --- Lib/ctypes/test/test_keeprefs.py | 153 ---- Lib/ctypes/test/test_libc.py | 33 - Lib/ctypes/test/test_loading.py | 182 ----- Lib/ctypes/test/test_macholib.py | 110 --- Lib/ctypes/test/test_memfunctions.py | 79 -- Lib/ctypes/test/test_numbers.py | 295 -------- Lib/ctypes/test/test_objects.py | 67 -- Lib/ctypes/test/test_parameters.py | 250 ------- Lib/ctypes/test/test_pep3118.py | 233 ------ Lib/ctypes/test/test_pickling.py | 81 -- Lib/ctypes/test/test_pointers.py | 223 ------ Lib/ctypes/test/test_prototypes.py | 222 ------ Lib/ctypes/test/test_python_api.py | 85 --- Lib/ctypes/test/test_random_things.py | 77 -- Lib/ctypes/test/test_refcounts.py | 101 --- Lib/ctypes/test/test_repr.py | 29 - Lib/ctypes/test/test_returnfuncptrs.py | 66 -- Lib/ctypes/test/test_simplesubclasses.py | 55 -- Lib/ctypes/test/test_sizes.py | 33 - Lib/ctypes/test/test_slicing.py | 167 ----- Lib/ctypes/test/test_stringptr.py | 77 -- Lib/ctypes/test/test_strings.py | 145 ---- Lib/ctypes/test/test_struct_fields.py | 82 --- Lib/ctypes/test/test_structures.py | 812 --------------------- Lib/ctypes/test/test_unaligned_structures.py | 43 -- Lib/ctypes/test/test_unicode.py | 64 -- Lib/ctypes/test/test_values.py | 103 --- Lib/ctypes/test/test_varsize_struct.py | 50 -- Lib/ctypes/test/test_win32.py | 136 ---- Lib/ctypes/test/test_wintypes.py | 43 -- Lib/test/leakers/test_ctypes.py | 2 +- Lib/test/test_ctypes.py | 10 - Lib/test/test_ctypes/__init__.py | 16 + Lib/test/test_ctypes/__main__.py | 4 + Lib/test/test_ctypes/test_anon.py | 73 ++ Lib/test/test_ctypes/test_array_in_pointer.py | 64 ++ Lib/test/test_ctypes/test_arrays.py | 238 ++++++ Lib/test/test_ctypes/test_as_parameter.py | 230 ++++++ Lib/test/test_ctypes/test_bitfields.py | 297 ++++++++ Lib/test/test_ctypes/test_buffers.py | 73 ++ Lib/test/test_ctypes/test_bytes.py | 66 ++ Lib/test/test_ctypes/test_byteswap.py | 364 +++++++++ Lib/test/test_ctypes/test_callbacks.py | 330 +++++++++ Lib/test/test_ctypes/test_cast.py | 99 +++ Lib/test/test_ctypes/test_cfuncs.py | 212 ++++++ Lib/test/test_ctypes/test_checkretval.py | 36 + Lib/test/test_ctypes/test_delattr.py | 21 + Lib/test/test_ctypes/test_errno.py | 76 ++ Lib/test/test_ctypes/test_find.py | 127 ++++ Lib/test/test_ctypes/test_frombuffer.py | 141 ++++ Lib/test/test_ctypes/test_funcptr.py | 132 ++++ Lib/test/test_ctypes/test_functions.py | 383 ++++++++++ Lib/test/test_ctypes/test_incomplete.py | 42 ++ Lib/test/test_ctypes/test_init.py | 40 + Lib/test/test_ctypes/test_internals.py | 100 +++ Lib/test/test_ctypes/test_keeprefs.py | 153 ++++ Lib/test/test_ctypes/test_libc.py | 33 + Lib/test/test_ctypes/test_loading.py | 182 +++++ Lib/test/test_ctypes/test_macholib.py | 110 +++ Lib/test/test_ctypes/test_memfunctions.py | 79 ++ Lib/test/test_ctypes/test_numbers.py | 295 ++++++++ Lib/test/test_ctypes/test_objects.py | 67 ++ Lib/test/test_ctypes/test_parameters.py | 250 +++++++ Lib/test/test_ctypes/test_pep3118.py | 233 ++++++ Lib/test/test_ctypes/test_pickling.py | 81 ++ Lib/test/test_ctypes/test_pointers.py | 223 ++++++ Lib/test/test_ctypes/test_prototypes.py | 222 ++++++ Lib/test/test_ctypes/test_python_api.py | 85 +++ Lib/test/test_ctypes/test_random_things.py | 77 ++ Lib/test/test_ctypes/test_refcounts.py | 101 +++ Lib/test/test_ctypes/test_repr.py | 29 + Lib/test/test_ctypes/test_returnfuncptrs.py | 66 ++ Lib/test/test_ctypes/test_simplesubclasses.py | 55 ++ Lib/test/test_ctypes/test_sizes.py | 33 + Lib/test/test_ctypes/test_slicing.py | 167 +++++ Lib/test/test_ctypes/test_stringptr.py | 77 ++ Lib/test/test_ctypes/test_strings.py | 145 ++++ Lib/test/test_ctypes/test_struct_fields.py | 82 +++ Lib/test/test_ctypes/test_structures.py | 812 +++++++++++++++++++++ Lib/test/test_ctypes/test_unaligned_structures.py | 43 ++ Lib/test/test_ctypes/test_unicode.py | 64 ++ Lib/test/test_ctypes/test_values.py | 103 +++ Lib/test/test_ctypes/test_varsize_struct.py | 50 ++ Lib/test/test_ctypes/test_win32.py | 136 ++++ Lib/test/test_ctypes/test_wintypes.py | 43 ++ Makefile.pre.in | 4 +- .../2022-06-20-23-04-52.gh-issue-93839.OE3Ybk.rst | 2 + PCbuild/lib.pyproj | 109 ++- Tools/wasm/wasm_assets.py | 1 - 112 files changed, 7319 insertions(+), 7329 deletions(-) delete mode 100644 Lib/ctypes/test/__init__.py delete mode 100644 Lib/ctypes/test/__main__.py delete mode 100644 Lib/ctypes/test/test_anon.py delete mode 100644 Lib/ctypes/test/test_array_in_pointer.py delete mode 100644 Lib/ctypes/test/test_arrays.py delete mode 100644 Lib/ctypes/test/test_as_parameter.py delete mode 100644 Lib/ctypes/test/test_bitfields.py delete mode 100644 Lib/ctypes/test/test_buffers.py delete mode 100644 Lib/ctypes/test/test_bytes.py delete mode 100644 Lib/ctypes/test/test_byteswap.py delete mode 100644 Lib/ctypes/test/test_callbacks.py delete mode 100644 Lib/ctypes/test/test_cast.py delete mode 100644 Lib/ctypes/test/test_cfuncs.py delete mode 100644 Lib/ctypes/test/test_checkretval.py delete mode 100644 Lib/ctypes/test/test_delattr.py delete mode 100644 Lib/ctypes/test/test_errno.py delete mode 100644 Lib/ctypes/test/test_find.py delete mode 100644 Lib/ctypes/test/test_frombuffer.py delete mode 100644 Lib/ctypes/test/test_funcptr.py delete mode 100644 Lib/ctypes/test/test_functions.py delete mode 100644 Lib/ctypes/test/test_incomplete.py delete mode 100644 Lib/ctypes/test/test_init.py delete mode 100644 Lib/ctypes/test/test_internals.py delete mode 100644 Lib/ctypes/test/test_keeprefs.py delete mode 100644 Lib/ctypes/test/test_libc.py delete mode 100644 Lib/ctypes/test/test_loading.py delete mode 100644 Lib/ctypes/test/test_macholib.py delete mode 100644 Lib/ctypes/test/test_memfunctions.py delete mode 100644 Lib/ctypes/test/test_numbers.py delete mode 100644 Lib/ctypes/test/test_objects.py delete mode 100644 Lib/ctypes/test/test_parameters.py delete mode 100644 Lib/ctypes/test/test_pep3118.py delete mode 100644 Lib/ctypes/test/test_pickling.py delete mode 100644 Lib/ctypes/test/test_pointers.py delete mode 100644 Lib/ctypes/test/test_prototypes.py delete mode 100644 Lib/ctypes/test/test_python_api.py delete mode 100644 Lib/ctypes/test/test_random_things.py delete mode 100644 Lib/ctypes/test/test_refcounts.py delete mode 100644 Lib/ctypes/test/test_repr.py delete mode 100644 Lib/ctypes/test/test_returnfuncptrs.py delete mode 100644 Lib/ctypes/test/test_simplesubclasses.py delete mode 100644 Lib/ctypes/test/test_sizes.py delete mode 100644 Lib/ctypes/test/test_slicing.py delete mode 100644 Lib/ctypes/test/test_stringptr.py delete mode 100644 Lib/ctypes/test/test_strings.py delete mode 100644 Lib/ctypes/test/test_struct_fields.py delete mode 100644 Lib/ctypes/test/test_structures.py delete mode 100644 Lib/ctypes/test/test_unaligned_structures.py delete mode 100644 Lib/ctypes/test/test_unicode.py delete mode 100644 Lib/ctypes/test/test_values.py delete mode 100644 Lib/ctypes/test/test_varsize_struct.py delete mode 100644 Lib/ctypes/test/test_win32.py delete mode 100644 Lib/ctypes/test/test_wintypes.py delete mode 100644 Lib/test/test_ctypes.py create mode 100644 Lib/test/test_ctypes/__init__.py create mode 100644 Lib/test/test_ctypes/__main__.py create mode 100644 Lib/test/test_ctypes/test_anon.py create mode 100644 Lib/test/test_ctypes/test_array_in_pointer.py create mode 100644 Lib/test/test_ctypes/test_arrays.py create mode 100644 Lib/test/test_ctypes/test_as_parameter.py create mode 100644 Lib/test/test_ctypes/test_bitfields.py create mode 100644 Lib/test/test_ctypes/test_buffers.py create mode 100644 Lib/test/test_ctypes/test_bytes.py create mode 100644 Lib/test/test_ctypes/test_byteswap.py create mode 100644 Lib/test/test_ctypes/test_callbacks.py create mode 100644 Lib/test/test_ctypes/test_cast.py create mode 100644 Lib/test/test_ctypes/test_cfuncs.py create mode 100644 Lib/test/test_ctypes/test_checkretval.py create mode 100644 Lib/test/test_ctypes/test_delattr.py create mode 100644 Lib/test/test_ctypes/test_errno.py create mode 100644 Lib/test/test_ctypes/test_find.py create mode 100644 Lib/test/test_ctypes/test_frombuffer.py create mode 100644 Lib/test/test_ctypes/test_funcptr.py create mode 100644 Lib/test/test_ctypes/test_functions.py create mode 100644 Lib/test/test_ctypes/test_incomplete.py create mode 100644 Lib/test/test_ctypes/test_init.py create mode 100644 Lib/test/test_ctypes/test_internals.py create mode 100644 Lib/test/test_ctypes/test_keeprefs.py create mode 100644 Lib/test/test_ctypes/test_libc.py create mode 100644 Lib/test/test_ctypes/test_loading.py create mode 100644 Lib/test/test_ctypes/test_macholib.py create mode 100644 Lib/test/test_ctypes/test_memfunctions.py create mode 100644 Lib/test/test_ctypes/test_numbers.py create mode 100644 Lib/test/test_ctypes/test_objects.py create mode 100644 Lib/test/test_ctypes/test_parameters.py create mode 100644 Lib/test/test_ctypes/test_pep3118.py create mode 100644 Lib/test/test_ctypes/test_pickling.py create mode 100644 Lib/test/test_ctypes/test_pointers.py create mode 100644 Lib/test/test_ctypes/test_prototypes.py create mode 100644 Lib/test/test_ctypes/test_python_api.py create mode 100644 Lib/test/test_ctypes/test_random_things.py create mode 100644 Lib/test/test_ctypes/test_refcounts.py create mode 100644 Lib/test/test_ctypes/test_repr.py create mode 100644 Lib/test/test_ctypes/test_returnfuncptrs.py create mode 100644 Lib/test/test_ctypes/test_simplesubclasses.py create mode 100644 Lib/test/test_ctypes/test_sizes.py create mode 100644 Lib/test/test_ctypes/test_slicing.py create mode 100644 Lib/test/test_ctypes/test_stringptr.py create mode 100644 Lib/test/test_ctypes/test_strings.py create mode 100644 Lib/test/test_ctypes/test_struct_fields.py create mode 100644 Lib/test/test_ctypes/test_structures.py create mode 100644 Lib/test/test_ctypes/test_unaligned_structures.py create mode 100644 Lib/test/test_ctypes/test_unicode.py create mode 100644 Lib/test/test_ctypes/test_values.py create mode 100644 Lib/test/test_ctypes/test_varsize_struct.py create mode 100644 Lib/test/test_ctypes/test_win32.py create mode 100644 Lib/test/test_ctypes/test_wintypes.py create mode 100644 Misc/NEWS.d/next/Tests/2022-06-20-23-04-52.gh-issue-93839.OE3Ybk.rst diff --git a/Lib/ctypes/test/__init__.py b/Lib/ctypes/test/__init__.py deleted file mode 100644 index 6e496fa..0000000 --- a/Lib/ctypes/test/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -import os -import unittest -from test import support -from test.support import import_helper - - -# skip tests if _ctypes was not built -ctypes = import_helper.import_module('ctypes') -ctypes_symbols = dir(ctypes) - -def need_symbol(name): - return unittest.skipUnless(name in ctypes_symbols, - '{!r} is required'.format(name)) - -def load_tests(*args): - return support.load_package_tests(os.path.dirname(__file__), *args) diff --git a/Lib/ctypes/test/__main__.py b/Lib/ctypes/test/__main__.py deleted file mode 100644 index 362a9ec..0000000 --- a/Lib/ctypes/test/__main__.py +++ /dev/null @@ -1,4 +0,0 @@ -from ctypes.test import load_tests -import unittest - -unittest.main() diff --git a/Lib/ctypes/test/test_anon.py b/Lib/ctypes/test/test_anon.py deleted file mode 100644 index d378392..0000000 --- a/Lib/ctypes/test/test_anon.py +++ /dev/null @@ -1,73 +0,0 @@ -import unittest -import test.support -from ctypes import * - -class AnonTest(unittest.TestCase): - - def test_anon(self): - class ANON(Union): - _fields_ = [("a", c_int), - ("b", c_int)] - - class Y(Structure): - _fields_ = [("x", c_int), - ("_", ANON), - ("y", c_int)] - _anonymous_ = ["_"] - - self.assertEqual(Y.a.offset, sizeof(c_int)) - self.assertEqual(Y.b.offset, sizeof(c_int)) - - self.assertEqual(ANON.a.offset, 0) - self.assertEqual(ANON.b.offset, 0) - - def test_anon_nonseq(self): - # TypeError: _anonymous_ must be a sequence - self.assertRaises(TypeError, - lambda: type(Structure)("Name", - (Structure,), - {"_fields_": [], "_anonymous_": 42})) - - def test_anon_nonmember(self): - # AttributeError: type object 'Name' has no attribute 'x' - self.assertRaises(AttributeError, - lambda: type(Structure)("Name", - (Structure,), - {"_fields_": [], - "_anonymous_": ["x"]})) - - @test.support.cpython_only - def test_issue31490(self): - # There shouldn't be an assertion failure in case the class has an - # attribute whose name is specified in _anonymous_ but not in _fields_. - - # AttributeError: 'x' is specified in _anonymous_ but not in _fields_ - with self.assertRaises(AttributeError): - class Name(Structure): - _fields_ = [] - _anonymous_ = ["x"] - x = 42 - - def test_nested(self): - class ANON_S(Structure): - _fields_ = [("a", c_int)] - - class ANON_U(Union): - _fields_ = [("_", ANON_S), - ("b", c_int)] - _anonymous_ = ["_"] - - class Y(Structure): - _fields_ = [("x", c_int), - ("_", ANON_U), - ("y", c_int)] - _anonymous_ = ["_"] - - self.assertEqual(Y.x.offset, 0) - self.assertEqual(Y.a.offset, sizeof(c_int)) - self.assertEqual(Y.b.offset, sizeof(c_int)) - self.assertEqual(Y._.offset, sizeof(c_int)) - self.assertEqual(Y.y.offset, sizeof(c_int) * 2) - -if __name__ == "__main__": - unittest.main() diff --git a/Lib/ctypes/test/test_array_in_pointer.py b/Lib/ctypes/test/test_array_in_pointer.py deleted file mode 100644 index ca1edcf..0000000 --- a/Lib/ctypes/test/test_array_in_pointer.py +++ /dev/null @@ -1,64 +0,0 @@ -import unittest -from ctypes import * -from binascii import hexlify -import re - -def dump(obj): - # helper function to dump memory contents in hex, with a hyphen - # between the bytes. - h = hexlify(memoryview(obj)).decode() - return re.sub(r"(..)", r"\1-", h)[:-1] - - -class Value(Structure): - _fields_ = [("val", c_byte)] - -class Container(Structure): - _fields_ = [("pvalues", POINTER(Value))] - -class Test(unittest.TestCase): - def test(self): - # create an array of 4 values - val_array = (Value * 4)() - - # create a container, which holds a pointer to the pvalues array. - c = Container() - c.pvalues = val_array - - # memory contains 4 NUL bytes now, that's correct - self.assertEqual("00-00-00-00", dump(val_array)) - - # set the values of the array through the pointer: - for i in range(4): - c.pvalues[i].val = i + 1 - - values = [c.pvalues[i].val for i in range(4)] - - # These are the expected results: here s the bug! - self.assertEqual( - (values, dump(val_array)), - ([1, 2, 3, 4], "01-02-03-04") - ) - - def test_2(self): - - val_array = (Value * 4)() - - # memory contains 4 NUL bytes now, that's correct - self.assertEqual("00-00-00-00", dump(val_array)) - - ptr = cast(val_array, POINTER(Value)) - # set the values of the array through the pointer: - for i in range(4): - ptr[i].val = i + 1 - - values = [ptr[i].val for i in range(4)] - - # These are the expected results: here s the bug! - self.assertEqual( - (values, dump(val_array)), - ([1, 2, 3, 4], "01-02-03-04") - ) - -if __name__ == "__main__": - unittest.main() diff --git a/Lib/ctypes/test/test_arrays.py b/Lib/ctypes/test/test_arrays.py deleted file mode 100644 index 14603b7..0000000 --- a/Lib/ctypes/test/test_arrays.py +++ /dev/null @@ -1,238 +0,0 @@ -import unittest -from test.support import bigmemtest, _2G -import sys -from ctypes import * - -from ctypes.test import need_symbol - -formats = "bBhHiIlLqQfd" - -formats = c_byte, c_ubyte, c_short, c_ushort, c_int, c_uint, \ - c_long, c_ulonglong, c_float, c_double, c_longdouble - -class ArrayTestCase(unittest.TestCase): - def test_simple(self): - # create classes holding simple numeric types, and check - # various properties. - - init = list(range(15, 25)) - - for fmt in formats: - alen = len(init) - int_array = ARRAY(fmt, alen) - - ia = int_array(*init) - # length of instance ok? - self.assertEqual(len(ia), alen) - - # slot values ok? - values = [ia[i] for i in range(alen)] - self.assertEqual(values, init) - - # out-of-bounds accesses should be caught - with self.assertRaises(IndexError): ia[alen] - with self.assertRaises(IndexError): ia[-alen-1] - - # change the items - from operator import setitem - new_values = list(range(42, 42+alen)) - [setitem(ia, n, new_values[n]) for n in range(alen)] - values = [ia[i] for i in range(alen)] - self.assertEqual(values, new_values) - - # are the items initialized to 0? - ia = int_array() - values = [ia[i] for i in range(alen)] - self.assertEqual(values, [0] * alen) - - # Too many initializers should be caught - self.assertRaises(IndexError, int_array, *range(alen*2)) - - CharArray = ARRAY(c_char, 3) - - ca = CharArray(b"a", b"b", b"c") - - # Should this work? It doesn't: - # CharArray("abc") - self.assertRaises(TypeError, CharArray, "abc") - - self.assertEqual(ca[0], b"a") - self.assertEqual(ca[1], b"b") - self.assertEqual(ca[2], b"c") - self.assertEqual(ca[-3], b"a") - self.assertEqual(ca[-2], b"b") - self.assertEqual(ca[-1], b"c") - - self.assertEqual(len(ca), 3) - - # cannot delete items - from operator import delitem - self.assertRaises(TypeError, delitem, ca, 0) - - def test_step_overflow(self): - a = (c_int * 5)() - a[3::sys.maxsize] = (1,) - self.assertListEqual(a[3::sys.maxsize], [1]) - a = (c_char * 5)() - a[3::sys.maxsize] = b"A" - self.assertEqual(a[3::sys.maxsize], b"A") - a = (c_wchar * 5)() - a[3::sys.maxsize] = u"X" - self.assertEqual(a[3::sys.maxsize], u"X") - - def test_numeric_arrays(self): - - alen = 5 - - numarray = ARRAY(c_int, alen) - - na = numarray() - values = [na[i] for i in range(alen)] - self.assertEqual(values, [0] * alen) - - na = numarray(*[c_int()] * alen) - values = [na[i] for i in range(alen)] - self.assertEqual(values, [0]*alen) - - na = numarray(1, 2, 3, 4, 5) - values = [i for i in na] - self.assertEqual(values, [1, 2, 3, 4, 5]) - - na = numarray(*map(c_int, (1, 2, 3, 4, 5))) - values = [i for i in na] - self.assertEqual(values, [1, 2, 3, 4, 5]) - - def test_classcache(self): - self.assertIsNot(ARRAY(c_int, 3), ARRAY(c_int, 4)) - self.assertIs(ARRAY(c_int, 3), ARRAY(c_int, 3)) - - def test_from_address(self): - # Failed with 0.9.8, reported by JUrner - p = create_string_buffer(b"foo") - sz = (c_char * 3).from_address(addressof(p)) - self.assertEqual(sz[:], b"foo") - self.assertEqual(sz[::], b"foo") - self.assertEqual(sz[::-1], b"oof") - self.assertEqual(sz[::3], b"f") - self.assertEqual(sz[1:4:2], b"o") - self.assertEqual(sz.value, b"foo") - - @need_symbol('create_unicode_buffer') - def test_from_addressW(self): - p = create_unicode_buffer("foo") - sz = (c_wchar * 3).from_address(addressof(p)) - self.assertEqual(sz[:], "foo") - self.assertEqual(sz[::], "foo") - self.assertEqual(sz[::-1], "oof") - self.assertEqual(sz[::3], "f") - self.assertEqual(sz[1:4:2], "o") - self.assertEqual(sz.value, "foo") - - def test_cache(self): - # Array types are cached internally in the _ctypes extension, - # in a WeakValueDictionary. Make sure the array type is - # removed from the cache when the itemtype goes away. This - # test will not fail, but will show a leak in the testsuite. - - # Create a new type: - class my_int(c_int): - pass - # Create a new array type based on it: - t1 = my_int * 1 - t2 = my_int * 1 - self.assertIs(t1, t2) - - def test_subclass(self): - class T(Array): - _type_ = c_int - _length_ = 13 - class U(T): - pass - class V(U): - pass - class W(V): - pass - class X(T): - _type_ = c_short - class Y(T): - _length_ = 187 - - for c in [T, U, V, W]: - self.assertEqual(c._type_, c_int) - self.assertEqual(c._length_, 13) - self.assertEqual(c()._type_, c_int) - self.assertEqual(c()._length_, 13) - - self.assertEqual(X._type_, c_short) - self.assertEqual(X._length_, 13) - self.assertEqual(X()._type_, c_short) - self.assertEqual(X()._length_, 13) - - self.assertEqual(Y._type_, c_int) - self.assertEqual(Y._length_, 187) - self.assertEqual(Y()._type_, c_int) - self.assertEqual(Y()._length_, 187) - - def test_bad_subclass(self): - with self.assertRaises(AttributeError): - class T(Array): - pass - with self.assertRaises(AttributeError): - class T(Array): - _type_ = c_int - with self.assertRaises(AttributeError): - class T(Array): - _length_ = 13 - - def test_bad_length(self): - with self.assertRaises(ValueError): - class T(Array): - _type_ = c_int - _length_ = - sys.maxsize * 2 - with self.assertRaises(ValueError): - class T(Array): - _type_ = c_int - _length_ = -1 - with self.assertRaises(TypeError): - class T(Array): - _type_ = c_int - _length_ = 1.87 - with self.assertRaises(OverflowError): - class T(Array): - _type_ = c_int - _length_ = sys.maxsize * 2 - - def test_zero_length(self): - # _length_ can be zero. - class T(Array): - _type_ = c_int - _length_ = 0 - - def test_empty_element_struct(self): - class EmptyStruct(Structure): - _fields_ = [] - - obj = (EmptyStruct * 2)() # bpo37188: Floating point exception - self.assertEqual(sizeof(obj), 0) - - def test_empty_element_array(self): - class EmptyArray(Array): - _type_ = c_int - _length_ = 0 - - obj = (EmptyArray * 2)() # bpo37188: Floating point exception - self.assertEqual(sizeof(obj), 0) - - def test_bpo36504_signed_int_overflow(self): - # The overflow check in PyCArrayType_new() could cause signed integer - # overflow. - with self.assertRaises(OverflowError): - c_char * sys.maxsize * 2 - - @unittest.skipUnless(sys.maxsize > 2**32, 'requires 64bit platform') - @bigmemtest(size=_2G, memuse=1, dry_run=False) - def test_large_array(self, size): - c_char * size - -if __name__ == '__main__': - unittest.main() diff --git a/Lib/ctypes/test/test_as_parameter.py b/Lib/ctypes/test/test_as_parameter.py deleted file mode 100644 index f9d27cb..0000000 --- a/Lib/ctypes/test/test_as_parameter.py +++ /dev/null @@ -1,230 +0,0 @@ -import unittest -from ctypes import * -from ctypes.test import need_symbol -import _ctypes_test - -dll = CDLL(_ctypes_test.__file__) - -try: - CALLBACK_FUNCTYPE = WINFUNCTYPE -except NameError: - # fake to enable this test on Linux - CALLBACK_FUNCTYPE = CFUNCTYPE - -class POINT(Structure): - _fields_ = [("x", c_int), ("y", c_int)] - -class BasicWrapTestCase(unittest.TestCase): - def wrap(self, param): - return param - - @need_symbol('c_wchar') - def test_wchar_parm(self): - f = dll._testfunc_i_bhilfd - f.argtypes = [c_byte, c_wchar, c_int, c_long, c_float, c_double] - result = f(self.wrap(1), self.wrap("x"), self.wrap(3), self.wrap(4), self.wrap(5.0), self.wrap(6.0)) - self.assertEqual(result, 139) - self.assertIs(type(result), int) - - def test_pointers(self): - f = dll._testfunc_p_p - f.restype = POINTER(c_int) - f.argtypes = [POINTER(c_int)] - - # This only works if the value c_int(42) passed to the - # function is still alive while the pointer (the result) is - # used. - - v = c_int(42) - - self.assertEqual(pointer(v).contents.value, 42) - result = f(self.wrap(pointer(v))) - self.assertEqual(type(result), POINTER(c_int)) - self.assertEqual(result.contents.value, 42) - - # This on works... - result = f(self.wrap(pointer(v))) - self.assertEqual(result.contents.value, v.value) - - p = pointer(c_int(99)) - result = f(self.wrap(p)) - self.assertEqual(result.contents.value, 99) - - def test_shorts(self): - f = dll._testfunc_callback_i_if - - args = [] - expected = [262144, 131072, 65536, 32768, 16384, 8192, 4096, 2048, - 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1] - - def callback(v): - args.append(v) - return v - - CallBack = CFUNCTYPE(c_int, c_int) - - cb = CallBack(callback) - f(self.wrap(2**18), self.wrap(cb)) - self.assertEqual(args, expected) - - ################################################################ - - def test_callbacks(self): - f = dll._testfunc_callback_i_if - f.restype = c_int - f.argtypes = None - - MyCallback = CFUNCTYPE(c_int, c_int) - - def callback(value): - #print "called back with", value - return value - - cb = MyCallback(callback) - - result = f(self.wrap(-10), self.wrap(cb)) - self.assertEqual(result, -18) - - # test with prototype - f.argtypes = [c_int, MyCallback] - cb = MyCallback(callback) - - result = f(self.wrap(-10), self.wrap(cb)) - self.assertEqual(result, -18) - - result = f(self.wrap(-10), self.wrap(cb)) - self.assertEqual(result, -18) - - AnotherCallback = CALLBACK_FUNCTYPE(c_int, c_int, c_int, c_int, c_int) - - # check that the prototype works: we call f with wrong - # argument types - cb = AnotherCallback(callback) - self.assertRaises(ArgumentError, f, self.wrap(-10), self.wrap(cb)) - - def test_callbacks_2(self): - # Can also use simple datatypes as argument type specifiers - # for the callback function. - # In this case the call receives an instance of that type - f = dll._testfunc_callback_i_if - f.restype = c_int - - MyCallback = CFUNCTYPE(c_int, c_int) - - f.argtypes = [c_int, MyCallback] - - def callback(value): - #print "called back with", value - self.assertEqual(type(value), int) - return value - - cb = MyCallback(callback) - result = f(self.wrap(-10), self.wrap(cb)) - self.assertEqual(result, -18) - - def test_longlong_callbacks(self): - - f = dll._testfunc_callback_q_qf - f.restype = c_longlong - - MyCallback = CFUNCTYPE(c_longlong, c_longlong) - - f.argtypes = [c_longlong, MyCallback] - - def callback(value): - self.assertIsInstance(value, int) - return value & 0x7FFFFFFF - - cb = MyCallback(callback) - - self.assertEqual(13577625587, int(f(self.wrap(1000000000000), self.wrap(cb)))) - - def test_byval(self): - # without prototype - ptin = POINT(1, 2) - ptout = POINT() - # EXPORT int _testfunc_byval(point in, point *pout) - result = dll._testfunc_byval(ptin, byref(ptout)) - got = result, ptout.x, ptout.y - expected = 3, 1, 2 - self.assertEqual(got, expected) - - # with prototype - ptin = POINT(101, 102) - ptout = POINT() - dll._testfunc_byval.argtypes = (POINT, POINTER(POINT)) - dll._testfunc_byval.restype = c_int - result = dll._testfunc_byval(self.wrap(ptin), byref(ptout)) - got = result, ptout.x, ptout.y - expected = 203, 101, 102 - self.assertEqual(got, expected) - - def test_struct_return_2H(self): - class S2H(Structure): - _fields_ = [("x", c_short), - ("y", c_short)] - dll.ret_2h_func.restype = S2H - dll.ret_2h_func.argtypes = [S2H] - inp = S2H(99, 88) - s2h = dll.ret_2h_func(self.wrap(inp)) - self.assertEqual((s2h.x, s2h.y), (99*2, 88*3)) - - # Test also that the original struct was unmodified (i.e. was passed by - # value) - self.assertEqual((inp.x, inp.y), (99, 88)) - - def test_struct_return_8H(self): - class S8I(Structure): - _fields_ = [("a", c_int), - ("b", c_int), - ("c", c_int), - ("d", c_int), - ("e", c_int), - ("f", c_int), - ("g", c_int), - ("h", c_int)] - dll.ret_8i_func.restype = S8I - dll.ret_8i_func.argtypes = [S8I] - inp = S8I(9, 8, 7, 6, 5, 4, 3, 2) - s8i = dll.ret_8i_func(self.wrap(inp)) - self.assertEqual((s8i.a, s8i.b, s8i.c, s8i.d, s8i.e, s8i.f, s8i.g, s8i.h), - (9*2, 8*3, 7*4, 6*5, 5*6, 4*7, 3*8, 2*9)) - - def test_recursive_as_param(self): - from ctypes import c_int - - class A(object): - pass - - a = A() - a._as_parameter_ = a - with self.assertRaises(RecursionError): - c_int.from_param(a) - - -#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -class AsParamWrapper(object): - def __init__(self, param): - self._as_parameter_ = param - -class AsParamWrapperTestCase(BasicWrapTestCase): - wrap = AsParamWrapper - -#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -class AsParamPropertyWrapper(object): - def __init__(self, param): - self._param = param - - def getParameter(self): - return self._param - _as_parameter_ = property(getParameter) - -class AsParamPropertyWrapperTestCase(BasicWrapTestCase): - wrap = AsParamPropertyWrapper - -#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -if __name__ == '__main__': - unittest.main() diff --git a/Lib/ctypes/test/test_bitfields.py b/Lib/ctypes/test/test_bitfields.py deleted file mode 100644 index 66acd62..0000000 --- a/Lib/ctypes/test/test_bitfields.py +++ /dev/null @@ -1,297 +0,0 @@ -from ctypes import * -from ctypes.test import need_symbol -from test import support -import unittest -import os - -import _ctypes_test - -class BITS(Structure): - _fields_ = [("A", c_int, 1), - ("B", c_int, 2), - ("C", c_int, 3), - ("D", c_int, 4), - ("E", c_int, 5), - ("F", c_int, 6), - ("G", c_int, 7), - ("H", c_int, 8), - ("I", c_int, 9), - - ("M", c_short, 1), - ("N", c_short, 2), - ("O", c_short, 3), - ("P", c_short, 4), - ("Q", c_short, 5), - ("R", c_short, 6), - ("S", c_short, 7)] - -func = CDLL(_ctypes_test.__file__).unpack_bitfields -func.argtypes = POINTER(BITS), c_char - -##for n in "ABCDEFGHIMNOPQRS": -## print n, hex(getattr(BITS, n).size), getattr(BITS, n).offset - -class C_Test(unittest.TestCase): - - def test_ints(self): - for i in range(512): - for name in "ABCDEFGHI": - b = BITS() - setattr(b, name, i) - self.assertEqual(getattr(b, name), func(byref(b), name.encode('ascii'))) - - # bpo-46913: _ctypes/cfield.c h_get() has an undefined behavior - @support.skip_if_sanitizer(ub=True) - def test_shorts(self): - b = BITS() - name = "M" - if func(byref(b), name.encode('ascii')) == 999: - self.skipTest("Compiler does not support signed short bitfields") - for i in range(256): - for name in "MNOPQRS": - b = BITS() - setattr(b, name, i) - self.assertEqual(getattr(b, name), func(byref(b), name.encode('ascii'))) - -signed_int_types = (c_byte, c_short, c_int, c_long, c_longlong) -unsigned_int_types = (c_ubyte, c_ushort, c_uint, c_ulong, c_ulonglong) -int_types = unsigned_int_types + signed_int_types - -class BitFieldTest(unittest.TestCase): - - def test_longlong(self): - class X(Structure): - _fields_ = [("a", c_longlong, 1), - ("b", c_longlong, 62), - ("c", c_longlong, 1)] - - self.assertEqual(sizeof(X), sizeof(c_longlong)) - x = X() - x.a, x.b, x.c = -1, 7, -1 - self.assertEqual((x.a, x.b, x.c), (-1, 7, -1)) - - def test_ulonglong(self): - class X(Structure): - _fields_ = [("a", c_ulonglong, 1), - ("b", c_ulonglong, 62), - ("c", c_ulonglong, 1)] - - self.assertEqual(sizeof(X), sizeof(c_longlong)) - x = X() - self.assertEqual((x.a, x.b, x.c), (0, 0, 0)) - x.a, x.b, x.c = 7, 7, 7 - self.assertEqual((x.a, x.b, x.c), (1, 7, 1)) - - def test_signed(self): - for c_typ in signed_int_types: - class X(Structure): - _fields_ = [("dummy", c_typ), - ("a", c_typ, 3), - ("b", c_typ, 3), - ("c", c_typ, 1)] - self.assertEqual(sizeof(X), sizeof(c_typ)*2) - - x = X() - self.assertEqual((c_typ, x.a, x.b, x.c), (c_typ, 0, 0, 0)) - x.a = -1 - self.assertEqual((c_typ, x.a, x.b, x.c), (c_typ, -1, 0, 0)) - x.a, x.b = 0, -1 - self.assertEqual((c_typ, x.a, x.b, x.c), (c_typ, 0, -1, 0)) - - - def test_unsigned(self): - for c_typ in unsigned_int_types: - class X(Structure): - _fields_ = [("a", c_typ, 3), - ("b", c_typ, 3), - ("c", c_typ, 1)] - self.assertEqual(sizeof(X), sizeof(c_typ)) - - x = X() - self.assertEqual((c_typ, x.a, x.b, x.c), (c_typ, 0, 0, 0)) - x.a = -1 - self.assertEqual((c_typ, x.a, x.b, x.c), (c_typ, 7, 0, 0)) - x.a, x.b = 0, -1 - self.assertEqual((c_typ, x.a, x.b, x.c), (c_typ, 0, 7, 0)) - - - def fail_fields(self, *fields): - return self.get_except(type(Structure), "X", (), - {"_fields_": fields}) - - def test_nonint_types(self): - # bit fields are not allowed on non-integer types. - result = self.fail_fields(("a", c_char_p, 1)) - self.assertEqual(result, (TypeError, 'bit fields not allowed for type c_char_p')) - - result = self.fail_fields(("a", c_void_p, 1)) - self.assertEqual(result, (TypeError, 'bit fields not allowed for type c_void_p')) - - if c_int != c_long: - result = self.fail_fields(("a", POINTER(c_int), 1)) - self.assertEqual(result, (TypeError, 'bit fields not allowed for type LP_c_int')) - - result = self.fail_fields(("a", c_char, 1)) - self.assertEqual(result, (TypeError, 'bit fields not allowed for type c_char')) - - class Dummy(Structure): - _fields_ = [] - - result = self.fail_fields(("a", Dummy, 1)) - self.assertEqual(result, (TypeError, 'bit fields not allowed for type Dummy')) - - @need_symbol('c_wchar') - def test_c_wchar(self): - result = self.fail_fields(("a", c_wchar, 1)) - self.assertEqual(result, - (TypeError, 'bit fields not allowed for type c_wchar')) - - def test_single_bitfield_size(self): - for c_typ in int_types: - result = self.fail_fields(("a", c_typ, -1)) - self.assertEqual(result, (ValueError, 'number of bits invalid for bit field')) - - result = self.fail_fields(("a", c_typ, 0)) - self.assertEqual(result, (ValueError, 'number of bits invalid for bit field')) - - class X(Structure): - _fields_ = [("a", c_typ, 1)] - self.assertEqual(sizeof(X), sizeof(c_typ)) - - class X(Structure): - _fields_ = [("a", c_typ, sizeof(c_typ)*8)] - self.assertEqual(sizeof(X), sizeof(c_typ)) - - result = self.fail_fields(("a", c_typ, sizeof(c_typ)*8 + 1)) - self.assertEqual(result, (ValueError, 'number of bits invalid for bit field')) - - def test_multi_bitfields_size(self): - class X(Structure): - _fields_ = [("a", c_short, 1), - ("b", c_short, 14), - ("c", c_short, 1)] - self.assertEqual(sizeof(X), sizeof(c_short)) - - class X(Structure): - _fields_ = [("a", c_short, 1), - ("a1", c_short), - ("b", c_short, 14), - ("c", c_short, 1)] - self.assertEqual(sizeof(X), sizeof(c_short)*3) - self.assertEqual(X.a.offset, 0) - self.assertEqual(X.a1.offset, sizeof(c_short)) - self.assertEqual(X.b.offset, sizeof(c_short)*2) - self.assertEqual(X.c.offset, sizeof(c_short)*2) - - class X(Structure): - _fields_ = [("a", c_short, 3), - ("b", c_short, 14), - ("c", c_short, 14)] - self.assertEqual(sizeof(X), sizeof(c_short)*3) - self.assertEqual(X.a.offset, sizeof(c_short)*0) - self.assertEqual(X.b.offset, sizeof(c_short)*1) - self.assertEqual(X.c.offset, sizeof(c_short)*2) - - - def get_except(self, func, *args, **kw): - try: - func(*args, **kw) - except Exception as detail: - return detail.__class__, str(detail) - - def test_mixed_1(self): - class X(Structure): - _fields_ = [("a", c_byte, 4), - ("b", c_int, 4)] - if os.name == "nt": - self.assertEqual(sizeof(X), sizeof(c_int)*2) - else: - self.assertEqual(sizeof(X), sizeof(c_int)) - - def test_mixed_2(self): - class X(Structure): - _fields_ = [("a", c_byte, 4), - ("b", c_int, 32)] - self.assertEqual(sizeof(X), alignment(c_int)+sizeof(c_int)) - - def test_mixed_3(self): - class X(Structure): - _fields_ = [("a", c_byte, 4), - ("b", c_ubyte, 4)] - self.assertEqual(sizeof(X), sizeof(c_byte)) - - def test_mixed_4(self): - class X(Structure): - _fields_ = [("a", c_short, 4), - ("b", c_short, 4), - ("c", c_int, 24), - ("d", c_short, 4), - ("e", c_short, 4), - ("f", c_int, 24)] - # MSVC does NOT combine c_short and c_int into one field, GCC - # does (unless GCC is run with '-mms-bitfields' which - # produces code compatible with MSVC). - if os.name == "nt": - self.assertEqual(sizeof(X), sizeof(c_int) * 4) - else: - self.assertEqual(sizeof(X), sizeof(c_int) * 2) - - def test_anon_bitfields(self): - # anonymous bit-fields gave a strange error message - class X(Structure): - _fields_ = [("a", c_byte, 4), - ("b", c_ubyte, 4)] - class Y(Structure): - _anonymous_ = ["_"] - _fields_ = [("_", X)] - - @need_symbol('c_uint32') - def test_uint32(self): - class X(Structure): - _fields_ = [("a", c_uint32, 32)] - x = X() - x.a = 10 - self.assertEqual(x.a, 10) - x.a = 0xFDCBA987 - self.assertEqual(x.a, 0xFDCBA987) - - @need_symbol('c_uint64') - def test_uint64(self): - class X(Structure): - _fields_ = [("a", c_uint64, 64)] - x = X() - x.a = 10 - self.assertEqual(x.a, 10) - x.a = 0xFEDCBA9876543211 - self.assertEqual(x.a, 0xFEDCBA9876543211) - - @need_symbol('c_uint32') - def test_uint32_swap_little_endian(self): - # Issue #23319 - class Little(LittleEndianStructure): - _fields_ = [("a", c_uint32, 24), - ("b", c_uint32, 4), - ("c", c_uint32, 4)] - b = bytearray(4) - x = Little.from_buffer(b) - x.a = 0xabcdef - x.b = 1 - x.c = 2 - self.assertEqual(b, b'\xef\xcd\xab\x21') - - @need_symbol('c_uint32') - def test_uint32_swap_big_endian(self): - # Issue #23319 - class Big(BigEndianStructure): - _fields_ = [("a", c_uint32, 24), - ("b", c_uint32, 4), - ("c", c_uint32, 4)] - b = bytearray(4) - x = Big.from_buffer(b) - x.a = 0xabcdef - x.b = 1 - x.c = 2 - self.assertEqual(b, b'\xab\xcd\xef\x12') - -if __name__ == "__main__": - unittest.main() diff --git a/Lib/ctypes/test/test_buffers.py b/Lib/ctypes/test/test_buffers.py deleted file mode 100644 index 15782be..0000000 --- a/Lib/ctypes/test/test_buffers.py +++ /dev/null @@ -1,73 +0,0 @@ -from ctypes import * -from ctypes.test import need_symbol -import unittest - -class StringBufferTestCase(unittest.TestCase): - - def test_buffer(self): - b = create_string_buffer(32) - self.assertEqual(len(b), 32) - self.assertEqual(sizeof(b), 32 * sizeof(c_char)) - self.assertIs(type(b[0]), bytes) - - b = create_string_buffer(b"abc") - self.assertEqual(len(b), 4) # trailing nul char - self.assertEqual(sizeof(b), 4 * sizeof(c_char)) - self.assertIs(type(b[0]), bytes) - self.assertEqual(b[0], b"a") - self.assertEqual(b[:], b"abc\0") - self.assertEqual(b[::], b"abc\0") - self.assertEqual(b[::-1], b"\0cba") - self.assertEqual(b[::2], b"ac") - self.assertEqual(b[::5], b"a") - - self.assertRaises(TypeError, create_string_buffer, "abc") - - def test_buffer_interface(self): - self.assertEqual(len(bytearray(create_string_buffer(0))), 0) - self.assertEqual(len(bytearray(create_string_buffer(1))), 1) - - @need_symbol('c_wchar') - def test_unicode_buffer(self): - b = create_unicode_buffer(32) - self.assertEqual(len(b), 32) - self.assertEqual(sizeof(b), 32 * sizeof(c_wchar)) - self.assertIs(type(b[0]), str) - - b = create_unicode_buffer("abc") - self.assertEqual(len(b), 4) # trailing nul char - self.assertEqual(sizeof(b), 4 * sizeof(c_wchar)) - self.assertIs(type(b[0]), str) - self.assertEqual(b[0], "a") - self.assertEqual(b[:], "abc\0") - self.assertEqual(b[::], "abc\0") - self.assertEqual(b[::-1], "\0cba") - self.assertEqual(b[::2], "ac") - self.assertEqual(b[::5], "a") - - self.assertRaises(TypeError, create_unicode_buffer, b"abc") - - @need_symbol('c_wchar') - def test_unicode_conversion(self): - b = create_unicode_buffer("abc") - self.assertEqual(len(b), 4) # trailing nul char - self.assertEqual(sizeof(b), 4 * sizeof(c_wchar)) - self.assertIs(type(b[0]), str) - self.assertEqual(b[0], "a") - self.assertEqual(b[:], "abc\0") - self.assertEqual(b[::], "abc\0") - self.assertEqual(b[::-1], "\0cba") - self.assertEqual(b[::2], "ac") - self.assertEqual(b[::5], "a") - - @need_symbol('c_wchar') - def test_create_unicode_buffer_non_bmp(self): - expected = 5 if sizeof(c_wchar) == 2 else 3 - for s in '\U00010000\U00100000', '\U00010000\U0010ffff': - b = create_unicode_buffer(s) - self.assertEqual(len(b), expected) - self.assertEqual(b[-1], '\0') - - -if __name__ == "__main__": - unittest.main() diff --git a/Lib/ctypes/test/test_bytes.py b/Lib/ctypes/test/test_bytes.py deleted file mode 100644 index 092ec5a..0000000 --- a/Lib/ctypes/test/test_bytes.py +++ /dev/null @@ -1,66 +0,0 @@ -"""Test where byte objects are accepted""" -import unittest -import sys -from ctypes import * - -class BytesTest(unittest.TestCase): - def test_c_char(self): - x = c_char(b"x") - self.assertRaises(TypeError, c_char, "x") - x.value = b"y" - with self.assertRaises(TypeError): - x.value = "y" - c_char.from_param(b"x") - self.assertRaises(TypeError, c_char.from_param, "x") - self.assertIn('xbd', repr(c_char.from_param(b"\xbd"))) - (c_char * 3)(b"a", b"b", b"c") - self.assertRaises(TypeError, c_char * 3, "a", "b", "c") - - def test_c_wchar(self): - x = c_wchar("x") - self.assertRaises(TypeError, c_wchar, b"x") - x.value = "y" - with self.assertRaises(TypeError): - x.value = b"y" - c_wchar.from_param("x") - self.assertRaises(TypeError, c_wchar.from_param, b"x") - (c_wchar * 3)("a", "b", "c") - self.assertRaises(TypeError, c_wchar * 3, b"a", b"b", b"c") - - def test_c_char_p(self): - c_char_p(b"foo bar") - self.assertRaises(TypeError, c_char_p, "foo bar") - - def test_c_wchar_p(self): - c_wchar_p("foo bar") - self.assertRaises(TypeError, c_wchar_p, b"foo bar") - - def test_struct(self): - class X(Structure): - _fields_ = [("a", c_char * 3)] - - x = X(b"abc") - self.assertRaises(TypeError, X, "abc") - self.assertEqual(x.a, b"abc") - self.assertEqual(type(x.a), bytes) - - def test_struct_W(self): - class X(Structure): - _fields_ = [("a", c_wchar * 3)] - - x = X("abc") - self.assertRaises(TypeError, X, b"abc") - self.assertEqual(x.a, "abc") - self.assertEqual(type(x.a), str) - - @unittest.skipUnless(sys.platform == "win32", 'Windows-specific test') - def test_BSTR(self): - from _ctypes import _SimpleCData - class BSTR(_SimpleCData): - _type_ = "X" - - BSTR("abc") - - -if __name__ == '__main__': - unittest.main() diff --git a/Lib/ctypes/test/test_byteswap.py b/Lib/ctypes/test/test_byteswap.py deleted file mode 100644 index 7e98559..0000000 --- a/Lib/ctypes/test/test_byteswap.py +++ /dev/null @@ -1,364 +0,0 @@ -import sys, unittest, struct, math, ctypes -from binascii import hexlify - -from ctypes import * - -def bin(s): - return hexlify(memoryview(s)).decode().upper() - -# Each *simple* type that supports different byte orders has an -# __ctype_be__ attribute that specifies the same type in BIG ENDIAN -# byte order, and a __ctype_le__ attribute that is the same type in -# LITTLE ENDIAN byte order. -# -# For Structures and Unions, these types are created on demand. - -class Test(unittest.TestCase): - @unittest.skip('test disabled') - def test_X(self): - print(sys.byteorder, file=sys.stderr) - for i in range(32): - bits = BITS() - setattr(bits, "i%s" % i, 1) - dump(bits) - - def test_slots(self): - class BigPoint(BigEndianStructure): - __slots__ = () - _fields_ = [("x", c_int), ("y", c_int)] - - class LowPoint(LittleEndianStructure): - __slots__ = () - _fields_ = [("x", c_int), ("y", c_int)] - - big = BigPoint() - little = LowPoint() - big.x = 4 - big.y = 2 - little.x = 2 - little.y = 4 - with self.assertRaises(AttributeError): - big.z = 42 - with self.assertRaises(AttributeError): - little.z = 24 - - def test_endian_short(self): - if sys.byteorder == "little": - self.assertIs(c_short.__ctype_le__, c_short) - self.assertIs(c_short.__ctype_be__.__ctype_le__, c_short) - else: - self.assertIs(c_short.__ctype_be__, c_short) - self.assertIs(c_short.__ctype_le__.__ctype_be__, c_short) - s = c_short.__ctype_be__(0x1234) - self.assertEqual(bin(struct.pack(">h", 0x1234)), "1234") - self.assertEqual(bin(s), "1234") - self.assertEqual(s.value, 0x1234) - - s = c_short.__ctype_le__(0x1234) - self.assertEqual(bin(struct.pack("h", 0x1234)), "1234") - self.assertEqual(bin(s), "1234") - self.assertEqual(s.value, 0x1234) - - s = c_ushort.__ctype_le__(0x1234) - self.assertEqual(bin(struct.pack("i", 0x12345678)), "12345678") - self.assertEqual(bin(s), "12345678") - self.assertEqual(s.value, 0x12345678) - - s = c_int.__ctype_le__(0x12345678) - self.assertEqual(bin(struct.pack("I", 0x12345678)), "12345678") - self.assertEqual(bin(s), "12345678") - self.assertEqual(s.value, 0x12345678) - - s = c_uint.__ctype_le__(0x12345678) - self.assertEqual(bin(struct.pack("q", 0x1234567890ABCDEF)), "1234567890ABCDEF") - self.assertEqual(bin(s), "1234567890ABCDEF") - self.assertEqual(s.value, 0x1234567890ABCDEF) - - s = c_longlong.__ctype_le__(0x1234567890ABCDEF) - self.assertEqual(bin(struct.pack("Q", 0x1234567890ABCDEF)), "1234567890ABCDEF") - self.assertEqual(bin(s), "1234567890ABCDEF") - self.assertEqual(s.value, 0x1234567890ABCDEF) - - s = c_ulonglong.__ctype_le__(0x1234567890ABCDEF) - self.assertEqual(bin(struct.pack("f", math.pi)), bin(s)) - - def test_endian_double(self): - if sys.byteorder == "little": - self.assertIs(c_double.__ctype_le__, c_double) - self.assertIs(c_double.__ctype_be__.__ctype_le__, c_double) - else: - self.assertIs(c_double.__ctype_be__, c_double) - self.assertIs(c_double.__ctype_le__.__ctype_be__, c_double) - s = c_double(math.pi) - self.assertEqual(s.value, math.pi) - self.assertEqual(bin(struct.pack("d", math.pi)), bin(s)) - s = c_double.__ctype_le__(math.pi) - self.assertEqual(s.value, math.pi) - self.assertEqual(bin(struct.pack("d", math.pi)), bin(s)) - - def test_endian_other(self): - self.assertIs(c_byte.__ctype_le__, c_byte) - self.assertIs(c_byte.__ctype_be__, c_byte) - - self.assertIs(c_ubyte.__ctype_le__, c_ubyte) - self.assertIs(c_ubyte.__ctype_be__, c_ubyte) - - self.assertIs(c_char.__ctype_le__, c_char) - self.assertIs(c_char.__ctype_be__, c_char) - - def test_struct_fields_unsupported_byte_order(self): - - fields = [ - ("a", c_ubyte), - ("b", c_byte), - ("c", c_short), - ("d", c_ushort), - ("e", c_int), - ("f", c_uint), - ("g", c_long), - ("h", c_ulong), - ("i", c_longlong), - ("k", c_ulonglong), - ("l", c_float), - ("m", c_double), - ("n", c_char), - ("b1", c_byte, 3), - ("b2", c_byte, 3), - ("b3", c_byte, 2), - ("a", c_int * 3 * 3 * 3) - ] - - # these fields do not support different byte order: - for typ in c_wchar, c_void_p, POINTER(c_int): - with self.assertRaises(TypeError): - class T(BigEndianStructure if sys.byteorder == "little" else LittleEndianStructure): - _fields_ = fields + [("x", typ)] - - - def test_struct_struct(self): - # nested structures with different byteorders - - # create nested structures with given byteorders and set memory to data - - for nested, data in ( - (BigEndianStructure, b'\0\0\0\1\0\0\0\2'), - (LittleEndianStructure, b'\1\0\0\0\2\0\0\0'), - ): - for parent in ( - BigEndianStructure, - LittleEndianStructure, - Structure, - ): - class NestedStructure(nested): - _fields_ = [("x", c_uint32), - ("y", c_uint32)] - - class TestStructure(parent): - _fields_ = [("point", NestedStructure)] - - self.assertEqual(len(data), sizeof(TestStructure)) - ptr = POINTER(TestStructure) - s = cast(data, ptr)[0] - del ctypes._pointer_type_cache[TestStructure] - self.assertEqual(s.point.x, 1) - self.assertEqual(s.point.y, 2) - - def test_struct_field_alignment(self): - # standard packing in struct uses no alignment. - # So, we have to align using pad bytes. - # - # Unaligned accesses will crash Python (on those platforms that - # don't allow it, like sparc solaris). - if sys.byteorder == "little": - base = BigEndianStructure - fmt = ">bxhid" - else: - base = LittleEndianStructure - fmt = " float -> double - import math - self.check_type(c_float, math.e) - self.check_type(c_float, -math.e) - - def test_double(self): - self.check_type(c_double, 3.14) - self.check_type(c_double, -3.14) - - def test_longdouble(self): - self.check_type(c_longdouble, 3.14) - self.check_type(c_longdouble, -3.14) - - def test_char(self): - self.check_type(c_char, b"x") - self.check_type(c_char, b"a") - - # disabled: would now (correctly) raise a RuntimeWarning about - # a memory leak. A callback function cannot return a non-integral - # C type without causing a memory leak. - @unittest.skip('test disabled') - def test_char_p(self): - self.check_type(c_char_p, "abc") - self.check_type(c_char_p, "def") - - def test_pyobject(self): - o = () - from sys import getrefcount as grc - for o in (), [], object(): - initial = grc(o) - # This call leaks a reference to 'o'... - self.check_type(py_object, o) - before = grc(o) - # ...but this call doesn't leak any more. Where is the refcount? - self.check_type(py_object, o) - after = grc(o) - self.assertEqual((after, o), (before, o)) - - def test_unsupported_restype_1(self): - # Only "fundamental" result types are supported for callback - # functions, the type must have a non-NULL stgdict->setfunc. - # POINTER(c_double), for example, is not supported. - - prototype = self.functype.__func__(POINTER(c_double)) - # The type is checked when the prototype is called - self.assertRaises(TypeError, prototype, lambda: None) - - def test_unsupported_restype_2(self): - prototype = self.functype.__func__(object) - self.assertRaises(TypeError, prototype, lambda: None) - - def test_issue_7959(self): - proto = self.functype.__func__(None) - - class X(object): - def func(self): pass - def __init__(self): - self.v = proto(self.func) - - import gc - for i in range(32): - X() - gc.collect() - live = [x for x in gc.get_objects() - if isinstance(x, X)] - self.assertEqual(len(live), 0) - - def test_issue12483(self): - import gc - class Nasty: - def __del__(self): - gc.collect() - CFUNCTYPE(None)(lambda x=Nasty(): None) - - -@need_symbol('WINFUNCTYPE') -class StdcallCallbacks(Callbacks): - try: - functype = WINFUNCTYPE - except NameError: - pass - -################################################################ - -class SampleCallbacksTestCase(unittest.TestCase): - - def test_integrate(self): - # Derived from some then non-working code, posted by David Foster - dll = CDLL(_ctypes_test.__file__) - - # The function prototype called by 'integrate': double func(double); - CALLBACK = CFUNCTYPE(c_double, c_double) - - # The integrate function itself, exposed from the _ctypes_test dll - integrate = dll.integrate - integrate.argtypes = (c_double, c_double, CALLBACK, c_long) - integrate.restype = c_double - - def func(x): - return x**2 - - result = integrate(0.0, 1.0, CALLBACK(func), 10) - diff = abs(result - 1./3.) - - self.assertLess(diff, 0.01, "%s not less than 0.01" % diff) - - def test_issue_8959_a(self): - from ctypes.util import find_library - libc_path = find_library("c") - if not libc_path: - self.skipTest('could not find libc') - libc = CDLL(libc_path) - - @CFUNCTYPE(c_int, POINTER(c_int), POINTER(c_int)) - def cmp_func(a, b): - return a[0] - b[0] - - array = (c_int * 5)(5, 1, 99, 7, 33) - - libc.qsort(array, len(array), sizeof(c_int), cmp_func) - self.assertEqual(array[:], [1, 5, 7, 33, 99]) - - @need_symbol('WINFUNCTYPE') - def test_issue_8959_b(self): - from ctypes.wintypes import BOOL, HWND, LPARAM - global windowCount - windowCount = 0 - - @WINFUNCTYPE(BOOL, HWND, LPARAM) - def EnumWindowsCallbackFunc(hwnd, lParam): - global windowCount - windowCount += 1 - return True #Allow windows to keep enumerating - - windll.user32.EnumWindows(EnumWindowsCallbackFunc, 0) - - def test_callback_register_int(self): - # Issue #8275: buggy handling of callback args under Win64 - # NOTE: should be run on release builds as well - dll = CDLL(_ctypes_test.__file__) - CALLBACK = CFUNCTYPE(c_int, c_int, c_int, c_int, c_int, c_int) - # All this function does is call the callback with its args squared - func = dll._testfunc_cbk_reg_int - func.argtypes = (c_int, c_int, c_int, c_int, c_int, CALLBACK) - func.restype = c_int - - def callback(a, b, c, d, e): - return a + b + c + d + e - - result = func(2, 3, 4, 5, 6, CALLBACK(callback)) - self.assertEqual(result, callback(2*2, 3*3, 4*4, 5*5, 6*6)) - - def test_callback_register_double(self): - # Issue #8275: buggy handling of callback args under Win64 - # NOTE: should be run on release builds as well - dll = CDLL(_ctypes_test.__file__) - CALLBACK = CFUNCTYPE(c_double, c_double, c_double, c_double, - c_double, c_double) - # All this function does is call the callback with its args squared - func = dll._testfunc_cbk_reg_double - func.argtypes = (c_double, c_double, c_double, - c_double, c_double, CALLBACK) - func.restype = c_double - - def callback(a, b, c, d, e): - return a + b + c + d + e - - result = func(1.1, 2.2, 3.3, 4.4, 5.5, CALLBACK(callback)) - self.assertEqual(result, - callback(1.1*1.1, 2.2*2.2, 3.3*3.3, 4.4*4.4, 5.5*5.5)) - - def test_callback_large_struct(self): - class Check: pass - - # This should mirror the structure in Modules/_ctypes/_ctypes_test.c - class X(Structure): - _fields_ = [ - ('first', c_ulong), - ('second', c_ulong), - ('third', c_ulong), - ] - - def callback(check, s): - check.first = s.first - check.second = s.second - check.third = s.third - # See issue #29565. - # The structure should be passed by value, so - # any changes to it should not be reflected in - # the value passed - s.first = s.second = s.third = 0x0badf00d - - check = Check() - s = X() - s.first = 0xdeadbeef - s.second = 0xcafebabe - s.third = 0x0bad1dea - - CALLBACK = CFUNCTYPE(None, X) - dll = CDLL(_ctypes_test.__file__) - func = dll._testfunc_cbk_large_struct - func.argtypes = (X, CALLBACK) - func.restype = None - # the function just calls the callback with the passed structure - func(s, CALLBACK(functools.partial(callback, check))) - self.assertEqual(check.first, s.first) - self.assertEqual(check.second, s.second) - self.assertEqual(check.third, s.third) - self.assertEqual(check.first, 0xdeadbeef) - self.assertEqual(check.second, 0xcafebabe) - self.assertEqual(check.third, 0x0bad1dea) - # See issue #29565. - # Ensure that the original struct is unchanged. - self.assertEqual(s.first, check.first) - self.assertEqual(s.second, check.second) - self.assertEqual(s.third, check.third) - - def test_callback_too_many_args(self): - def func(*args): - return len(args) - - # valid call with nargs <= CTYPES_MAX_ARGCOUNT - proto = CFUNCTYPE(c_int, *(c_int,) * CTYPES_MAX_ARGCOUNT) - cb = proto(func) - args1 = (1,) * CTYPES_MAX_ARGCOUNT - self.assertEqual(cb(*args1), CTYPES_MAX_ARGCOUNT) - - # invalid call with nargs > CTYPES_MAX_ARGCOUNT - args2 = (1,) * (CTYPES_MAX_ARGCOUNT + 1) - with self.assertRaises(ArgumentError): - cb(*args2) - - # error when creating the type with too many arguments - with self.assertRaises(ArgumentError): - CFUNCTYPE(c_int, *(c_int,) * (CTYPES_MAX_ARGCOUNT + 1)) - - def test_convert_result_error(self): - def func(): - return ("tuple",) - - proto = CFUNCTYPE(c_int) - ctypes_func = proto(func) - with support.catch_unraisable_exception() as cm: - # don't test the result since it is an uninitialized value - result = ctypes_func() - - self.assertIsInstance(cm.unraisable.exc_value, TypeError) - self.assertEqual(cm.unraisable.err_msg, - "Exception ignored on converting result " - "of ctypes callback function") - self.assertIs(cm.unraisable.object, func) - - -if __name__ == '__main__': - unittest.main() diff --git a/Lib/ctypes/test/test_cast.py b/Lib/ctypes/test/test_cast.py deleted file mode 100644 index 6878f97..0000000 --- a/Lib/ctypes/test/test_cast.py +++ /dev/null @@ -1,99 +0,0 @@ -from ctypes import * -from ctypes.test import need_symbol -import unittest -import sys - -class Test(unittest.TestCase): - - def test_array2pointer(self): - array = (c_int * 3)(42, 17, 2) - - # casting an array to a pointer works. - ptr = cast(array, POINTER(c_int)) - self.assertEqual([ptr[i] for i in range(3)], [42, 17, 2]) - - if 2*sizeof(c_short) == sizeof(c_int): - ptr = cast(array, POINTER(c_short)) - if sys.byteorder == "little": - self.assertEqual([ptr[i] for i in range(6)], - [42, 0, 17, 0, 2, 0]) - else: - self.assertEqual([ptr[i] for i in range(6)], - [0, 42, 0, 17, 0, 2]) - - def test_address2pointer(self): - array = (c_int * 3)(42, 17, 2) - - address = addressof(array) - ptr = cast(c_void_p(address), POINTER(c_int)) - self.assertEqual([ptr[i] for i in range(3)], [42, 17, 2]) - - ptr = cast(address, POINTER(c_int)) - self.assertEqual([ptr[i] for i in range(3)], [42, 17, 2]) - - def test_p2a_objects(self): - array = (c_char_p * 5)() - self.assertEqual(array._objects, None) - array[0] = b"foo bar" - self.assertEqual(array._objects, {'0': b"foo bar"}) - - p = cast(array, POINTER(c_char_p)) - # array and p share a common _objects attribute - self.assertIs(p._objects, array._objects) - self.assertEqual(array._objects, {'0': b"foo bar", id(array): array}) - p[0] = b"spam spam" - self.assertEqual(p._objects, {'0': b"spam spam", id(array): array}) - self.assertIs(array._objects, p._objects) - p[1] = b"foo bar" - self.assertEqual(p._objects, {'1': b'foo bar', '0': b"spam spam", id(array): array}) - self.assertIs(array._objects, p._objects) - - def test_other(self): - p = cast((c_int * 4)(1, 2, 3, 4), POINTER(c_int)) - self.assertEqual(p[:4], [1,2, 3, 4]) - self.assertEqual(p[:4:], [1, 2, 3, 4]) - self.assertEqual(p[3:-1:-1], [4, 3, 2, 1]) - self.assertEqual(p[:4:3], [1, 4]) - c_int() - self.assertEqual(p[:4], [1, 2, 3, 4]) - self.assertEqual(p[:4:], [1, 2, 3, 4]) - self.assertEqual(p[3:-1:-1], [4, 3, 2, 1]) - self.assertEqual(p[:4:3], [1, 4]) - p[2] = 96 - self.assertEqual(p[:4], [1, 2, 96, 4]) - self.assertEqual(p[:4:], [1, 2, 96, 4]) - self.assertEqual(p[3:-1:-1], [4, 96, 2, 1]) - self.assertEqual(p[:4:3], [1, 4]) - c_int() - self.assertEqual(p[:4], [1, 2, 96, 4]) - self.assertEqual(p[:4:], [1, 2, 96, 4]) - self.assertEqual(p[3:-1:-1], [4, 96, 2, 1]) - self.assertEqual(p[:4:3], [1, 4]) - - def test_char_p(self): - # This didn't work: bad argument to internal function - s = c_char_p(b"hiho") - self.assertEqual(cast(cast(s, c_void_p), c_char_p).value, - b"hiho") - - @need_symbol('c_wchar_p') - def test_wchar_p(self): - s = c_wchar_p("hiho") - self.assertEqual(cast(cast(s, c_void_p), c_wchar_p).value, - "hiho") - - def test_bad_type_arg(self): - # The type argument must be a ctypes pointer type. - array_type = c_byte * sizeof(c_int) - array = array_type() - self.assertRaises(TypeError, cast, array, None) - self.assertRaises(TypeError, cast, array, array_type) - class Struct(Structure): - _fields_ = [("a", c_int)] - self.assertRaises(TypeError, cast, array, Struct) - class MyUnion(Union): - _fields_ = [("a", c_int)] - self.assertRaises(TypeError, cast, array, MyUnion) - -if __name__ == "__main__": - unittest.main() diff --git a/Lib/ctypes/test/test_cfuncs.py b/Lib/ctypes/test/test_cfuncs.py deleted file mode 100644 index ac2240f..0000000 --- a/Lib/ctypes/test/test_cfuncs.py +++ /dev/null @@ -1,212 +0,0 @@ -# A lot of failures in these tests on Mac OS X. -# Byte order related? - -import unittest -from ctypes import * -from ctypes.test import need_symbol - -import _ctypes_test - -class CFunctions(unittest.TestCase): - _dll = CDLL(_ctypes_test.__file__) - - def S(self): - return c_longlong.in_dll(self._dll, "last_tf_arg_s").value - def U(self): - return c_ulonglong.in_dll(self._dll, "last_tf_arg_u").value - - def test_byte(self): - self._dll.tf_b.restype = c_byte - self._dll.tf_b.argtypes = (c_byte,) - self.assertEqual(self._dll.tf_b(-126), -42) - self.assertEqual(self.S(), -126) - - def test_byte_plus(self): - self._dll.tf_bb.restype = c_byte - self._dll.tf_bb.argtypes = (c_byte, c_byte) - self.assertEqual(self._dll.tf_bb(0, -126), -42) - self.assertEqual(self.S(), -126) - - def test_ubyte(self): - self._dll.tf_B.restype = c_ubyte - self._dll.tf_B.argtypes = (c_ubyte,) - self.assertEqual(self._dll.tf_B(255), 85) - self.assertEqual(self.U(), 255) - - def test_ubyte_plus(self): - self._dll.tf_bB.restype = c_ubyte - self._dll.tf_bB.argtypes = (c_byte, c_ubyte) - self.assertEqual(self._dll.tf_bB(0, 255), 85) - self.assertEqual(self.U(), 255) - - def test_short(self): - self._dll.tf_h.restype = c_short - self._dll.tf_h.argtypes = (c_short,) - self.assertEqual(self._dll.tf_h(-32766), -10922) - self.assertEqual(self.S(), -32766) - - def test_short_plus(self): - self._dll.tf_bh.restype = c_short - self._dll.tf_bh.argtypes = (c_byte, c_short) - self.assertEqual(self._dll.tf_bh(0, -32766), -10922) - self.assertEqual(self.S(), -32766) - - def test_ushort(self): - self._dll.tf_H.restype = c_ushort - self._dll.tf_H.argtypes = (c_ushort,) - self.assertEqual(self._dll.tf_H(65535), 21845) - self.assertEqual(self.U(), 65535) - - def test_ushort_plus(self): - self._dll.tf_bH.restype = c_ushort - self._dll.tf_bH.argtypes = (c_byte, c_ushort) - self.assertEqual(self._dll.tf_bH(0, 65535), 21845) - self.assertEqual(self.U(), 65535) - - def test_int(self): - self._dll.tf_i.restype = c_int - self._dll.tf_i.argtypes = (c_int,) - self.assertEqual(self._dll.tf_i(-2147483646), -715827882) - self.assertEqual(self.S(), -2147483646) - - def test_int_plus(self): - self._dll.tf_bi.restype = c_int - self._dll.tf_bi.argtypes = (c_byte, c_int) - self.assertEqual(self._dll.tf_bi(0, -2147483646), -715827882) - self.assertEqual(self.S(), -2147483646) - - def test_uint(self): - self._dll.tf_I.restype = c_uint - self._dll.tf_I.argtypes = (c_uint,) - self.assertEqual(self._dll.tf_I(4294967295), 1431655765) - self.assertEqual(self.U(), 4294967295) - - def test_uint_plus(self): - self._dll.tf_bI.restype = c_uint - self._dll.tf_bI.argtypes = (c_byte, c_uint) - self.assertEqual(self._dll.tf_bI(0, 4294967295), 1431655765) - self.assertEqual(self.U(), 4294967295) - - def test_long(self): - self._dll.tf_l.restype = c_long - self._dll.tf_l.argtypes = (c_long,) - self.assertEqual(self._dll.tf_l(-2147483646), -715827882) - self.assertEqual(self.S(), -2147483646) - - def test_long_plus(self): - self._dll.tf_bl.restype = c_long - self._dll.tf_bl.argtypes = (c_byte, c_long) - self.assertEqual(self._dll.tf_bl(0, -2147483646), -715827882) - self.assertEqual(self.S(), -2147483646) - - def test_ulong(self): - self._dll.tf_L.restype = c_ulong - self._dll.tf_L.argtypes = (c_ulong,) - self.assertEqual(self._dll.tf_L(4294967295), 1431655765) - self.assertEqual(self.U(), 4294967295) - - def test_ulong_plus(self): - self._dll.tf_bL.restype = c_ulong - self._dll.tf_bL.argtypes = (c_char, c_ulong) - self.assertEqual(self._dll.tf_bL(b' ', 4294967295), 1431655765) - self.assertEqual(self.U(), 4294967295) - - def test_longlong(self): - self._dll.tf_q.restype = c_longlong - self._dll.tf_q.argtypes = (c_longlong, ) - self.assertEqual(self._dll.tf_q(-9223372036854775806), -3074457345618258602) - self.assertEqual(self.S(), -9223372036854775806) - - def test_longlong_plus(self): - self._dll.tf_bq.restype = c_longlong - self._dll.tf_bq.argtypes = (c_byte, c_longlong) - self.assertEqual(self._dll.tf_bq(0, -9223372036854775806), -3074457345618258602) - self.assertEqual(self.S(), -9223372036854775806) - - def test_ulonglong(self): - self._dll.tf_Q.restype = c_ulonglong - self._dll.tf_Q.argtypes = (c_ulonglong, ) - self.assertEqual(self._dll.tf_Q(18446744073709551615), 6148914691236517205) - self.assertEqual(self.U(), 18446744073709551615) - - def test_ulonglong_plus(self): - self._dll.tf_bQ.restype = c_ulonglong - self._dll.tf_bQ.argtypes = (c_byte, c_ulonglong) - self.assertEqual(self._dll.tf_bQ(0, 18446744073709551615), 6148914691236517205) - self.assertEqual(self.U(), 18446744073709551615) - - def test_float(self): - self._dll.tf_f.restype = c_float - self._dll.tf_f.argtypes = (c_float,) - self.assertEqual(self._dll.tf_f(-42.), -14.) - self.assertEqual(self.S(), -42) - - def test_float_plus(self): - self._dll.tf_bf.restype = c_float - self._dll.tf_bf.argtypes = (c_byte, c_float) - self.assertEqual(self._dll.tf_bf(0, -42.), -14.) - self.assertEqual(self.S(), -42) - - def test_double(self): - self._dll.tf_d.restype = c_double - self._dll.tf_d.argtypes = (c_double,) - self.assertEqual(self._dll.tf_d(42.), 14.) - self.assertEqual(self.S(), 42) - - def test_double_plus(self): - self._dll.tf_bd.restype = c_double - self._dll.tf_bd.argtypes = (c_byte, c_double) - self.assertEqual(self._dll.tf_bd(0, 42.), 14.) - self.assertEqual(self.S(), 42) - - def test_longdouble(self): - self._dll.tf_D.restype = c_longdouble - self._dll.tf_D.argtypes = (c_longdouble,) - self.assertEqual(self._dll.tf_D(42.), 14.) - self.assertEqual(self.S(), 42) - - def test_longdouble_plus(self): - self._dll.tf_bD.restype = c_longdouble - self._dll.tf_bD.argtypes = (c_byte, c_longdouble) - self.assertEqual(self._dll.tf_bD(0, 42.), 14.) - self.assertEqual(self.S(), 42) - - def test_callwithresult(self): - def process_result(result): - return result * 2 - self._dll.tf_i.restype = process_result - self._dll.tf_i.argtypes = (c_int,) - self.assertEqual(self._dll.tf_i(42), 28) - self.assertEqual(self.S(), 42) - self.assertEqual(self._dll.tf_i(-42), -28) - self.assertEqual(self.S(), -42) - - def test_void(self): - self._dll.tv_i.restype = None - self._dll.tv_i.argtypes = (c_int,) - self.assertEqual(self._dll.tv_i(42), None) - self.assertEqual(self.S(), 42) - self.assertEqual(self._dll.tv_i(-42), None) - self.assertEqual(self.S(), -42) - -# The following repeats the above tests with stdcall functions (where -# they are available) -try: - WinDLL -except NameError: - def stdcall_dll(*_): pass -else: - class stdcall_dll(WinDLL): - def __getattr__(self, name): - if name[:2] == '__' and name[-2:] == '__': - raise AttributeError(name) - func = self._FuncPtr(("s_" + name, self)) - setattr(self, name, func) - return func - -@need_symbol('WinDLL') -class stdcallCFunctions(CFunctions): - _dll = stdcall_dll(_ctypes_test.__file__) - -if __name__ == '__main__': - unittest.main() diff --git a/Lib/ctypes/test/test_checkretval.py b/Lib/ctypes/test/test_checkretval.py deleted file mode 100644 index e9567dc..0000000 --- a/Lib/ctypes/test/test_checkretval.py +++ /dev/null @@ -1,36 +0,0 @@ -import unittest - -from ctypes import * -from ctypes.test import need_symbol - -class CHECKED(c_int): - def _check_retval_(value): - # Receives a CHECKED instance. - return str(value.value) - _check_retval_ = staticmethod(_check_retval_) - -class Test(unittest.TestCase): - - def test_checkretval(self): - - import _ctypes_test - dll = CDLL(_ctypes_test.__file__) - self.assertEqual(42, dll._testfunc_p_p(42)) - - dll._testfunc_p_p.restype = CHECKED - self.assertEqual("42", dll._testfunc_p_p(42)) - - dll._testfunc_p_p.restype = None - self.assertEqual(None, dll._testfunc_p_p(42)) - - del dll._testfunc_p_p.restype - self.assertEqual(42, dll._testfunc_p_p(42)) - - @need_symbol('oledll') - def test_oledll(self): - self.assertRaises(OSError, - oledll.oleaut32.CreateTypeLib2, - 0, None, None) - -if __name__ == "__main__": - unittest.main() diff --git a/Lib/ctypes/test/test_delattr.py b/Lib/ctypes/test/test_delattr.py deleted file mode 100644 index 0f4d586..0000000 --- a/Lib/ctypes/test/test_delattr.py +++ /dev/null @@ -1,21 +0,0 @@ -import unittest -from ctypes import * - -class X(Structure): - _fields_ = [("foo", c_int)] - -class TestCase(unittest.TestCase): - def test_simple(self): - self.assertRaises(TypeError, - delattr, c_int(42), "value") - - def test_chararray(self): - self.assertRaises(TypeError, - delattr, (c_char * 5)(), "value") - - def test_struct(self): - self.assertRaises(TypeError, - delattr, X(), "foo") - -if __name__ == "__main__": - unittest.main() diff --git a/Lib/ctypes/test/test_errno.py b/Lib/ctypes/test/test_errno.py deleted file mode 100644 index 3685164..0000000 --- a/Lib/ctypes/test/test_errno.py +++ /dev/null @@ -1,76 +0,0 @@ -import unittest, os, errno -import threading - -from ctypes import * -from ctypes.util import find_library - -class Test(unittest.TestCase): - def test_open(self): - libc_name = find_library("c") - if libc_name is None: - raise unittest.SkipTest("Unable to find C library") - libc = CDLL(libc_name, use_errno=True) - if os.name == "nt": - libc_open = libc._open - else: - libc_open = libc.open - - libc_open.argtypes = c_char_p, c_int - - self.assertEqual(libc_open(b"", 0), -1) - self.assertEqual(get_errno(), errno.ENOENT) - - self.assertEqual(set_errno(32), errno.ENOENT) - self.assertEqual(get_errno(), 32) - - def _worker(): - set_errno(0) - - libc = CDLL(libc_name, use_errno=False) - if os.name == "nt": - libc_open = libc._open - else: - libc_open = libc.open - libc_open.argtypes = c_char_p, c_int - self.assertEqual(libc_open(b"", 0), -1) - self.assertEqual(get_errno(), 0) - - t = threading.Thread(target=_worker) - t.start() - t.join() - - self.assertEqual(get_errno(), 32) - set_errno(0) - - @unittest.skipUnless(os.name == "nt", 'Test specific to Windows') - def test_GetLastError(self): - dll = WinDLL("kernel32", use_last_error=True) - GetModuleHandle = dll.GetModuleHandleA - GetModuleHandle.argtypes = [c_wchar_p] - - self.assertEqual(0, GetModuleHandle("foo")) - self.assertEqual(get_last_error(), 126) - - self.assertEqual(set_last_error(32), 126) - self.assertEqual(get_last_error(), 32) - - def _worker(): - set_last_error(0) - - dll = WinDLL("kernel32", use_last_error=False) - GetModuleHandle = dll.GetModuleHandleW - GetModuleHandle.argtypes = [c_wchar_p] - GetModuleHandle("bar") - - self.assertEqual(get_last_error(), 0) - - t = threading.Thread(target=_worker) - t.start() - t.join() - - self.assertEqual(get_last_error(), 32) - - set_last_error(0) - -if __name__ == "__main__": - unittest.main() diff --git a/Lib/ctypes/test/test_find.py b/Lib/ctypes/test/test_find.py deleted file mode 100644 index 1ff9d01..0000000 --- a/Lib/ctypes/test/test_find.py +++ /dev/null @@ -1,127 +0,0 @@ -import unittest -import unittest.mock -import os.path -import sys -import test.support -from test.support import os_helper -from ctypes import * -from ctypes.util import find_library - -# On some systems, loading the OpenGL libraries needs the RTLD_GLOBAL mode. -class Test_OpenGL_libs(unittest.TestCase): - @classmethod - def setUpClass(cls): - lib_gl = lib_glu = lib_gle = None - if sys.platform == "win32": - lib_gl = find_library("OpenGL32") - lib_glu = find_library("Glu32") - elif sys.platform == "darwin": - lib_gl = lib_glu = find_library("OpenGL") - else: - lib_gl = find_library("GL") - lib_glu = find_library("GLU") - lib_gle = find_library("gle") - - ## print, for debugging - if test.support.verbose: - print("OpenGL libraries:") - for item in (("GL", lib_gl), - ("GLU", lib_glu), - ("gle", lib_gle)): - print("\t", item) - - cls.gl = cls.glu = cls.gle = None - if lib_gl: - try: - cls.gl = CDLL(lib_gl, mode=RTLD_GLOBAL) - except OSError: - pass - if lib_glu: - try: - cls.glu = CDLL(lib_glu, RTLD_GLOBAL) - except OSError: - pass - if lib_gle: - try: - cls.gle = CDLL(lib_gle) - except OSError: - pass - - @classmethod - def tearDownClass(cls): - cls.gl = cls.glu = cls.gle = None - - def test_gl(self): - if self.gl is None: - self.skipTest('lib_gl not available') - self.gl.glClearIndex - - def test_glu(self): - if self.glu is None: - self.skipTest('lib_glu not available') - self.glu.gluBeginCurve - - def test_gle(self): - if self.gle is None: - self.skipTest('lib_gle not available') - self.gle.gleGetJoinStyle - - def test_shell_injection(self): - result = find_library('; echo Hello shell > ' + os_helper.TESTFN) - self.assertFalse(os.path.lexists(os_helper.TESTFN)) - self.assertIsNone(result) - - -@unittest.skipUnless(sys.platform.startswith('linux'), - 'Test only valid for Linux') -class FindLibraryLinux(unittest.TestCase): - def test_find_on_libpath(self): - import subprocess - import tempfile - - try: - p = subprocess.Popen(['gcc', '--version'], stdout=subprocess.PIPE, - stderr=subprocess.DEVNULL) - out, _ = p.communicate() - except OSError: - raise unittest.SkipTest('gcc, needed for test, not available') - with tempfile.TemporaryDirectory() as d: - # create an empty temporary file - srcname = os.path.join(d, 'dummy.c') - libname = 'py_ctypes_test_dummy' - dstname = os.path.join(d, 'lib%s.so' % libname) - with open(srcname, 'wb') as f: - pass - self.assertTrue(os.path.exists(srcname)) - # compile the file to a shared library - cmd = ['gcc', '-o', dstname, '--shared', - '-Wl,-soname,lib%s.so' % libname, srcname] - out = subprocess.check_output(cmd) - self.assertTrue(os.path.exists(dstname)) - # now check that the .so can't be found (since not in - # LD_LIBRARY_PATH) - self.assertIsNone(find_library(libname)) - # now add the location to LD_LIBRARY_PATH - with os_helper.EnvironmentVarGuard() as env: - KEY = 'LD_LIBRARY_PATH' - if KEY not in env: - v = d - else: - v = '%s:%s' % (env[KEY], d) - env.set(KEY, v) - # now check that the .so can be found (since in - # LD_LIBRARY_PATH) - self.assertEqual(find_library(libname), 'lib%s.so' % libname) - - def test_find_library_with_gcc(self): - with unittest.mock.patch("ctypes.util._findSoname_ldconfig", lambda *args: None): - self.assertNotEqual(find_library('c'), None) - - def test_find_library_with_ld(self): - with unittest.mock.patch("ctypes.util._findSoname_ldconfig", lambda *args: None), \ - unittest.mock.patch("ctypes.util._findLib_gcc", lambda *args: None): - self.assertNotEqual(find_library('c'), None) - - -if __name__ == "__main__": - unittest.main() diff --git a/Lib/ctypes/test/test_frombuffer.py b/Lib/ctypes/test/test_frombuffer.py deleted file mode 100644 index 55c2443..0000000 --- a/Lib/ctypes/test/test_frombuffer.py +++ /dev/null @@ -1,141 +0,0 @@ -from ctypes import * -import array -import gc -import unittest - -class X(Structure): - _fields_ = [("c_int", c_int)] - init_called = False - def __init__(self): - self._init_called = True - -class Test(unittest.TestCase): - def test_from_buffer(self): - a = array.array("i", range(16)) - x = (c_int * 16).from_buffer(a) - - y = X.from_buffer(a) - self.assertEqual(y.c_int, a[0]) - self.assertFalse(y.init_called) - - self.assertEqual(x[:], a.tolist()) - - a[0], a[-1] = 200, -200 - self.assertEqual(x[:], a.tolist()) - - self.assertRaises(BufferError, a.append, 100) - self.assertRaises(BufferError, a.pop) - - del x; del y; gc.collect(); gc.collect(); gc.collect() - a.append(100) - a.pop() - x = (c_int * 16).from_buffer(a) - - self.assertIn(a, [obj.obj if isinstance(obj, memoryview) else obj - for obj in x._objects.values()]) - - expected = x[:] - del a; gc.collect(); gc.collect(); gc.collect() - self.assertEqual(x[:], expected) - - with self.assertRaisesRegex(TypeError, "not writable"): - (c_char * 16).from_buffer(b"a" * 16) - with self.assertRaisesRegex(TypeError, "not writable"): - (c_char * 16).from_buffer(memoryview(b"a" * 16)) - with self.assertRaisesRegex(TypeError, "not C contiguous"): - (c_char * 16).from_buffer(memoryview(bytearray(b"a" * 16))[::-1]) - msg = "bytes-like object is required" - with self.assertRaisesRegex(TypeError, msg): - (c_char * 16).from_buffer("a" * 16) - - def test_fortran_contiguous(self): - try: - import _testbuffer - except ImportError as err: - self.skipTest(str(err)) - flags = _testbuffer.ND_WRITABLE | _testbuffer.ND_FORTRAN - array = _testbuffer.ndarray( - [97] * 16, format="B", shape=[4, 4], flags=flags) - with self.assertRaisesRegex(TypeError, "not C contiguous"): - (c_char * 16).from_buffer(array) - array = memoryview(array) - self.assertTrue(array.f_contiguous) - self.assertFalse(array.c_contiguous) - with self.assertRaisesRegex(TypeError, "not C contiguous"): - (c_char * 16).from_buffer(array) - - def test_from_buffer_with_offset(self): - a = array.array("i", range(16)) - x = (c_int * 15).from_buffer(a, sizeof(c_int)) - - self.assertEqual(x[:], a.tolist()[1:]) - with self.assertRaises(ValueError): - c_int.from_buffer(a, -1) - with self.assertRaises(ValueError): - (c_int * 16).from_buffer(a, sizeof(c_int)) - with self.assertRaises(ValueError): - (c_int * 1).from_buffer(a, 16 * sizeof(c_int)) - - def test_from_buffer_memoryview(self): - a = [c_char.from_buffer(memoryview(bytearray(b'a')))] - a.append(a) - del a - gc.collect() # Should not crash - - def test_from_buffer_copy(self): - a = array.array("i", range(16)) - x = (c_int * 16).from_buffer_copy(a) - - y = X.from_buffer_copy(a) - self.assertEqual(y.c_int, a[0]) - self.assertFalse(y.init_called) - - self.assertEqual(x[:], list(range(16))) - - a[0], a[-1] = 200, -200 - self.assertEqual(x[:], list(range(16))) - - a.append(100) - self.assertEqual(x[:], list(range(16))) - - self.assertEqual(x._objects, None) - - del a; gc.collect(); gc.collect(); gc.collect() - self.assertEqual(x[:], list(range(16))) - - x = (c_char * 16).from_buffer_copy(b"a" * 16) - self.assertEqual(x[:], b"a" * 16) - with self.assertRaises(TypeError): - (c_char * 16).from_buffer_copy("a" * 16) - - def test_from_buffer_copy_with_offset(self): - a = array.array("i", range(16)) - x = (c_int * 15).from_buffer_copy(a, sizeof(c_int)) - - self.assertEqual(x[:], a.tolist()[1:]) - with self.assertRaises(ValueError): - c_int.from_buffer_copy(a, -1) - with self.assertRaises(ValueError): - (c_int * 16).from_buffer_copy(a, sizeof(c_int)) - with self.assertRaises(ValueError): - (c_int * 1).from_buffer_copy(a, 16 * sizeof(c_int)) - - def test_abstract(self): - from ctypes import _Pointer, _SimpleCData, _CFuncPtr - - self.assertRaises(TypeError, Array.from_buffer, bytearray(10)) - self.assertRaises(TypeError, Structure.from_buffer, bytearray(10)) - self.assertRaises(TypeError, Union.from_buffer, bytearray(10)) - self.assertRaises(TypeError, _CFuncPtr.from_buffer, bytearray(10)) - self.assertRaises(TypeError, _Pointer.from_buffer, bytearray(10)) - self.assertRaises(TypeError, _SimpleCData.from_buffer, bytearray(10)) - - self.assertRaises(TypeError, Array.from_buffer_copy, b"123") - self.assertRaises(TypeError, Structure.from_buffer_copy, b"123") - self.assertRaises(TypeError, Union.from_buffer_copy, b"123") - self.assertRaises(TypeError, _CFuncPtr.from_buffer_copy, b"123") - self.assertRaises(TypeError, _Pointer.from_buffer_copy, b"123") - self.assertRaises(TypeError, _SimpleCData.from_buffer_copy, b"123") - -if __name__ == '__main__': - unittest.main() diff --git a/Lib/ctypes/test/test_funcptr.py b/Lib/ctypes/test/test_funcptr.py deleted file mode 100644 index e0b9b54..0000000 --- a/Lib/ctypes/test/test_funcptr.py +++ /dev/null @@ -1,132 +0,0 @@ -import unittest -from ctypes import * - -try: - WINFUNCTYPE -except NameError: - # fake to enable this test on Linux - WINFUNCTYPE = CFUNCTYPE - -import _ctypes_test -lib = CDLL(_ctypes_test.__file__) - -class CFuncPtrTestCase(unittest.TestCase): - def test_basic(self): - X = WINFUNCTYPE(c_int, c_int, c_int) - - def func(*args): - return len(args) - - x = X(func) - self.assertEqual(x.restype, c_int) - self.assertEqual(x.argtypes, (c_int, c_int)) - self.assertEqual(sizeof(x), sizeof(c_voidp)) - self.assertEqual(sizeof(X), sizeof(c_voidp)) - - def test_first(self): - StdCallback = WINFUNCTYPE(c_int, c_int, c_int) - CdeclCallback = CFUNCTYPE(c_int, c_int, c_int) - - def func(a, b): - return a + b - - s = StdCallback(func) - c = CdeclCallback(func) - - self.assertEqual(s(1, 2), 3) - self.assertEqual(c(1, 2), 3) - # The following no longer raises a TypeError - it is now - # possible, as in C, to call cdecl functions with more parameters. - #self.assertRaises(TypeError, c, 1, 2, 3) - self.assertEqual(c(1, 2, 3, 4, 5, 6), 3) - if not WINFUNCTYPE is CFUNCTYPE: - self.assertRaises(TypeError, s, 1, 2, 3) - - def test_structures(self): - WNDPROC = WINFUNCTYPE(c_long, c_int, c_int, c_int, c_int) - - def wndproc(hwnd, msg, wParam, lParam): - return hwnd + msg + wParam + lParam - - HINSTANCE = c_int - HICON = c_int - HCURSOR = c_int - LPCTSTR = c_char_p - - class WNDCLASS(Structure): - _fields_ = [("style", c_uint), - ("lpfnWndProc", WNDPROC), - ("cbClsExtra", c_int), - ("cbWndExtra", c_int), - ("hInstance", HINSTANCE), - ("hIcon", HICON), - ("hCursor", HCURSOR), - ("lpszMenuName", LPCTSTR), - ("lpszClassName", LPCTSTR)] - - wndclass = WNDCLASS() - wndclass.lpfnWndProc = WNDPROC(wndproc) - - WNDPROC_2 = WINFUNCTYPE(c_long, c_int, c_int, c_int, c_int) - - # This is no longer true, now that WINFUNCTYPE caches created types internally. - ## # CFuncPtr subclasses are compared by identity, so this raises a TypeError: - ## self.assertRaises(TypeError, setattr, wndclass, - ## "lpfnWndProc", WNDPROC_2(wndproc)) - # instead: - - self.assertIs(WNDPROC, WNDPROC_2) - # 'wndclass.lpfnWndProc' leaks 94 references. Why? - self.assertEqual(wndclass.lpfnWndProc(1, 2, 3, 4), 10) - - - f = wndclass.lpfnWndProc - - del wndclass - del wndproc - - self.assertEqual(f(10, 11, 12, 13), 46) - - def test_dllfunctions(self): - - def NoNullHandle(value): - if not value: - raise WinError() - return value - - strchr = lib.my_strchr - strchr.restype = c_char_p - strchr.argtypes = (c_char_p, c_char) - self.assertEqual(strchr(b"abcdefghi", b"b"), b"bcdefghi") - self.assertEqual(strchr(b"abcdefghi", b"x"), None) - - - strtok = lib.my_strtok - strtok.restype = c_char_p - # Neither of this does work: strtok changes the buffer it is passed -## strtok.argtypes = (c_char_p, c_char_p) -## strtok.argtypes = (c_string, c_char_p) - - def c_string(init): - size = len(init) + 1 - return (c_char*size)(*init) - - s = b"a\nb\nc" - b = c_string(s) - -## b = (c_char * (len(s)+1))() -## b.value = s - -## b = c_string(s) - self.assertEqual(strtok(b, b"\n"), b"a") - self.assertEqual(strtok(None, b"\n"), b"b") - self.assertEqual(strtok(None, b"\n"), b"c") - self.assertEqual(strtok(None, b"\n"), None) - - def test_abstract(self): - from ctypes import _CFuncPtr - - self.assertRaises(TypeError, _CFuncPtr, 13, "name", 42, "iid") - -if __name__ == '__main__': - unittest.main() diff --git a/Lib/ctypes/test/test_functions.py b/Lib/ctypes/test/test_functions.py deleted file mode 100644 index f9e92e1..0000000 --- a/Lib/ctypes/test/test_functions.py +++ /dev/null @@ -1,383 +0,0 @@ -""" -Here is probably the place to write the docs, since the test-cases -show how the type behave. - -Later... -""" - -from ctypes import * -from ctypes.test import need_symbol -import sys, unittest - -try: - WINFUNCTYPE -except NameError: - # fake to enable this test on Linux - WINFUNCTYPE = CFUNCTYPE - -import _ctypes_test -dll = CDLL(_ctypes_test.__file__) -if sys.platform == "win32": - windll = WinDLL(_ctypes_test.__file__) - -class POINT(Structure): - _fields_ = [("x", c_int), ("y", c_int)] -class RECT(Structure): - _fields_ = [("left", c_int), ("top", c_int), - ("right", c_int), ("bottom", c_int)] -class FunctionTestCase(unittest.TestCase): - - def test_mro(self): - # in Python 2.3, this raises TypeError: MRO conflict among bases classes, - # in Python 2.2 it works. - # - # But in early versions of _ctypes.c, the result of tp_new - # wasn't checked, and it even crashed Python. - # Found by Greg Chapman. - - with self.assertRaises(TypeError): - class X(object, Array): - _length_ = 5 - _type_ = "i" - - from _ctypes import _Pointer - with self.assertRaises(TypeError): - class X(object, _Pointer): - pass - - from _ctypes import _SimpleCData - with self.assertRaises(TypeError): - class X(object, _SimpleCData): - _type_ = "i" - - with self.assertRaises(TypeError): - class X(object, Structure): - _fields_ = [] - - @need_symbol('c_wchar') - def test_wchar_parm(self): - f = dll._testfunc_i_bhilfd - f.argtypes = [c_byte, c_wchar, c_int, c_long, c_float, c_double] - result = f(1, "x", 3, 4, 5.0, 6.0) - self.assertEqual(result, 139) - self.assertEqual(type(result), int) - - @need_symbol('c_wchar') - def test_wchar_result(self): - f = dll._testfunc_i_bhilfd - f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double] - f.restype = c_wchar - result = f(0, 0, 0, 0, 0, 0) - self.assertEqual(result, '\x00') - - def test_voidresult(self): - f = dll._testfunc_v - f.restype = None - f.argtypes = [c_int, c_int, POINTER(c_int)] - result = c_int() - self.assertEqual(None, f(1, 2, byref(result))) - self.assertEqual(result.value, 3) - - def test_intresult(self): - f = dll._testfunc_i_bhilfd - f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double] - f.restype = c_int - result = f(1, 2, 3, 4, 5.0, 6.0) - self.assertEqual(result, 21) - self.assertEqual(type(result), int) - - result = f(-1, -2, -3, -4, -5.0, -6.0) - self.assertEqual(result, -21) - self.assertEqual(type(result), int) - - # If we declare the function to return a short, - # is the high part split off? - f.restype = c_short - result = f(1, 2, 3, 4, 5.0, 6.0) - self.assertEqual(result, 21) - self.assertEqual(type(result), int) - - result = f(1, 2, 3, 0x10004, 5.0, 6.0) - self.assertEqual(result, 21) - self.assertEqual(type(result), int) - - # You cannot assign character format codes as restype any longer - self.assertRaises(TypeError, setattr, f, "restype", "i") - - def test_floatresult(self): - f = dll._testfunc_f_bhilfd - f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double] - f.restype = c_float - result = f(1, 2, 3, 4, 5.0, 6.0) - self.assertEqual(result, 21) - self.assertEqual(type(result), float) - - result = f(-1, -2, -3, -4, -5.0, -6.0) - self.assertEqual(result, -21) - self.assertEqual(type(result), float) - - def test_doubleresult(self): - f = dll._testfunc_d_bhilfd - f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double] - f.restype = c_double - result = f(1, 2, 3, 4, 5.0, 6.0) - self.assertEqual(result, 21) - self.assertEqual(type(result), float) - - result = f(-1, -2, -3, -4, -5.0, -6.0) - self.assertEqual(result, -21) - self.assertEqual(type(result), float) - - def test_longdoubleresult(self): - f = dll._testfunc_D_bhilfD - f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_longdouble] - f.restype = c_longdouble - result = f(1, 2, 3, 4, 5.0, 6.0) - self.assertEqual(result, 21) - self.assertEqual(type(result), float) - - result = f(-1, -2, -3, -4, -5.0, -6.0) - self.assertEqual(result, -21) - self.assertEqual(type(result), float) - - @need_symbol('c_longlong') - def test_longlongresult(self): - f = dll._testfunc_q_bhilfd - f.restype = c_longlong - f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double] - result = f(1, 2, 3, 4, 5.0, 6.0) - self.assertEqual(result, 21) - - f = dll._testfunc_q_bhilfdq - f.restype = c_longlong - f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double, c_longlong] - result = f(1, 2, 3, 4, 5.0, 6.0, 21) - self.assertEqual(result, 42) - - def test_stringresult(self): - f = dll._testfunc_p_p - f.argtypes = None - f.restype = c_char_p - result = f(b"123") - self.assertEqual(result, b"123") - - result = f(None) - self.assertEqual(result, None) - - def test_pointers(self): - f = dll._testfunc_p_p - f.restype = POINTER(c_int) - f.argtypes = [POINTER(c_int)] - - # This only works if the value c_int(42) passed to the - # function is still alive while the pointer (the result) is - # used. - - v = c_int(42) - - self.assertEqual(pointer(v).contents.value, 42) - result = f(pointer(v)) - self.assertEqual(type(result), POINTER(c_int)) - self.assertEqual(result.contents.value, 42) - - # This on works... - result = f(pointer(v)) - self.assertEqual(result.contents.value, v.value) - - p = pointer(c_int(99)) - result = f(p) - self.assertEqual(result.contents.value, 99) - - arg = byref(v) - result = f(arg) - self.assertNotEqual(result.contents, v.value) - - self.assertRaises(ArgumentError, f, byref(c_short(22))) - - # It is dangerous, however, because you don't control the lifetime - # of the pointer: - result = f(byref(c_int(99))) - self.assertNotEqual(result.contents, 99) - - ################################################################ - def test_shorts(self): - f = dll._testfunc_callback_i_if - - args = [] - expected = [262144, 131072, 65536, 32768, 16384, 8192, 4096, 2048, - 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1] - - def callback(v): - args.append(v) - return v - - CallBack = CFUNCTYPE(c_int, c_int) - - cb = CallBack(callback) - f(2**18, cb) - self.assertEqual(args, expected) - - ################################################################ - - - def test_callbacks(self): - f = dll._testfunc_callback_i_if - f.restype = c_int - f.argtypes = None - - MyCallback = CFUNCTYPE(c_int, c_int) - - def callback(value): - #print "called back with", value - return value - - cb = MyCallback(callback) - result = f(-10, cb) - self.assertEqual(result, -18) - - # test with prototype - f.argtypes = [c_int, MyCallback] - cb = MyCallback(callback) - result = f(-10, cb) - self.assertEqual(result, -18) - - AnotherCallback = WINFUNCTYPE(c_int, c_int, c_int, c_int, c_int) - - # check that the prototype works: we call f with wrong - # argument types - cb = AnotherCallback(callback) - self.assertRaises(ArgumentError, f, -10, cb) - - - def test_callbacks_2(self): - # Can also use simple datatypes as argument type specifiers - # for the callback function. - # In this case the call receives an instance of that type - f = dll._testfunc_callback_i_if - f.restype = c_int - - MyCallback = CFUNCTYPE(c_int, c_int) - - f.argtypes = [c_int, MyCallback] - - def callback(value): - #print "called back with", value - self.assertEqual(type(value), int) - return value - - cb = MyCallback(callback) - result = f(-10, cb) - self.assertEqual(result, -18) - - @need_symbol('c_longlong') - def test_longlong_callbacks(self): - - f = dll._testfunc_callback_q_qf - f.restype = c_longlong - - MyCallback = CFUNCTYPE(c_longlong, c_longlong) - - f.argtypes = [c_longlong, MyCallback] - - def callback(value): - self.assertIsInstance(value, int) - return value & 0x7FFFFFFF - - cb = MyCallback(callback) - - self.assertEqual(13577625587, f(1000000000000, cb)) - - def test_errors(self): - self.assertRaises(AttributeError, getattr, dll, "_xxx_yyy") - self.assertRaises(ValueError, c_int.in_dll, dll, "_xxx_yyy") - - def test_byval(self): - - # without prototype - ptin = POINT(1, 2) - ptout = POINT() - # EXPORT int _testfunc_byval(point in, point *pout) - result = dll._testfunc_byval(ptin, byref(ptout)) - got = result, ptout.x, ptout.y - expected = 3, 1, 2 - self.assertEqual(got, expected) - - # with prototype - ptin = POINT(101, 102) - ptout = POINT() - dll._testfunc_byval.argtypes = (POINT, POINTER(POINT)) - dll._testfunc_byval.restype = c_int - result = dll._testfunc_byval(ptin, byref(ptout)) - got = result, ptout.x, ptout.y - expected = 203, 101, 102 - self.assertEqual(got, expected) - - def test_struct_return_2H(self): - class S2H(Structure): - _fields_ = [("x", c_short), - ("y", c_short)] - dll.ret_2h_func.restype = S2H - dll.ret_2h_func.argtypes = [S2H] - inp = S2H(99, 88) - s2h = dll.ret_2h_func(inp) - self.assertEqual((s2h.x, s2h.y), (99*2, 88*3)) - - @unittest.skipUnless(sys.platform == "win32", 'Windows-specific test') - def test_struct_return_2H_stdcall(self): - class S2H(Structure): - _fields_ = [("x", c_short), - ("y", c_short)] - - windll.s_ret_2h_func.restype = S2H - windll.s_ret_2h_func.argtypes = [S2H] - s2h = windll.s_ret_2h_func(S2H(99, 88)) - self.assertEqual((s2h.x, s2h.y), (99*2, 88*3)) - - def test_struct_return_8H(self): - class S8I(Structure): - _fields_ = [("a", c_int), - ("b", c_int), - ("c", c_int), - ("d", c_int), - ("e", c_int), - ("f", c_int), - ("g", c_int), - ("h", c_int)] - dll.ret_8i_func.restype = S8I - dll.ret_8i_func.argtypes = [S8I] - inp = S8I(9, 8, 7, 6, 5, 4, 3, 2) - s8i = dll.ret_8i_func(inp) - self.assertEqual((s8i.a, s8i.b, s8i.c, s8i.d, s8i.e, s8i.f, s8i.g, s8i.h), - (9*2, 8*3, 7*4, 6*5, 5*6, 4*7, 3*8, 2*9)) - - @unittest.skipUnless(sys.platform == "win32", 'Windows-specific test') - def test_struct_return_8H_stdcall(self): - class S8I(Structure): - _fields_ = [("a", c_int), - ("b", c_int), - ("c", c_int), - ("d", c_int), - ("e", c_int), - ("f", c_int), - ("g", c_int), - ("h", c_int)] - windll.s_ret_8i_func.restype = S8I - windll.s_ret_8i_func.argtypes = [S8I] - inp = S8I(9, 8, 7, 6, 5, 4, 3, 2) - s8i = windll.s_ret_8i_func(inp) - self.assertEqual( - (s8i.a, s8i.b, s8i.c, s8i.d, s8i.e, s8i.f, s8i.g, s8i.h), - (9*2, 8*3, 7*4, 6*5, 5*6, 4*7, 3*8, 2*9)) - - def test_sf1651235(self): - # see https://www.python.org/sf/1651235 - - proto = CFUNCTYPE(c_int, RECT, POINT) - def callback(*args): - return 0 - - callback = proto(callback) - self.assertRaises(ArgumentError, lambda: callback((1, 2, 3, 4), POINT())) - -if __name__ == '__main__': - unittest.main() diff --git a/Lib/ctypes/test/test_incomplete.py b/Lib/ctypes/test/test_incomplete.py deleted file mode 100644 index 00c430e..0000000 --- a/Lib/ctypes/test/test_incomplete.py +++ /dev/null @@ -1,42 +0,0 @@ -import unittest -from ctypes import * - -################################################################ -# -# The incomplete pointer example from the tutorial -# - -class MyTestCase(unittest.TestCase): - - def test_incomplete_example(self): - lpcell = POINTER("cell") - class cell(Structure): - _fields_ = [("name", c_char_p), - ("next", lpcell)] - - SetPointerType(lpcell, cell) - - c1 = cell() - c1.name = b"foo" - c2 = cell() - c2.name = b"bar" - - c1.next = pointer(c2) - c2.next = pointer(c1) - - p = c1 - - result = [] - for i in range(8): - result.append(p.name) - p = p.next[0] - self.assertEqual(result, [b"foo", b"bar"] * 4) - - # to not leak references, we must clean _pointer_type_cache - from ctypes import _pointer_type_cache - del _pointer_type_cache[cell] - -################################################################ - -if __name__ == '__main__': - unittest.main() diff --git a/Lib/ctypes/test/test_init.py b/Lib/ctypes/test/test_init.py deleted file mode 100644 index 75fad11..0000000 --- a/Lib/ctypes/test/test_init.py +++ /dev/null @@ -1,40 +0,0 @@ -from ctypes import * -import unittest - -class X(Structure): - _fields_ = [("a", c_int), - ("b", c_int)] - new_was_called = False - - def __new__(cls): - result = super().__new__(cls) - result.new_was_called = True - return result - - def __init__(self): - self.a = 9 - self.b = 12 - -class Y(Structure): - _fields_ = [("x", X)] - - -class InitTest(unittest.TestCase): - def test_get(self): - # make sure the only accessing a nested structure - # doesn't call the structure's __new__ and __init__ - y = Y() - self.assertEqual((y.x.a, y.x.b), (0, 0)) - self.assertEqual(y.x.new_was_called, False) - - # But explicitly creating an X structure calls __new__ and __init__, of course. - x = X() - self.assertEqual((x.a, x.b), (9, 12)) - self.assertEqual(x.new_was_called, True) - - y.x = x - self.assertEqual((y.x.a, y.x.b), (9, 12)) - self.assertEqual(y.x.new_was_called, False) - -if __name__ == "__main__": - unittest.main() diff --git a/Lib/ctypes/test/test_internals.py b/Lib/ctypes/test/test_internals.py deleted file mode 100644 index 271e3f5..0000000 --- a/Lib/ctypes/test/test_internals.py +++ /dev/null @@ -1,100 +0,0 @@ -# This tests the internal _objects attribute -import unittest -from ctypes import * -from sys import getrefcount as grc - -# XXX This test must be reviewed for correctness!!! - -# ctypes' types are container types. -# -# They have an internal memory block, which only consists of some bytes, -# but it has to keep references to other objects as well. This is not -# really needed for trivial C types like int or char, but it is important -# for aggregate types like strings or pointers in particular. -# -# What about pointers? - -class ObjectsTestCase(unittest.TestCase): - def assertSame(self, a, b): - self.assertEqual(id(a), id(b)) - - def test_ints(self): - i = 42000123 - refcnt = grc(i) - ci = c_int(i) - self.assertEqual(refcnt, grc(i)) - self.assertEqual(ci._objects, None) - - def test_c_char_p(self): - s = b"Hello, World" - refcnt = grc(s) - cs = c_char_p(s) - self.assertEqual(refcnt + 1, grc(s)) - self.assertSame(cs._objects, s) - - def test_simple_struct(self): - class X(Structure): - _fields_ = [("a", c_int), ("b", c_int)] - - a = 421234 - b = 421235 - x = X() - self.assertEqual(x._objects, None) - x.a = a - x.b = b - self.assertEqual(x._objects, None) - - def test_embedded_structs(self): - class X(Structure): - _fields_ = [("a", c_int), ("b", c_int)] - - class Y(Structure): - _fields_ = [("x", X), ("y", X)] - - y = Y() - self.assertEqual(y._objects, None) - - x1, x2 = X(), X() - y.x, y.y = x1, x2 - self.assertEqual(y._objects, {"0": {}, "1": {}}) - x1.a, x2.b = 42, 93 - self.assertEqual(y._objects, {"0": {}, "1": {}}) - - def test_xxx(self): - class X(Structure): - _fields_ = [("a", c_char_p), ("b", c_char_p)] - - class Y(Structure): - _fields_ = [("x", X), ("y", X)] - - s1 = b"Hello, World" - s2 = b"Hallo, Welt" - - x = X() - x.a = s1 - x.b = s2 - self.assertEqual(x._objects, {"0": s1, "1": s2}) - - y = Y() - y.x = x - self.assertEqual(y._objects, {"0": {"0": s1, "1": s2}}) -## x = y.x -## del y -## print x._b_base_._objects - - def test_ptr_struct(self): - class X(Structure): - _fields_ = [("data", POINTER(c_int))] - - A = c_int*4 - a = A(11, 22, 33, 44) - self.assertEqual(a._objects, None) - - x = X() - x.data = a -##XXX print x._objects -##XXX print x.data[0] -##XXX print x.data._objects - -if __name__ == '__main__': - unittest.main() diff --git a/Lib/ctypes/test/test_keeprefs.py b/Lib/ctypes/test/test_keeprefs.py deleted file mode 100644 index 94c0257..0000000 --- a/Lib/ctypes/test/test_keeprefs.py +++ /dev/null @@ -1,153 +0,0 @@ -from ctypes import * -import unittest - -class SimpleTestCase(unittest.TestCase): - def test_cint(self): - x = c_int() - self.assertEqual(x._objects, None) - x.value = 42 - self.assertEqual(x._objects, None) - x = c_int(99) - self.assertEqual(x._objects, None) - - def test_ccharp(self): - x = c_char_p() - self.assertEqual(x._objects, None) - x.value = b"abc" - self.assertEqual(x._objects, b"abc") - x = c_char_p(b"spam") - self.assertEqual(x._objects, b"spam") - -class StructureTestCase(unittest.TestCase): - def test_cint_struct(self): - class X(Structure): - _fields_ = [("a", c_int), - ("b", c_int)] - - x = X() - self.assertEqual(x._objects, None) - x.a = 42 - x.b = 99 - self.assertEqual(x._objects, None) - - def test_ccharp_struct(self): - class X(Structure): - _fields_ = [("a", c_char_p), - ("b", c_char_p)] - x = X() - self.assertEqual(x._objects, None) - - x.a = b"spam" - x.b = b"foo" - self.assertEqual(x._objects, {"0": b"spam", "1": b"foo"}) - - def test_struct_struct(self): - class POINT(Structure): - _fields_ = [("x", c_int), ("y", c_int)] - class RECT(Structure): - _fields_ = [("ul", POINT), ("lr", POINT)] - - r = RECT() - r.ul.x = 0 - r.ul.y = 1 - r.lr.x = 2 - r.lr.y = 3 - self.assertEqual(r._objects, None) - - r = RECT() - pt = POINT(1, 2) - r.ul = pt - self.assertEqual(r._objects, {'0': {}}) - r.ul.x = 22 - r.ul.y = 44 - self.assertEqual(r._objects, {'0': {}}) - r.lr = POINT() - self.assertEqual(r._objects, {'0': {}, '1': {}}) - -class ArrayTestCase(unittest.TestCase): - def test_cint_array(self): - INTARR = c_int * 3 - - ia = INTARR() - self.assertEqual(ia._objects, None) - ia[0] = 1 - ia[1] = 2 - ia[2] = 3 - self.assertEqual(ia._objects, None) - - class X(Structure): - _fields_ = [("x", c_int), - ("a", INTARR)] - - x = X() - x.x = 1000 - x.a[0] = 42 - x.a[1] = 96 - self.assertEqual(x._objects, None) - x.a = ia - self.assertEqual(x._objects, {'1': {}}) - -class PointerTestCase(unittest.TestCase): - def test_p_cint(self): - i = c_int(42) - x = pointer(i) - self.assertEqual(x._objects, {'1': i}) - -class DeletePointerTestCase(unittest.TestCase): - @unittest.skip('test disabled') - def test_X(self): - class X(Structure): - _fields_ = [("p", POINTER(c_char_p))] - x = X() - i = c_char_p("abc def") - from sys import getrefcount as grc - print("2?", grc(i)) - x.p = pointer(i) - print("3?", grc(i)) - for i in range(320): - c_int(99) - x.p[0] - print(x.p[0]) -## del x -## print "2?", grc(i) -## del i - import gc - gc.collect() - for i in range(320): - c_int(99) - x.p[0] - print(x.p[0]) - print(x.p.contents) -## print x._objects - - x.p[0] = "spam spam" -## print x.p[0] - print("+" * 42) - print(x._objects) - -class PointerToStructure(unittest.TestCase): - def test(self): - class POINT(Structure): - _fields_ = [("x", c_int), ("y", c_int)] - class RECT(Structure): - _fields_ = [("a", POINTER(POINT)), - ("b", POINTER(POINT))] - r = RECT() - p1 = POINT(1, 2) - - r.a = pointer(p1) - r.b = pointer(p1) -## from pprint import pprint as pp -## pp(p1._objects) -## pp(r._objects) - - r.a[0].x = 42 - r.a[0].y = 99 - - # to avoid leaking when tests are run several times - # clean up the types left in the cache. - from ctypes import _pointer_type_cache - del _pointer_type_cache[POINT] - -if __name__ == "__main__": - unittest.main() diff --git a/Lib/ctypes/test/test_libc.py b/Lib/ctypes/test/test_libc.py deleted file mode 100644 index 56285b5..0000000 --- a/Lib/ctypes/test/test_libc.py +++ /dev/null @@ -1,33 +0,0 @@ -import unittest - -from ctypes import * -import _ctypes_test - -lib = CDLL(_ctypes_test.__file__) - -def three_way_cmp(x, y): - """Return -1 if x < y, 0 if x == y and 1 if x > y""" - return (x > y) - (x < y) - -class LibTest(unittest.TestCase): - def test_sqrt(self): - lib.my_sqrt.argtypes = c_double, - lib.my_sqrt.restype = c_double - self.assertEqual(lib.my_sqrt(4.0), 2.0) - import math - self.assertEqual(lib.my_sqrt(2.0), math.sqrt(2.0)) - - def test_qsort(self): - comparefunc = CFUNCTYPE(c_int, POINTER(c_char), POINTER(c_char)) - lib.my_qsort.argtypes = c_void_p, c_size_t, c_size_t, comparefunc - lib.my_qsort.restype = None - - def sort(a, b): - return three_way_cmp(a[0], b[0]) - - chars = create_string_buffer(b"spam, spam, and spam") - lib.my_qsort(chars, len(chars)-1, sizeof(c_char), comparefunc(sort)) - self.assertEqual(chars.raw, b" ,,aaaadmmmnpppsss\x00") - -if __name__ == "__main__": - unittest.main() diff --git a/Lib/ctypes/test/test_loading.py b/Lib/ctypes/test/test_loading.py deleted file mode 100644 index ea89227..0000000 --- a/Lib/ctypes/test/test_loading.py +++ /dev/null @@ -1,182 +0,0 @@ -from ctypes import * -import os -import shutil -import subprocess -import sys -import unittest -import test.support -from test.support import import_helper -from test.support import os_helper -from ctypes.util import find_library - -libc_name = None - -def setUpModule(): - global libc_name - if os.name == "nt": - libc_name = find_library("c") - elif sys.platform == "cygwin": - libc_name = "cygwin1.dll" - else: - libc_name = find_library("c") - - if test.support.verbose: - print("libc_name is", libc_name) - -class LoaderTest(unittest.TestCase): - - unknowndll = "xxrandomnamexx" - - def test_load(self): - if libc_name is None: - self.skipTest('could not find libc') - CDLL(libc_name) - CDLL(os.path.basename(libc_name)) - self.assertRaises(OSError, CDLL, self.unknowndll) - - def test_load_version(self): - if libc_name is None: - self.skipTest('could not find libc') - if os.path.basename(libc_name) != 'libc.so.6': - self.skipTest('wrong libc path for test') - cdll.LoadLibrary("libc.so.6") - # linux uses version, libc 9 should not exist - self.assertRaises(OSError, cdll.LoadLibrary, "libc.so.9") - self.assertRaises(OSError, cdll.LoadLibrary, self.unknowndll) - - def test_find(self): - for name in ("c", "m"): - lib = find_library(name) - if lib: - cdll.LoadLibrary(lib) - CDLL(lib) - - @unittest.skipUnless(os.name == "nt", - 'test specific to Windows') - def test_load_library(self): - # CRT is no longer directly loadable. See issue23606 for the - # discussion about alternative approaches. - #self.assertIsNotNone(libc_name) - if test.support.verbose: - print(find_library("kernel32")) - print(find_library("user32")) - - if os.name == "nt": - windll.kernel32.GetModuleHandleW - windll["kernel32"].GetModuleHandleW - windll.LoadLibrary("kernel32").GetModuleHandleW - WinDLL("kernel32").GetModuleHandleW - # embedded null character - self.assertRaises(ValueError, windll.LoadLibrary, "kernel32\0") - - @unittest.skipUnless(os.name == "nt", - 'test specific to Windows') - def test_load_ordinal_functions(self): - import _ctypes_test - dll = WinDLL(_ctypes_test.__file__) - # We load the same function both via ordinal and name - func_ord = dll[2] - func_name = dll.GetString - # addressof gets the address where the function pointer is stored - a_ord = addressof(func_ord) - a_name = addressof(func_name) - f_ord_addr = c_void_p.from_address(a_ord).value - f_name_addr = c_void_p.from_address(a_name).value - self.assertEqual(hex(f_ord_addr), hex(f_name_addr)) - - self.assertRaises(AttributeError, dll.__getitem__, 1234) - - @unittest.skipUnless(os.name == "nt", 'Windows-specific test') - def test_1703286_A(self): - from _ctypes import LoadLibrary, FreeLibrary - # On winXP 64-bit, advapi32 loads at an address that does - # NOT fit into a 32-bit integer. FreeLibrary must be able - # to accept this address. - - # These are tests for https://www.python.org/sf/1703286 - handle = LoadLibrary("advapi32") - FreeLibrary(handle) - - @unittest.skipUnless(os.name == "nt", 'Windows-specific test') - def test_1703286_B(self): - # Since on winXP 64-bit advapi32 loads like described - # above, the (arbitrarily selected) CloseEventLog function - # also has a high address. 'call_function' should accept - # addresses so large. - from _ctypes import call_function - advapi32 = windll.advapi32 - # Calling CloseEventLog with a NULL argument should fail, - # but the call should not segfault or so. - self.assertEqual(0, advapi32.CloseEventLog(None)) - windll.kernel32.GetProcAddress.argtypes = c_void_p, c_char_p - windll.kernel32.GetProcAddress.restype = c_void_p - proc = windll.kernel32.GetProcAddress(advapi32._handle, - b"CloseEventLog") - self.assertTrue(proc) - # This is the real test: call the function via 'call_function' - self.assertEqual(0, call_function(proc, (None,))) - - @unittest.skipUnless(os.name == "nt", - 'test specific to Windows') - def test_load_dll_with_flags(self): - _sqlite3 = import_helper.import_module("_sqlite3") - src = _sqlite3.__file__ - if src.lower().endswith("_d.pyd"): - ext = "_d.dll" - else: - ext = ".dll" - - with os_helper.temp_dir() as tmp: - # We copy two files and load _sqlite3.dll (formerly .pyd), - # which has a dependency on sqlite3.dll. Then we test - # loading it in subprocesses to avoid it starting in memory - # for each test. - target = os.path.join(tmp, "_sqlite3.dll") - shutil.copy(src, target) - shutil.copy(os.path.join(os.path.dirname(src), "sqlite3" + ext), - os.path.join(tmp, "sqlite3" + ext)) - - def should_pass(command): - with self.subTest(command): - subprocess.check_output( - [sys.executable, "-c", - "from ctypes import *; import nt;" + command], - cwd=tmp - ) - - def should_fail(command): - with self.subTest(command): - with self.assertRaises(subprocess.CalledProcessError): - subprocess.check_output( - [sys.executable, "-c", - "from ctypes import *; import nt;" + command], - cwd=tmp, stderr=subprocess.STDOUT, - ) - - # Default load should not find this in CWD - should_fail("WinDLL('_sqlite3.dll')") - - # Relative path (but not just filename) should succeed - should_pass("WinDLL('./_sqlite3.dll')") - - # Insecure load flags should succeed - # Clear the DLL directory to avoid safe search settings propagating - should_pass("windll.kernel32.SetDllDirectoryW(None); WinDLL('_sqlite3.dll', winmode=0)") - - # Full path load without DLL_LOAD_DIR shouldn't find dependency - should_fail("WinDLL(nt._getfullpathname('_sqlite3.dll'), " + - "winmode=nt._LOAD_LIBRARY_SEARCH_SYSTEM32)") - - # Full path load with DLL_LOAD_DIR should succeed - should_pass("WinDLL(nt._getfullpathname('_sqlite3.dll'), " + - "winmode=nt._LOAD_LIBRARY_SEARCH_SYSTEM32|" + - "nt._LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR)") - - # User-specified directory should succeed - should_pass("import os; p = os.add_dll_directory(os.getcwd());" + - "WinDLL('_sqlite3.dll'); p.close()") - - - -if __name__ == "__main__": - unittest.main() diff --git a/Lib/ctypes/test/test_macholib.py b/Lib/ctypes/test/test_macholib.py deleted file mode 100644 index bc75f1a..0000000 --- a/Lib/ctypes/test/test_macholib.py +++ /dev/null @@ -1,110 +0,0 @@ -import os -import sys -import unittest - -# Bob Ippolito: -# -# Ok.. the code to find the filename for __getattr__ should look -# something like: -# -# import os -# from macholib.dyld import dyld_find -# -# def find_lib(name): -# possible = ['lib'+name+'.dylib', name+'.dylib', -# name+'.framework/'+name] -# for dylib in possible: -# try: -# return os.path.realpath(dyld_find(dylib)) -# except ValueError: -# pass -# raise ValueError, "%s not found" % (name,) -# -# It'll have output like this: -# -# >>> find_lib('pthread') -# '/usr/lib/libSystem.B.dylib' -# >>> find_lib('z') -# '/usr/lib/libz.1.dylib' -# >>> find_lib('IOKit') -# '/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit' -# -# -bob - -from ctypes.macholib.dyld import dyld_find -from ctypes.macholib.dylib import dylib_info -from ctypes.macholib.framework import framework_info - -def find_lib(name): - possible = ['lib'+name+'.dylib', name+'.dylib', name+'.framework/'+name] - for dylib in possible: - try: - return os.path.realpath(dyld_find(dylib)) - except ValueError: - pass - raise ValueError("%s not found" % (name,)) - - -def d(location=None, name=None, shortname=None, version=None, suffix=None): - return {'location': location, 'name': name, 'shortname': shortname, - 'version': version, 'suffix': suffix} - - -class MachOTest(unittest.TestCase): - @unittest.skipUnless(sys.platform == "darwin", 'OSX-specific test') - def test_find(self): - self.assertEqual(dyld_find('libSystem.dylib'), - '/usr/lib/libSystem.dylib') - self.assertEqual(dyld_find('System.framework/System'), - '/System/Library/Frameworks/System.framework/System') - - # On Mac OS 11, system dylibs are only present in the shared cache, - # so symlinks like libpthread.dylib -> libSystem.B.dylib will not - # be resolved by dyld_find - self.assertIn(find_lib('pthread'), - ('/usr/lib/libSystem.B.dylib', '/usr/lib/libpthread.dylib')) - - result = find_lib('z') - # Issue #21093: dyld default search path includes $HOME/lib and - # /usr/local/lib before /usr/lib, which caused test failures if - # a local copy of libz exists in one of them. Now ignore the head - # of the path. - self.assertRegex(result, r".*/lib/libz.*\.dylib") - - self.assertIn(find_lib('IOKit'), - ('/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit', - '/System/Library/Frameworks/IOKit.framework/IOKit')) - - @unittest.skipUnless(sys.platform == "darwin", 'OSX-specific test') - def test_info(self): - self.assertIsNone(dylib_info('completely/invalid')) - self.assertIsNone(dylib_info('completely/invalide_debug')) - self.assertEqual(dylib_info('P/Foo.dylib'), d('P', 'Foo.dylib', 'Foo')) - self.assertEqual(dylib_info('P/Foo_debug.dylib'), - d('P', 'Foo_debug.dylib', 'Foo', suffix='debug')) - self.assertEqual(dylib_info('P/Foo.A.dylib'), - d('P', 'Foo.A.dylib', 'Foo', 'A')) - self.assertEqual(dylib_info('P/Foo_debug.A.dylib'), - d('P', 'Foo_debug.A.dylib', 'Foo_debug', 'A')) - self.assertEqual(dylib_info('P/Foo.A_debug.dylib'), - d('P', 'Foo.A_debug.dylib', 'Foo', 'A', 'debug')) - - @unittest.skipUnless(sys.platform == "darwin", 'OSX-specific test') - def test_framework_info(self): - self.assertIsNone(framework_info('completely/invalid')) - self.assertIsNone(framework_info('completely/invalid/_debug')) - self.assertIsNone(framework_info('P/F.framework')) - self.assertIsNone(framework_info('P/F.framework/_debug')) - self.assertEqual(framework_info('P/F.framework/F'), - d('P', 'F.framework/F', 'F')) - self.assertEqual(framework_info('P/F.framework/F_debug'), - d('P', 'F.framework/F_debug', 'F', suffix='debug')) - self.assertIsNone(framework_info('P/F.framework/Versions')) - self.assertIsNone(framework_info('P/F.framework/Versions/A')) - self.assertEqual(framework_info('P/F.framework/Versions/A/F'), - d('P', 'F.framework/Versions/A/F', 'F', 'A')) - self.assertEqual(framework_info('P/F.framework/Versions/A/F_debug'), - d('P', 'F.framework/Versions/A/F_debug', 'F', 'A', 'debug')) - -if __name__ == "__main__": - unittest.main() diff --git a/Lib/ctypes/test/test_memfunctions.py b/Lib/ctypes/test/test_memfunctions.py deleted file mode 100644 index e784b9a..0000000 --- a/Lib/ctypes/test/test_memfunctions.py +++ /dev/null @@ -1,79 +0,0 @@ -import sys -from test import support -import unittest -from ctypes import * -from ctypes.test import need_symbol - -class MemFunctionsTest(unittest.TestCase): - @unittest.skip('test disabled') - def test_overflow(self): - # string_at and wstring_at must use the Python calling - # convention (which acquires the GIL and checks the Python - # error flag). Provoke an error and catch it; see also issue - # #3554: - self.assertRaises((OverflowError, MemoryError, SystemError), - lambda: wstring_at(u"foo", sys.maxint - 1)) - self.assertRaises((OverflowError, MemoryError, SystemError), - lambda: string_at("foo", sys.maxint - 1)) - - def test_memmove(self): - # large buffers apparently increase the chance that the memory - # is allocated in high address space. - a = create_string_buffer(1000000) - p = b"Hello, World" - result = memmove(a, p, len(p)) - self.assertEqual(a.value, b"Hello, World") - - self.assertEqual(string_at(result), b"Hello, World") - self.assertEqual(string_at(result, 5), b"Hello") - self.assertEqual(string_at(result, 16), b"Hello, World\0\0\0\0") - self.assertEqual(string_at(result, 0), b"") - - def test_memset(self): - a = create_string_buffer(1000000) - result = memset(a, ord('x'), 16) - self.assertEqual(a.value, b"xxxxxxxxxxxxxxxx") - - self.assertEqual(string_at(result), b"xxxxxxxxxxxxxxxx") - self.assertEqual(string_at(a), b"xxxxxxxxxxxxxxxx") - self.assertEqual(string_at(a, 20), b"xxxxxxxxxxxxxxxx\0\0\0\0") - - def test_cast(self): - a = (c_ubyte * 32)(*map(ord, "abcdef")) - self.assertEqual(cast(a, c_char_p).value, b"abcdef") - self.assertEqual(cast(a, POINTER(c_byte))[:7], - [97, 98, 99, 100, 101, 102, 0]) - self.assertEqual(cast(a, POINTER(c_byte))[:7:], - [97, 98, 99, 100, 101, 102, 0]) - self.assertEqual(cast(a, POINTER(c_byte))[6:-1:-1], - [0, 102, 101, 100, 99, 98, 97]) - self.assertEqual(cast(a, POINTER(c_byte))[:7:2], - [97, 99, 101, 0]) - self.assertEqual(cast(a, POINTER(c_byte))[:7:7], - [97]) - - @support.refcount_test - def test_string_at(self): - s = string_at(b"foo bar") - # XXX The following may be wrong, depending on how Python - # manages string instances - self.assertEqual(2, sys.getrefcount(s)) - self.assertTrue(s, "foo bar") - - self.assertEqual(string_at(b"foo bar", 7), b"foo bar") - self.assertEqual(string_at(b"foo bar", 3), b"foo") - - @need_symbol('create_unicode_buffer') - def test_wstring_at(self): - p = create_unicode_buffer("Hello, World") - a = create_unicode_buffer(1000000) - result = memmove(a, p, len(p) * sizeof(c_wchar)) - self.assertEqual(a.value, "Hello, World") - - self.assertEqual(wstring_at(a), "Hello, World") - self.assertEqual(wstring_at(a, 5), "Hello") - self.assertEqual(wstring_at(a, 16), "Hello, World\0\0\0\0") - self.assertEqual(wstring_at(a, 0), "") - -if __name__ == "__main__": - unittest.main() diff --git a/Lib/ctypes/test/test_numbers.py b/Lib/ctypes/test/test_numbers.py deleted file mode 100644 index db500e8..0000000 --- a/Lib/ctypes/test/test_numbers.py +++ /dev/null @@ -1,295 +0,0 @@ -from ctypes import * -import unittest -import struct - -def valid_ranges(*types): - # given a sequence of numeric types, collect their _type_ - # attribute, which is a single format character compatible with - # the struct module, use the struct module to calculate the - # minimum and maximum value allowed for this format. - # Returns a list of (min, max) values. - result = [] - for t in types: - fmt = t._type_ - size = struct.calcsize(fmt) - a = struct.unpack(fmt, (b"\x00"*32)[:size])[0] - b = struct.unpack(fmt, (b"\xFF"*32)[:size])[0] - c = struct.unpack(fmt, (b"\x7F"+b"\x00"*32)[:size])[0] - d = struct.unpack(fmt, (b"\x80"+b"\xFF"*32)[:size])[0] - result.append((min(a, b, c, d), max(a, b, c, d))) - return result - -ArgType = type(byref(c_int(0))) - -unsigned_types = [c_ubyte, c_ushort, c_uint, c_ulong] -signed_types = [c_byte, c_short, c_int, c_long, c_longlong] - -bool_types = [] - -float_types = [c_double, c_float] - -try: - c_ulonglong - c_longlong -except NameError: - pass -else: - unsigned_types.append(c_ulonglong) - signed_types.append(c_longlong) - -try: - c_bool -except NameError: - pass -else: - bool_types.append(c_bool) - -unsigned_ranges = valid_ranges(*unsigned_types) -signed_ranges = valid_ranges(*signed_types) -bool_values = [True, False, 0, 1, -1, 5000, 'test', [], [1]] - -################################################################ - -class NumberTestCase(unittest.TestCase): - - def test_default_init(self): - # default values are set to zero - for t in signed_types + unsigned_types + float_types: - self.assertEqual(t().value, 0) - - def test_unsigned_values(self): - # the value given to the constructor is available - # as the 'value' attribute - for t, (l, h) in zip(unsigned_types, unsigned_ranges): - self.assertEqual(t(l).value, l) - self.assertEqual(t(h).value, h) - - def test_signed_values(self): - # see above - for t, (l, h) in zip(signed_types, signed_ranges): - self.assertEqual(t(l).value, l) - self.assertEqual(t(h).value, h) - - def test_bool_values(self): - from operator import truth - for t, v in zip(bool_types, bool_values): - self.assertEqual(t(v).value, truth(v)) - - def test_typeerror(self): - # Only numbers are allowed in the constructor, - # otherwise TypeError is raised - for t in signed_types + unsigned_types + float_types: - self.assertRaises(TypeError, t, "") - self.assertRaises(TypeError, t, None) - - @unittest.skip('test disabled') - def test_valid_ranges(self): - # invalid values of the correct type - # raise ValueError (not OverflowError) - for t, (l, h) in zip(unsigned_types, unsigned_ranges): - self.assertRaises(ValueError, t, l-1) - self.assertRaises(ValueError, t, h+1) - - def test_from_param(self): - # the from_param class method attribute always - # returns PyCArgObject instances - for t in signed_types + unsigned_types + float_types: - self.assertEqual(ArgType, type(t.from_param(0))) - - def test_byref(self): - # calling byref returns also a PyCArgObject instance - for t in signed_types + unsigned_types + float_types + bool_types: - parm = byref(t()) - self.assertEqual(ArgType, type(parm)) - - - def test_floats(self): - # c_float and c_double can be created from - # Python int and float - class FloatLike(object): - def __float__(self): - return 2.0 - f = FloatLike() - for t in float_types: - self.assertEqual(t(2.0).value, 2.0) - self.assertEqual(t(2).value, 2.0) - self.assertEqual(t(2).value, 2.0) - self.assertEqual(t(f).value, 2.0) - - def test_integers(self): - class FloatLike(object): - def __float__(self): - return 2.0 - f = FloatLike() - class IntLike(object): - def __int__(self): - return 2 - d = IntLike() - class IndexLike(object): - def __index__(self): - return 2 - i = IndexLike() - # integers cannot be constructed from floats, - # but from integer-like objects - for t in signed_types + unsigned_types: - self.assertRaises(TypeError, t, 3.14) - self.assertRaises(TypeError, t, f) - self.assertRaises(TypeError, t, d) - self.assertEqual(t(i).value, 2) - - def test_sizes(self): - for t in signed_types + unsigned_types + float_types + bool_types: - try: - size = struct.calcsize(t._type_) - except struct.error: - continue - # sizeof of the type... - self.assertEqual(sizeof(t), size) - # and sizeof of an instance - self.assertEqual(sizeof(t()), size) - - def test_alignments(self): - for t in signed_types + unsigned_types + float_types: - code = t._type_ # the typecode - align = struct.calcsize("c%c" % code) - struct.calcsize(code) - - # alignment of the type... - self.assertEqual((code, alignment(t)), - (code, align)) - # and alignment of an instance - self.assertEqual((code, alignment(t())), - (code, align)) - - def test_int_from_address(self): - from array import array - for t in signed_types + unsigned_types: - # the array module doesn't support all format codes - # (no 'q' or 'Q') - try: - array(t._type_) - except ValueError: - continue - a = array(t._type_, [100]) - - # v now is an integer at an 'external' memory location - v = t.from_address(a.buffer_info()[0]) - self.assertEqual(v.value, a[0]) - self.assertEqual(type(v), t) - - # changing the value at the memory location changes v's value also - a[0] = 42 - self.assertEqual(v.value, a[0]) - - - def test_float_from_address(self): - from array import array - for t in float_types: - a = array(t._type_, [3.14]) - v = t.from_address(a.buffer_info()[0]) - self.assertEqual(v.value, a[0]) - self.assertIs(type(v), t) - a[0] = 2.3456e17 - self.assertEqual(v.value, a[0]) - self.assertIs(type(v), t) - - def test_char_from_address(self): - from ctypes import c_char - from array import array - - a = array('b', [0]) - a[0] = ord('x') - v = c_char.from_address(a.buffer_info()[0]) - self.assertEqual(v.value, b'x') - self.assertIs(type(v), c_char) - - a[0] = ord('?') - self.assertEqual(v.value, b'?') - - # array does not support c_bool / 't' - @unittest.skip('test disabled') - def test_bool_from_address(self): - from ctypes import c_bool - from array import array - a = array(c_bool._type_, [True]) - v = t.from_address(a.buffer_info()[0]) - self.assertEqual(v.value, a[0]) - self.assertEqual(type(v) is t) - a[0] = False - self.assertEqual(v.value, a[0]) - self.assertEqual(type(v) is t) - - def test_init(self): - # c_int() can be initialized from Python's int, and c_int. - # Not from c_long or so, which seems strange, abc should - # probably be changed: - self.assertRaises(TypeError, c_int, c_long(42)) - - def test_float_overflow(self): - import sys - big_int = int(sys.float_info.max) * 2 - for t in float_types + [c_longdouble]: - self.assertRaises(OverflowError, t, big_int) - if (hasattr(t, "__ctype_be__")): - self.assertRaises(OverflowError, t.__ctype_be__, big_int) - if (hasattr(t, "__ctype_le__")): - self.assertRaises(OverflowError, t.__ctype_le__, big_int) - - @unittest.skip('test disabled') - def test_perf(self): - check_perf() - -from ctypes import _SimpleCData -class c_int_S(_SimpleCData): - _type_ = "i" - __slots__ = [] - -def run_test(rep, msg, func, arg=None): -## items = [None] * rep - items = range(rep) - from time import perf_counter as clock - if arg is not None: - start = clock() - for i in items: - func(arg); func(arg); func(arg); func(arg); func(arg) - stop = clock() - else: - start = clock() - for i in items: - func(); func(); func(); func(); func() - stop = clock() - print("%15s: %.2f us" % (msg, ((stop-start)*1e6/5/rep))) - -def check_perf(): - # Construct 5 objects - from ctypes import c_int - - REP = 200000 - - run_test(REP, "int()", int) - run_test(REP, "int(999)", int) - run_test(REP, "c_int()", c_int) - run_test(REP, "c_int(999)", c_int) - run_test(REP, "c_int_S()", c_int_S) - run_test(REP, "c_int_S(999)", c_int_S) - -# Python 2.3 -OO, win2k, P4 700 MHz: -# -# int(): 0.87 us -# int(999): 0.87 us -# c_int(): 3.35 us -# c_int(999): 3.34 us -# c_int_S(): 3.23 us -# c_int_S(999): 3.24 us - -# Python 2.2 -OO, win2k, P4 700 MHz: -# -# int(): 0.89 us -# int(999): 0.89 us -# c_int(): 9.99 us -# c_int(999): 10.02 us -# c_int_S(): 9.87 us -# c_int_S(999): 9.85 us - -if __name__ == '__main__': -## check_perf() - unittest.main() diff --git a/Lib/ctypes/test/test_objects.py b/Lib/ctypes/test/test_objects.py deleted file mode 100644 index 19e3dc1..0000000 --- a/Lib/ctypes/test/test_objects.py +++ /dev/null @@ -1,67 +0,0 @@ -r''' -This tests the '_objects' attribute of ctypes instances. '_objects' -holds references to objects that must be kept alive as long as the -ctypes instance, to make sure that the memory buffer is valid. - -WARNING: The '_objects' attribute is exposed ONLY for debugging ctypes itself, -it MUST NEVER BE MODIFIED! - -'_objects' is initialized to a dictionary on first use, before that it -is None. - -Here is an array of string pointers: - ->>> from ctypes import * ->>> array = (c_char_p * 5)() ->>> print(array._objects) -None ->>> - -The memory block stores pointers to strings, and the strings itself -assigned from Python must be kept. - ->>> array[4] = b'foo bar' ->>> array._objects -{'4': b'foo bar'} ->>> array[4] -b'foo bar' ->>> - -It gets more complicated when the ctypes instance itself is contained -in a 'base' object. - ->>> class X(Structure): -... _fields_ = [("x", c_int), ("y", c_int), ("array", c_char_p * 5)] -... ->>> x = X() ->>> print(x._objects) -None ->>> - -The'array' attribute of the 'x' object shares part of the memory buffer -of 'x' ('_b_base_' is either None, or the root object owning the memory block): - ->>> print(x.array._b_base_) # doctest: +ELLIPSIS - ->>> - ->>> x.array[0] = b'spam spam spam' ->>> x._objects -{'0:2': b'spam spam spam'} ->>> x.array._b_base_._objects -{'0:2': b'spam spam spam'} ->>> - -''' - -import unittest, doctest - -import ctypes.test.test_objects - -class TestCase(unittest.TestCase): - def test(self): - failures, tests = doctest.testmod(ctypes.test.test_objects) - self.assertFalse(failures, 'doctests failed, see output above') - -if __name__ == '__main__': - doctest.testmod(ctypes.test.test_objects) diff --git a/Lib/ctypes/test/test_parameters.py b/Lib/ctypes/test/test_parameters.py deleted file mode 100644 index 38af7ac..0000000 --- a/Lib/ctypes/test/test_parameters.py +++ /dev/null @@ -1,250 +0,0 @@ -import unittest -from ctypes.test import need_symbol -import test.support - -class SimpleTypesTestCase(unittest.TestCase): - - def setUp(self): - import ctypes - try: - from _ctypes import set_conversion_mode - except ImportError: - pass - else: - self.prev_conv_mode = set_conversion_mode("ascii", "strict") - - def tearDown(self): - try: - from _ctypes import set_conversion_mode - except ImportError: - pass - else: - set_conversion_mode(*self.prev_conv_mode) - - def test_subclasses(self): - from ctypes import c_void_p, c_char_p - # ctypes 0.9.5 and before did overwrite from_param in SimpleType_new - class CVOIDP(c_void_p): - def from_param(cls, value): - return value * 2 - from_param = classmethod(from_param) - - class CCHARP(c_char_p): - def from_param(cls, value): - return value * 4 - from_param = classmethod(from_param) - - self.assertEqual(CVOIDP.from_param("abc"), "abcabc") - self.assertEqual(CCHARP.from_param("abc"), "abcabcabcabc") - - @need_symbol('c_wchar_p') - def test_subclasses_c_wchar_p(self): - from ctypes import c_wchar_p - - class CWCHARP(c_wchar_p): - def from_param(cls, value): - return value * 3 - from_param = classmethod(from_param) - - self.assertEqual(CWCHARP.from_param("abc"), "abcabcabc") - - # XXX Replace by c_char_p tests - def test_cstrings(self): - from ctypes import c_char_p - - # c_char_p.from_param on a Python String packs the string - # into a cparam object - s = b"123" - self.assertIs(c_char_p.from_param(s)._obj, s) - - # new in 0.9.1: convert (encode) unicode to ascii - self.assertEqual(c_char_p.from_param(b"123")._obj, b"123") - self.assertRaises(TypeError, c_char_p.from_param, "123\377") - self.assertRaises(TypeError, c_char_p.from_param, 42) - - # calling c_char_p.from_param with a c_char_p instance - # returns the argument itself: - a = c_char_p(b"123") - self.assertIs(c_char_p.from_param(a), a) - - @need_symbol('c_wchar_p') - def test_cw_strings(self): - from ctypes import c_wchar_p - - c_wchar_p.from_param("123") - - self.assertRaises(TypeError, c_wchar_p.from_param, 42) - self.assertRaises(TypeError, c_wchar_p.from_param, b"123\377") - - pa = c_wchar_p.from_param(c_wchar_p("123")) - self.assertEqual(type(pa), c_wchar_p) - - def test_int_pointers(self): - from ctypes import c_short, c_uint, c_int, c_long, POINTER, pointer - LPINT = POINTER(c_int) - -## p = pointer(c_int(42)) -## x = LPINT.from_param(p) - x = LPINT.from_param(pointer(c_int(42))) - self.assertEqual(x.contents.value, 42) - self.assertEqual(LPINT(c_int(42)).contents.value, 42) - - self.assertEqual(LPINT.from_param(None), None) - - if c_int != c_long: - self.assertRaises(TypeError, LPINT.from_param, pointer(c_long(42))) - self.assertRaises(TypeError, LPINT.from_param, pointer(c_uint(42))) - self.assertRaises(TypeError, LPINT.from_param, pointer(c_short(42))) - - def test_byref_pointer(self): - # The from_param class method of POINTER(typ) classes accepts what is - # returned by byref(obj), it type(obj) == typ - from ctypes import c_short, c_uint, c_int, c_long, POINTER, byref - LPINT = POINTER(c_int) - - LPINT.from_param(byref(c_int(42))) - - self.assertRaises(TypeError, LPINT.from_param, byref(c_short(22))) - if c_int != c_long: - self.assertRaises(TypeError, LPINT.from_param, byref(c_long(22))) - self.assertRaises(TypeError, LPINT.from_param, byref(c_uint(22))) - - def test_byref_pointerpointer(self): - # See above - from ctypes import c_short, c_uint, c_int, c_long, pointer, POINTER, byref - - LPLPINT = POINTER(POINTER(c_int)) - LPLPINT.from_param(byref(pointer(c_int(42)))) - - self.assertRaises(TypeError, LPLPINT.from_param, byref(pointer(c_short(22)))) - if c_int != c_long: - self.assertRaises(TypeError, LPLPINT.from_param, byref(pointer(c_long(22)))) - self.assertRaises(TypeError, LPLPINT.from_param, byref(pointer(c_uint(22)))) - - def test_array_pointers(self): - from ctypes import c_short, c_uint, c_int, c_long, POINTER - INTARRAY = c_int * 3 - ia = INTARRAY() - self.assertEqual(len(ia), 3) - self.assertEqual([ia[i] for i in range(3)], [0, 0, 0]) - - # Pointers are only compatible with arrays containing items of - # the same type! - LPINT = POINTER(c_int) - LPINT.from_param((c_int*3)()) - self.assertRaises(TypeError, LPINT.from_param, c_short*3) - self.assertRaises(TypeError, LPINT.from_param, c_long*3) - self.assertRaises(TypeError, LPINT.from_param, c_uint*3) - - def test_noctypes_argtype(self): - import _ctypes_test - from ctypes import CDLL, c_void_p, ArgumentError - - func = CDLL(_ctypes_test.__file__)._testfunc_p_p - func.restype = c_void_p - # TypeError: has no from_param method - self.assertRaises(TypeError, setattr, func, "argtypes", (object,)) - - class Adapter(object): - def from_param(cls, obj): - return None - - func.argtypes = (Adapter(),) - self.assertEqual(func(None), None) - self.assertEqual(func(object()), None) - - class Adapter(object): - def from_param(cls, obj): - return obj - - func.argtypes = (Adapter(),) - # don't know how to convert parameter 1 - self.assertRaises(ArgumentError, func, object()) - self.assertEqual(func(c_void_p(42)), 42) - - class Adapter(object): - def from_param(cls, obj): - raise ValueError(obj) - - func.argtypes = (Adapter(),) - # ArgumentError: argument 1: ValueError: 99 - self.assertRaises(ArgumentError, func, 99) - - def test_abstract(self): - from ctypes import (Array, Structure, Union, _Pointer, - _SimpleCData, _CFuncPtr) - - self.assertRaises(TypeError, Array.from_param, 42) - self.assertRaises(TypeError, Structure.from_param, 42) - self.assertRaises(TypeError, Union.from_param, 42) - self.assertRaises(TypeError, _CFuncPtr.from_param, 42) - self.assertRaises(TypeError, _Pointer.from_param, 42) - self.assertRaises(TypeError, _SimpleCData.from_param, 42) - - @test.support.cpython_only - def test_issue31311(self): - # __setstate__ should neither raise a SystemError nor crash in case - # of a bad __dict__. - from ctypes import Structure - - class BadStruct(Structure): - @property - def __dict__(self): - pass - with self.assertRaises(TypeError): - BadStruct().__setstate__({}, b'foo') - - class WorseStruct(Structure): - @property - def __dict__(self): - 1/0 - with self.assertRaises(ZeroDivisionError): - WorseStruct().__setstate__({}, b'foo') - - def test_parameter_repr(self): - from ctypes import ( - c_bool, - c_char, - c_wchar, - c_byte, - c_ubyte, - c_short, - c_ushort, - c_int, - c_uint, - c_long, - c_ulong, - c_longlong, - c_ulonglong, - c_float, - c_double, - c_longdouble, - c_char_p, - c_wchar_p, - c_void_p, - ) - self.assertRegex(repr(c_bool.from_param(True)), r"^$") - self.assertEqual(repr(c_char.from_param(97)), "") - self.assertRegex(repr(c_wchar.from_param('a')), r"^$") - self.assertEqual(repr(c_byte.from_param(98)), "") - self.assertEqual(repr(c_ubyte.from_param(98)), "") - self.assertEqual(repr(c_short.from_param(511)), "") - self.assertEqual(repr(c_ushort.from_param(511)), "") - self.assertRegex(repr(c_int.from_param(20000)), r"^$") - self.assertRegex(repr(c_uint.from_param(20000)), r"^$") - self.assertRegex(repr(c_long.from_param(20000)), r"^$") - self.assertRegex(repr(c_ulong.from_param(20000)), r"^$") - self.assertRegex(repr(c_longlong.from_param(20000)), r"^$") - self.assertRegex(repr(c_ulonglong.from_param(20000)), r"^$") - self.assertEqual(repr(c_float.from_param(1.5)), "") - self.assertEqual(repr(c_double.from_param(1.5)), "") - self.assertEqual(repr(c_double.from_param(1e300)), "") - self.assertRegex(repr(c_longdouble.from_param(1.5)), r"^$") - self.assertRegex(repr(c_char_p.from_param(b'hihi')), r"^$") - self.assertRegex(repr(c_wchar_p.from_param('hihi')), r"^$") - self.assertRegex(repr(c_void_p.from_param(0x12)), r"^$") - -################################################################ - -if __name__ == '__main__': - unittest.main() diff --git a/Lib/ctypes/test/test_pep3118.py b/Lib/ctypes/test/test_pep3118.py deleted file mode 100644 index 81e8ca7..0000000 --- a/Lib/ctypes/test/test_pep3118.py +++ /dev/null @@ -1,233 +0,0 @@ -import unittest -from ctypes import * -import re, sys - -if sys.byteorder == "little": - THIS_ENDIAN = "<" - OTHER_ENDIAN = ">" -else: - THIS_ENDIAN = ">" - OTHER_ENDIAN = "<" - -def normalize(format): - # Remove current endian specifier and white space from a format - # string - if format is None: - return "" - format = format.replace(OTHER_ENDIAN, THIS_ENDIAN) - return re.sub(r"\s", "", format) - -class Test(unittest.TestCase): - - def test_native_types(self): - for tp, fmt, shape, itemtp in native_types: - ob = tp() - v = memoryview(ob) - try: - self.assertEqual(normalize(v.format), normalize(fmt)) - if shape: - self.assertEqual(len(v), shape[0]) - else: - self.assertEqual(len(v) * sizeof(itemtp), sizeof(ob)) - self.assertEqual(v.itemsize, sizeof(itemtp)) - self.assertEqual(v.shape, shape) - # XXX Issue #12851: PyCData_NewGetBuffer() must provide strides - # if requested. memoryview currently reconstructs missing - # stride information, so this assert will fail. - # self.assertEqual(v.strides, ()) - - # they are always read/write - self.assertFalse(v.readonly) - - if v.shape: - n = 1 - for dim in v.shape: - n = n * dim - self.assertEqual(n * v.itemsize, len(v.tobytes())) - except: - # so that we can see the failing type - print(tp) - raise - - def test_endian_types(self): - for tp, fmt, shape, itemtp in endian_types: - ob = tp() - v = memoryview(ob) - try: - self.assertEqual(v.format, fmt) - if shape: - self.assertEqual(len(v), shape[0]) - else: - self.assertEqual(len(v) * sizeof(itemtp), sizeof(ob)) - self.assertEqual(v.itemsize, sizeof(itemtp)) - self.assertEqual(v.shape, shape) - # XXX Issue #12851 - # self.assertEqual(v.strides, ()) - - # they are always read/write - self.assertFalse(v.readonly) - - if v.shape: - n = 1 - for dim in v.shape: - n = n * dim - self.assertEqual(n, len(v)) - except: - # so that we can see the failing type - print(tp) - raise - -# define some structure classes - -class Point(Structure): - _fields_ = [("x", c_long), ("y", c_long)] - -class PackedPoint(Structure): - _pack_ = 2 - _fields_ = [("x", c_long), ("y", c_long)] - -class Point2(Structure): - pass -Point2._fields_ = [("x", c_long), ("y", c_long)] - -class EmptyStruct(Structure): - _fields_ = [] - -class aUnion(Union): - _fields_ = [("a", c_int)] - -class StructWithArrays(Structure): - _fields_ = [("x", c_long * 3 * 2), ("y", Point * 4)] - -class Incomplete(Structure): - pass - -class Complete(Structure): - pass -PComplete = POINTER(Complete) -Complete._fields_ = [("a", c_long)] - -################################################################ -# -# This table contains format strings as they look on little endian -# machines. The test replaces '<' with '>' on big endian machines. -# - -# Platform-specific type codes -s_bool = {1: '?', 2: 'H', 4: 'L', 8: 'Q'}[sizeof(c_bool)] -s_short = {2: 'h', 4: 'l', 8: 'q'}[sizeof(c_short)] -s_ushort = {2: 'H', 4: 'L', 8: 'Q'}[sizeof(c_ushort)] -s_int = {2: 'h', 4: 'i', 8: 'q'}[sizeof(c_int)] -s_uint = {2: 'H', 4: 'I', 8: 'Q'}[sizeof(c_uint)] -s_long = {4: 'l', 8: 'q'}[sizeof(c_long)] -s_ulong = {4: 'L', 8: 'Q'}[sizeof(c_ulong)] -s_longlong = "q" -s_ulonglong = "Q" -s_float = "f" -s_double = "d" -s_longdouble = "g" - -# Alias definitions in ctypes/__init__.py -if c_int is c_long: - s_int = s_long -if c_uint is c_ulong: - s_uint = s_ulong -if c_longlong is c_long: - s_longlong = s_long -if c_ulonglong is c_ulong: - s_ulonglong = s_ulong -if c_longdouble is c_double: - s_longdouble = s_double - - -native_types = [ - # type format shape calc itemsize - - ## simple types - - (c_char, "l:x:>l:y:}".replace('l', s_long), (), BEPoint), - (LEPoint, "T{l:x:>l:y:}".replace('l', s_long), (), POINTER(BEPoint)), - (POINTER(LEPoint), "&T{= 0: - return a - # View the bits in `a` as unsigned instead. - import struct - num_bits = struct.calcsize("P") * 8 # num bits in native machine address - a += 1 << num_bits - assert a >= 0 - return a - -def c_wbuffer(init): - n = len(init) + 1 - return (c_wchar * n)(*init) - -class CharPointersTestCase(unittest.TestCase): - - def setUp(self): - func = testdll._testfunc_p_p - func.restype = c_long - func.argtypes = None - - def test_paramflags(self): - # function returns c_void_p result, - # and has a required parameter named 'input' - prototype = CFUNCTYPE(c_void_p, c_void_p) - func = prototype(("_testfunc_p_p", testdll), - ((1, "input"),)) - - try: - func() - except TypeError as details: - self.assertEqual(str(details), "required argument 'input' missing") - else: - self.fail("TypeError not raised") - - self.assertEqual(func(None), None) - self.assertEqual(func(input=None), None) - - - def test_int_pointer_arg(self): - func = testdll._testfunc_p_p - if sizeof(c_longlong) == sizeof(c_void_p): - func.restype = c_longlong - else: - func.restype = c_long - self.assertEqual(0, func(0)) - - ci = c_int(0) - - func.argtypes = POINTER(c_int), - self.assertEqual(positive_address(addressof(ci)), - positive_address(func(byref(ci)))) - - func.argtypes = c_char_p, - self.assertRaises(ArgumentError, func, byref(ci)) - - func.argtypes = POINTER(c_short), - self.assertRaises(ArgumentError, func, byref(ci)) - - func.argtypes = POINTER(c_double), - self.assertRaises(ArgumentError, func, byref(ci)) - - def test_POINTER_c_char_arg(self): - func = testdll._testfunc_p_p - func.restype = c_char_p - func.argtypes = POINTER(c_char), - - self.assertEqual(None, func(None)) - self.assertEqual(b"123", func(b"123")) - self.assertEqual(None, func(c_char_p(None))) - self.assertEqual(b"123", func(c_char_p(b"123"))) - - self.assertEqual(b"123", func(c_buffer(b"123"))) - ca = c_char(b"a") - self.assertEqual(ord(b"a"), func(pointer(ca))[0]) - self.assertEqual(ord(b"a"), func(byref(ca))[0]) - - def test_c_char_p_arg(self): - func = testdll._testfunc_p_p - func.restype = c_char_p - func.argtypes = c_char_p, - - self.assertEqual(None, func(None)) - self.assertEqual(b"123", func(b"123")) - self.assertEqual(None, func(c_char_p(None))) - self.assertEqual(b"123", func(c_char_p(b"123"))) - - self.assertEqual(b"123", func(c_buffer(b"123"))) - ca = c_char(b"a") - self.assertEqual(ord(b"a"), func(pointer(ca))[0]) - self.assertEqual(ord(b"a"), func(byref(ca))[0]) - - def test_c_void_p_arg(self): - func = testdll._testfunc_p_p - func.restype = c_char_p - func.argtypes = c_void_p, - - self.assertEqual(None, func(None)) - self.assertEqual(b"123", func(b"123")) - self.assertEqual(b"123", func(c_char_p(b"123"))) - self.assertEqual(None, func(c_char_p(None))) - - self.assertEqual(b"123", func(c_buffer(b"123"))) - ca = c_char(b"a") - self.assertEqual(ord(b"a"), func(pointer(ca))[0]) - self.assertEqual(ord(b"a"), func(byref(ca))[0]) - - func(byref(c_int())) - func(pointer(c_int())) - func((c_int * 3)()) - - @need_symbol('c_wchar_p') - def test_c_void_p_arg_with_c_wchar_p(self): - func = testdll._testfunc_p_p - func.restype = c_wchar_p - func.argtypes = c_void_p, - - self.assertEqual(None, func(c_wchar_p(None))) - self.assertEqual("123", func(c_wchar_p("123"))) - - def test_instance(self): - func = testdll._testfunc_p_p - func.restype = c_void_p - - class X: - _as_parameter_ = None - - func.argtypes = c_void_p, - self.assertEqual(None, func(X())) - - func.argtypes = None - self.assertEqual(None, func(X())) - -@need_symbol('c_wchar') -class WCharPointersTestCase(unittest.TestCase): - - def setUp(self): - func = testdll._testfunc_p_p - func.restype = c_int - func.argtypes = None - - - def test_POINTER_c_wchar_arg(self): - func = testdll._testfunc_p_p - func.restype = c_wchar_p - func.argtypes = POINTER(c_wchar), - - self.assertEqual(None, func(None)) - self.assertEqual("123", func("123")) - self.assertEqual(None, func(c_wchar_p(None))) - self.assertEqual("123", func(c_wchar_p("123"))) - - self.assertEqual("123", func(c_wbuffer("123"))) - ca = c_wchar("a") - self.assertEqual("a", func(pointer(ca))[0]) - self.assertEqual("a", func(byref(ca))[0]) - - def test_c_wchar_p_arg(self): - func = testdll._testfunc_p_p - func.restype = c_wchar_p - func.argtypes = c_wchar_p, - - c_wchar_p.from_param("123") - - self.assertEqual(None, func(None)) - self.assertEqual("123", func("123")) - self.assertEqual(None, func(c_wchar_p(None))) - self.assertEqual("123", func(c_wchar_p("123"))) - - # XXX Currently, these raise TypeErrors, although they shouldn't: - self.assertEqual("123", func(c_wbuffer("123"))) - ca = c_wchar("a") - self.assertEqual("a", func(pointer(ca))[0]) - self.assertEqual("a", func(byref(ca))[0]) - -class ArrayTest(unittest.TestCase): - def test(self): - func = testdll._testfunc_ai8 - func.restype = POINTER(c_int) - func.argtypes = c_int * 8, - - func((c_int * 8)(1, 2, 3, 4, 5, 6, 7, 8)) - - # This did crash before: - - def func(): pass - CFUNCTYPE(None, c_int * 3)(func) - -################################################################ - -if __name__ == '__main__': - unittest.main() diff --git a/Lib/ctypes/test/test_python_api.py b/Lib/ctypes/test/test_python_api.py deleted file mode 100644 index 49571f9..0000000 --- a/Lib/ctypes/test/test_python_api.py +++ /dev/null @@ -1,85 +0,0 @@ -from ctypes import * -import unittest -from test import support - -################################################################ -# This section should be moved into ctypes\__init__.py, when it's ready. - -from _ctypes import PyObj_FromPtr - -################################################################ - -from sys import getrefcount as grc - -class PythonAPITestCase(unittest.TestCase): - - def test_PyBytes_FromStringAndSize(self): - PyBytes_FromStringAndSize = pythonapi.PyBytes_FromStringAndSize - - PyBytes_FromStringAndSize.restype = py_object - PyBytes_FromStringAndSize.argtypes = c_char_p, c_size_t - - self.assertEqual(PyBytes_FromStringAndSize(b"abcdefghi", 3), b"abc") - - @support.refcount_test - def test_PyString_FromString(self): - pythonapi.PyBytes_FromString.restype = py_object - pythonapi.PyBytes_FromString.argtypes = (c_char_p,) - - s = b"abc" - refcnt = grc(s) - pyob = pythonapi.PyBytes_FromString(s) - self.assertEqual(grc(s), refcnt) - self.assertEqual(s, pyob) - del pyob - self.assertEqual(grc(s), refcnt) - - @support.refcount_test - def test_PyLong_Long(self): - ref42 = grc(42) - pythonapi.PyLong_FromLong.restype = py_object - self.assertEqual(pythonapi.PyLong_FromLong(42), 42) - - self.assertEqual(grc(42), ref42) - - pythonapi.PyLong_AsLong.argtypes = (py_object,) - pythonapi.PyLong_AsLong.restype = c_long - - res = pythonapi.PyLong_AsLong(42) - self.assertEqual(grc(res), ref42 + 1) - del res - self.assertEqual(grc(42), ref42) - - @support.refcount_test - def test_PyObj_FromPtr(self): - s = "abc def ghi jkl" - ref = grc(s) - # id(python-object) is the address - pyobj = PyObj_FromPtr(id(s)) - self.assertIs(s, pyobj) - - self.assertEqual(grc(s), ref + 1) - del pyobj - self.assertEqual(grc(s), ref) - - def test_PyOS_snprintf(self): - PyOS_snprintf = pythonapi.PyOS_snprintf - PyOS_snprintf.argtypes = POINTER(c_char), c_size_t, c_char_p - - buf = c_buffer(256) - PyOS_snprintf(buf, sizeof(buf), b"Hello from %s", b"ctypes") - self.assertEqual(buf.value, b"Hello from ctypes") - - PyOS_snprintf(buf, sizeof(buf), b"Hello from %s (%d, %d, %d)", b"ctypes", 1, 2, 3) - self.assertEqual(buf.value, b"Hello from ctypes (1, 2, 3)") - - # not enough arguments - self.assertRaises(TypeError, PyOS_snprintf, buf) - - def test_pyobject_repr(self): - self.assertEqual(repr(py_object()), "py_object()") - self.assertEqual(repr(py_object(42)), "py_object(42)") - self.assertEqual(repr(py_object(object)), "py_object(%r)" % object) - -if __name__ == "__main__": - unittest.main() diff --git a/Lib/ctypes/test/test_random_things.py b/Lib/ctypes/test/test_random_things.py deleted file mode 100644 index 2988e27..0000000 --- a/Lib/ctypes/test/test_random_things.py +++ /dev/null @@ -1,77 +0,0 @@ -from ctypes import * -import contextlib -from test import support -import unittest -import sys - - -def callback_func(arg): - 42 / arg - raise ValueError(arg) - -@unittest.skipUnless(sys.platform == "win32", 'Windows-specific test') -class call_function_TestCase(unittest.TestCase): - # _ctypes.call_function is deprecated and private, but used by - # Gary Bishp's readline module. If we have it, we must test it as well. - - def test(self): - from _ctypes import call_function - windll.kernel32.LoadLibraryA.restype = c_void_p - windll.kernel32.GetProcAddress.argtypes = c_void_p, c_char_p - windll.kernel32.GetProcAddress.restype = c_void_p - - hdll = windll.kernel32.LoadLibraryA(b"kernel32") - funcaddr = windll.kernel32.GetProcAddress(hdll, b"GetModuleHandleA") - - self.assertEqual(call_function(funcaddr, (None,)), - windll.kernel32.GetModuleHandleA(None)) - -class CallbackTracbackTestCase(unittest.TestCase): - # When an exception is raised in a ctypes callback function, the C - # code prints a traceback. - # - # This test makes sure the exception types *and* the exception - # value is printed correctly. - # - # Changed in 0.9.3: No longer is '(in callback)' prepended to the - # error message - instead an additional frame for the C code is - # created, then a full traceback printed. When SystemExit is - # raised in a callback function, the interpreter exits. - - @contextlib.contextmanager - def expect_unraisable(self, exc_type, exc_msg=None): - with support.catch_unraisable_exception() as cm: - yield - - self.assertIsInstance(cm.unraisable.exc_value, exc_type) - if exc_msg is not None: - self.assertEqual(str(cm.unraisable.exc_value), exc_msg) - self.assertEqual(cm.unraisable.err_msg, - "Exception ignored on calling ctypes " - "callback function") - self.assertIs(cm.unraisable.object, callback_func) - - def test_ValueError(self): - cb = CFUNCTYPE(c_int, c_int)(callback_func) - with self.expect_unraisable(ValueError, '42'): - cb(42) - - def test_IntegerDivisionError(self): - cb = CFUNCTYPE(c_int, c_int)(callback_func) - with self.expect_unraisable(ZeroDivisionError): - cb(0) - - def test_FloatDivisionError(self): - cb = CFUNCTYPE(c_int, c_double)(callback_func) - with self.expect_unraisable(ZeroDivisionError): - cb(0.0) - - def test_TypeErrorDivisionError(self): - cb = CFUNCTYPE(c_int, c_char_p)(callback_func) - err_msg = "unsupported operand type(s) for /: 'int' and 'bytes'" - with self.expect_unraisable(TypeError, err_msg): - cb(b"spam") - - -if __name__ == '__main__': - unittest.main() diff --git a/Lib/ctypes/test/test_refcounts.py b/Lib/ctypes/test/test_refcounts.py deleted file mode 100644 index f2edfa6..0000000 --- a/Lib/ctypes/test/test_refcounts.py +++ /dev/null @@ -1,101 +0,0 @@ -import unittest -from test import support -import ctypes -import gc - -MyCallback = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_int) -OtherCallback = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_int, ctypes.c_ulonglong) - -import _ctypes_test -dll = ctypes.CDLL(_ctypes_test.__file__) - -class RefcountTestCase(unittest.TestCase): - - @support.refcount_test - def test_1(self): - from sys import getrefcount as grc - - f = dll._testfunc_callback_i_if - f.restype = ctypes.c_int - f.argtypes = [ctypes.c_int, MyCallback] - - def callback(value): - #print "called back with", value - return value - - self.assertEqual(grc(callback), 2) - cb = MyCallback(callback) - - self.assertGreater(grc(callback), 2) - result = f(-10, cb) - self.assertEqual(result, -18) - cb = None - - gc.collect() - - self.assertEqual(grc(callback), 2) - - - @support.refcount_test - def test_refcount(self): - from sys import getrefcount as grc - def func(*args): - pass - # this is the standard refcount for func - self.assertEqual(grc(func), 2) - - # the CFuncPtr instance holds at least one refcount on func: - f = OtherCallback(func) - self.assertGreater(grc(func), 2) - - # and may release it again - del f - self.assertGreaterEqual(grc(func), 2) - - # but now it must be gone - gc.collect() - self.assertEqual(grc(func), 2) - - class X(ctypes.Structure): - _fields_ = [("a", OtherCallback)] - x = X() - x.a = OtherCallback(func) - - # the CFuncPtr instance holds at least one refcount on func: - self.assertGreater(grc(func), 2) - - # and may release it again - del x - self.assertGreaterEqual(grc(func), 2) - - # and now it must be gone again - gc.collect() - self.assertEqual(grc(func), 2) - - f = OtherCallback(func) - - # the CFuncPtr instance holds at least one refcount on func: - self.assertGreater(grc(func), 2) - - # create a cycle - f.cycle = f - - del f - gc.collect() - self.assertEqual(grc(func), 2) - -class AnotherLeak(unittest.TestCase): - def test_callback(self): - import sys - - proto = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_int, ctypes.c_int) - def func(a, b): - return a * b * 2 - f = proto(func) - - a = sys.getrefcount(ctypes.c_int) - f(1, 2) - self.assertEqual(sys.getrefcount(ctypes.c_int), a) - -if __name__ == '__main__': - unittest.main() diff --git a/Lib/ctypes/test/test_repr.py b/Lib/ctypes/test/test_repr.py deleted file mode 100644 index 60a2c80..0000000 --- a/Lib/ctypes/test/test_repr.py +++ /dev/null @@ -1,29 +0,0 @@ -from ctypes import * -import unittest - -subclasses = [] -for base in [c_byte, c_short, c_int, c_long, c_longlong, - c_ubyte, c_ushort, c_uint, c_ulong, c_ulonglong, - c_float, c_double, c_longdouble, c_bool]: - class X(base): - pass - subclasses.append(X) - -class X(c_char): - pass - -# This test checks if the __repr__ is correct for subclasses of simple types - -class ReprTest(unittest.TestCase): - def test_numbers(self): - for typ in subclasses: - base = typ.__bases__[0] - self.assertTrue(repr(base(42)).startswith(base.__name__)) - self.assertEqual(": " - "expected bytes, int found") - - cls, msg = self.get_except(Person, b"Someone", (b"a", b"b", b"c")) - self.assertEqual(cls, RuntimeError) - self.assertEqual(msg, - "(Phone) : too many initializers") - - def test_huge_field_name(self): - # issue12881: segfault with large structure field names - def create_class(length): - class S(Structure): - _fields_ = [('x' * length, c_int)] - - for length in [10 ** i for i in range(0, 8)]: - try: - create_class(length) - except MemoryError: - # MemoryErrors are OK, we just don't want to segfault - pass - - def get_except(self, func, *args): - try: - func(*args) - except Exception as detail: - return detail.__class__, str(detail) - - @unittest.skip('test disabled') - def test_subclass_creation(self): - meta = type(Structure) - # same as 'class X(Structure): pass' - # fails, since we need either a _fields_ or a _abstract_ attribute - cls, msg = self.get_except(meta, "X", (Structure,), {}) - self.assertEqual((cls, msg), - (AttributeError, "class must define a '_fields_' attribute")) - - def test_abstract_class(self): - class X(Structure): - _abstract_ = "something" - # try 'X()' - cls, msg = self.get_except(eval, "X()", locals()) - self.assertEqual((cls, msg), (TypeError, "abstract class")) - - def test_methods(self): -## class X(Structure): -## _fields_ = [] - - self.assertIn("in_dll", dir(type(Structure))) - self.assertIn("from_address", dir(type(Structure))) - self.assertIn("in_dll", dir(type(Structure))) - - def test_positional_args(self): - # see also http://bugs.python.org/issue5042 - class W(Structure): - _fields_ = [("a", c_int), ("b", c_int)] - class X(W): - _fields_ = [("c", c_int)] - class Y(X): - pass - class Z(Y): - _fields_ = [("d", c_int), ("e", c_int), ("f", c_int)] - - z = Z(1, 2, 3, 4, 5, 6) - self.assertEqual((z.a, z.b, z.c, z.d, z.e, z.f), - (1, 2, 3, 4, 5, 6)) - z = Z(1) - self.assertEqual((z.a, z.b, z.c, z.d, z.e, z.f), - (1, 0, 0, 0, 0, 0)) - self.assertRaises(TypeError, lambda: Z(1, 2, 3, 4, 5, 6, 7)) - - def test_pass_by_value(self): - # This should mirror the Test structure - # in Modules/_ctypes/_ctypes_test.c - class Test(Structure): - _fields_ = [ - ('first', c_ulong), - ('second', c_ulong), - ('third', c_ulong), - ] - - s = Test() - s.first = 0xdeadbeef - s.second = 0xcafebabe - s.third = 0x0bad1dea - dll = CDLL(_ctypes_test.__file__) - func = dll._testfunc_large_struct_update_value - func.argtypes = (Test,) - func.restype = None - func(s) - self.assertEqual(s.first, 0xdeadbeef) - self.assertEqual(s.second, 0xcafebabe) - self.assertEqual(s.third, 0x0bad1dea) - - def test_pass_by_value_finalizer(self): - # bpo-37140: Similar to test_pass_by_value(), but the Python structure - # has a finalizer (__del__() method): the finalizer must only be called - # once. - - finalizer_calls = [] - - class Test(Structure): - _fields_ = [ - ('first', c_ulong), - ('second', c_ulong), - ('third', c_ulong), - ] - def __del__(self): - finalizer_calls.append("called") - - s = Test(1, 2, 3) - # Test the StructUnionType_paramfunc() code path which copies the - # structure: if the structure is larger than sizeof(void*). - self.assertGreater(sizeof(s), sizeof(c_void_p)) - - dll = CDLL(_ctypes_test.__file__) - func = dll._testfunc_large_struct_update_value - func.argtypes = (Test,) - func.restype = None - func(s) - # bpo-37140: Passing the structure by reference must not call - # its finalizer! - self.assertEqual(finalizer_calls, []) - self.assertEqual(s.first, 1) - self.assertEqual(s.second, 2) - self.assertEqual(s.third, 3) - - # The finalizer must be called exactly once - s = None - support.gc_collect() - self.assertEqual(finalizer_calls, ["called"]) - - def test_pass_by_value_in_register(self): - class X(Structure): - _fields_ = [ - ('first', c_uint), - ('second', c_uint) - ] - - s = X() - s.first = 0xdeadbeef - s.second = 0xcafebabe - dll = CDLL(_ctypes_test.__file__) - func = dll._testfunc_reg_struct_update_value - func.argtypes = (X,) - func.restype = None - func(s) - self.assertEqual(s.first, 0xdeadbeef) - self.assertEqual(s.second, 0xcafebabe) - got = X.in_dll(dll, "last_tfrsuv_arg") - self.assertEqual(s.first, got.first) - self.assertEqual(s.second, got.second) - - def test_array_in_struct(self): - # See bpo-22273 - - # These should mirror the structures in Modules/_ctypes/_ctypes_test.c - class Test2(Structure): - _fields_ = [ - ('data', c_ubyte * 16), - ] - - class Test3(Structure): - _fields_ = [ - ('data', c_double * 2), - ] - - class Test3A(Structure): - _fields_ = [ - ('data', c_float * 2), - ] - - class Test3B(Test3A): - _fields_ = [ - ('more_data', c_float * 2), - ] - - s = Test2() - expected = 0 - for i in range(16): - s.data[i] = i - expected += i - dll = CDLL(_ctypes_test.__file__) - func = dll._testfunc_array_in_struct1 - func.restype = c_int - func.argtypes = (Test2,) - result = func(s) - self.assertEqual(result, expected) - # check the passed-in struct hasn't changed - for i in range(16): - self.assertEqual(s.data[i], i) - - s = Test3() - s.data[0] = 3.14159 - s.data[1] = 2.71828 - expected = 3.14159 + 2.71828 - func = dll._testfunc_array_in_struct2 - func.restype = c_double - func.argtypes = (Test3,) - result = func(s) - self.assertEqual(result, expected) - # check the passed-in struct hasn't changed - self.assertEqual(s.data[0], 3.14159) - self.assertEqual(s.data[1], 2.71828) - - s = Test3B() - s.data[0] = 3.14159 - s.data[1] = 2.71828 - s.more_data[0] = -3.0 - s.more_data[1] = -2.0 - - expected = 3.14159 + 2.71828 - 5.0 - func = dll._testfunc_array_in_struct2a - func.restype = c_double - func.argtypes = (Test3B,) - result = func(s) - self.assertAlmostEqual(result, expected, places=6) - # check the passed-in struct hasn't changed - self.assertAlmostEqual(s.data[0], 3.14159, places=6) - self.assertAlmostEqual(s.data[1], 2.71828, places=6) - self.assertAlmostEqual(s.more_data[0], -3.0, places=6) - self.assertAlmostEqual(s.more_data[1], -2.0, places=6) - - def test_38368(self): - class U(Union): - _fields_ = [ - ('f1', c_uint8 * 16), - ('f2', c_uint16 * 8), - ('f3', c_uint32 * 4), - ] - u = U() - u.f3[0] = 0x01234567 - u.f3[1] = 0x89ABCDEF - u.f3[2] = 0x76543210 - u.f3[3] = 0xFEDCBA98 - f1 = [u.f1[i] for i in range(16)] - f2 = [u.f2[i] for i in range(8)] - if sys.byteorder == 'little': - self.assertEqual(f1, [0x67, 0x45, 0x23, 0x01, - 0xef, 0xcd, 0xab, 0x89, - 0x10, 0x32, 0x54, 0x76, - 0x98, 0xba, 0xdc, 0xfe]) - self.assertEqual(f2, [0x4567, 0x0123, 0xcdef, 0x89ab, - 0x3210, 0x7654, 0xba98, 0xfedc]) - - @unittest.skipIf(True, 'Test disabled for now - see bpo-16575/bpo-16576') - def test_union_by_value(self): - # See bpo-16575 - - # These should mirror the structures in Modules/_ctypes/_ctypes_test.c - - class Nested1(Structure): - _fields_ = [ - ('an_int', c_int), - ('another_int', c_int), - ] - - class Test4(Union): - _fields_ = [ - ('a_long', c_long), - ('a_struct', Nested1), - ] - - class Nested2(Structure): - _fields_ = [ - ('an_int', c_int), - ('a_union', Test4), - ] - - class Test5(Structure): - _fields_ = [ - ('an_int', c_int), - ('nested', Nested2), - ('another_int', c_int), - ] - - test4 = Test4() - dll = CDLL(_ctypes_test.__file__) - with self.assertRaises(TypeError) as ctx: - func = dll._testfunc_union_by_value1 - func.restype = c_long - func.argtypes = (Test4,) - result = func(test4) - self.assertEqual(ctx.exception.args[0], 'item 1 in _argtypes_ passes ' - 'a union by value, which is unsupported.') - test5 = Test5() - with self.assertRaises(TypeError) as ctx: - func = dll._testfunc_union_by_value2 - func.restype = c_long - func.argtypes = (Test5,) - result = func(test5) - self.assertEqual(ctx.exception.args[0], 'item 1 in _argtypes_ passes ' - 'a union by value, which is unsupported.') - - # passing by reference should be OK - test4.a_long = 12345; - func = dll._testfunc_union_by_reference1 - func.restype = c_long - func.argtypes = (POINTER(Test4),) - result = func(byref(test4)) - self.assertEqual(result, 12345) - self.assertEqual(test4.a_long, 0) - self.assertEqual(test4.a_struct.an_int, 0) - self.assertEqual(test4.a_struct.another_int, 0) - test4.a_struct.an_int = 0x12340000 - test4.a_struct.another_int = 0x5678 - func = dll._testfunc_union_by_reference2 - func.restype = c_long - func.argtypes = (POINTER(Test4),) - result = func(byref(test4)) - self.assertEqual(result, 0x12345678) - self.assertEqual(test4.a_long, 0) - self.assertEqual(test4.a_struct.an_int, 0) - self.assertEqual(test4.a_struct.another_int, 0) - test5.an_int = 0x12000000 - test5.nested.an_int = 0x345600 - test5.another_int = 0x78 - func = dll._testfunc_union_by_reference3 - func.restype = c_long - func.argtypes = (POINTER(Test5),) - result = func(byref(test5)) - self.assertEqual(result, 0x12345678) - self.assertEqual(test5.an_int, 0) - self.assertEqual(test5.nested.an_int, 0) - self.assertEqual(test5.another_int, 0) - - @unittest.skipIf(True, 'Test disabled for now - see bpo-16575/bpo-16576') - def test_bitfield_by_value(self): - # See bpo-16576 - - # These should mirror the structures in Modules/_ctypes/_ctypes_test.c - - class Test6(Structure): - _fields_ = [ - ('A', c_int, 1), - ('B', c_int, 2), - ('C', c_int, 3), - ('D', c_int, 2), - ] - - test6 = Test6() - # As these are signed int fields, all are logically -1 due to sign - # extension. - test6.A = 1 - test6.B = 3 - test6.C = 7 - test6.D = 3 - dll = CDLL(_ctypes_test.__file__) - with self.assertRaises(TypeError) as ctx: - func = dll._testfunc_bitfield_by_value1 - func.restype = c_long - func.argtypes = (Test6,) - result = func(test6) - self.assertEqual(ctx.exception.args[0], 'item 1 in _argtypes_ passes ' - 'a struct/union with a bitfield by value, which is ' - 'unsupported.') - # passing by reference should be OK - func = dll._testfunc_bitfield_by_reference1 - func.restype = c_long - func.argtypes = (POINTER(Test6),) - result = func(byref(test6)) - self.assertEqual(result, -4) - self.assertEqual(test6.A, 0) - self.assertEqual(test6.B, 0) - self.assertEqual(test6.C, 0) - self.assertEqual(test6.D, 0) - - class Test7(Structure): - _fields_ = [ - ('A', c_uint, 1), - ('B', c_uint, 2), - ('C', c_uint, 3), - ('D', c_uint, 2), - ] - test7 = Test7() - test7.A = 1 - test7.B = 3 - test7.C = 7 - test7.D = 3 - func = dll._testfunc_bitfield_by_reference2 - func.restype = c_long - func.argtypes = (POINTER(Test7),) - result = func(byref(test7)) - self.assertEqual(result, 14) - self.assertEqual(test7.A, 0) - self.assertEqual(test7.B, 0) - self.assertEqual(test7.C, 0) - self.assertEqual(test7.D, 0) - - # for a union with bitfields, the union check happens first - class Test8(Union): - _fields_ = [ - ('A', c_int, 1), - ('B', c_int, 2), - ('C', c_int, 3), - ('D', c_int, 2), - ] - - test8 = Test8() - with self.assertRaises(TypeError) as ctx: - func = dll._testfunc_bitfield_by_value2 - func.restype = c_long - func.argtypes = (Test8,) - result = func(test8) - self.assertEqual(ctx.exception.args[0], 'item 1 in _argtypes_ passes ' - 'a union by value, which is unsupported.') - -class PointerMemberTestCase(unittest.TestCase): - - def test(self): - # a Structure with a POINTER field - class S(Structure): - _fields_ = [("array", POINTER(c_int))] - - s = S() - # We can assign arrays of the correct type - s.array = (c_int * 3)(1, 2, 3) - items = [s.array[i] for i in range(3)] - self.assertEqual(items, [1, 2, 3]) - - # The following are bugs, but are included here because the unittests - # also describe the current behaviour. - # - # This fails with SystemError: bad arg to internal function - # or with IndexError (with a patch I have) - - s.array[0] = 42 - - items = [s.array[i] for i in range(3)] - self.assertEqual(items, [42, 2, 3]) - - s.array[0] = 1 - -## s.array[1] = 42 - - items = [s.array[i] for i in range(3)] - self.assertEqual(items, [1, 2, 3]) - - def test_none_to_pointer_fields(self): - class S(Structure): - _fields_ = [("x", c_int), - ("p", POINTER(c_int))] - - s = S() - s.x = 12345678 - s.p = None - self.assertEqual(s.x, 12345678) - -class TestRecursiveStructure(unittest.TestCase): - def test_contains_itself(self): - class Recursive(Structure): - pass - - try: - Recursive._fields_ = [("next", Recursive)] - except AttributeError as details: - self.assertIn("Structure or union cannot contain itself", - str(details)) - else: - self.fail("Structure or union cannot contain itself") - - - def test_vice_versa(self): - class First(Structure): - pass - class Second(Structure): - pass - - First._fields_ = [("second", Second)] - - try: - Second._fields_ = [("first", First)] - except AttributeError as details: - self.assertIn("_fields_ is final", str(details)) - else: - self.fail("AttributeError not raised") - -if __name__ == '__main__': - unittest.main() diff --git a/Lib/ctypes/test/test_unaligned_structures.py b/Lib/ctypes/test/test_unaligned_structures.py deleted file mode 100644 index ee7fb45..0000000 --- a/Lib/ctypes/test/test_unaligned_structures.py +++ /dev/null @@ -1,43 +0,0 @@ -import sys, unittest -from ctypes import * - -structures = [] -byteswapped_structures = [] - - -if sys.byteorder == "little": - SwappedStructure = BigEndianStructure -else: - SwappedStructure = LittleEndianStructure - -for typ in [c_short, c_int, c_long, c_longlong, - c_float, c_double, - c_ushort, c_uint, c_ulong, c_ulonglong]: - class X(Structure): - _pack_ = 1 - _fields_ = [("pad", c_byte), - ("value", typ)] - class Y(SwappedStructure): - _pack_ = 1 - _fields_ = [("pad", c_byte), - ("value", typ)] - structures.append(X) - byteswapped_structures.append(Y) - -class TestStructures(unittest.TestCase): - def test_native(self): - for typ in structures: - self.assertEqual(typ.value.offset, 1) - o = typ() - o.value = 4 - self.assertEqual(o.value, 4) - - def test_swapped(self): - for typ in byteswapped_structures: - self.assertEqual(typ.value.offset, 1) - o = typ() - o.value = 4 - self.assertEqual(o.value, 4) - -if __name__ == '__main__': - unittest.main() diff --git a/Lib/ctypes/test/test_unicode.py b/Lib/ctypes/test/test_unicode.py deleted file mode 100644 index 60c7542..0000000 --- a/Lib/ctypes/test/test_unicode.py +++ /dev/null @@ -1,64 +0,0 @@ -import unittest -import ctypes -from ctypes.test import need_symbol - -import _ctypes_test - -@need_symbol('c_wchar') -class UnicodeTestCase(unittest.TestCase): - def test_wcslen(self): - dll = ctypes.CDLL(_ctypes_test.__file__) - wcslen = dll.my_wcslen - wcslen.argtypes = [ctypes.c_wchar_p] - - self.assertEqual(wcslen("abc"), 3) - self.assertEqual(wcslen("ab\u2070"), 3) - self.assertRaises(ctypes.ArgumentError, wcslen, b"ab\xe4") - - def test_buffers(self): - buf = ctypes.create_unicode_buffer("abc") - self.assertEqual(len(buf), 3+1) - - buf = ctypes.create_unicode_buffer("ab\xe4\xf6\xfc") - self.assertEqual(buf[:], "ab\xe4\xf6\xfc\0") - self.assertEqual(buf[::], "ab\xe4\xf6\xfc\0") - self.assertEqual(buf[::-1], '\x00\xfc\xf6\xe4ba') - self.assertEqual(buf[::2], 'a\xe4\xfc') - self.assertEqual(buf[6:5:-1], "") - - def test_embedded_null(self): - class TestStruct(ctypes.Structure): - _fields_ = [("unicode", ctypes.c_wchar_p)] - t = TestStruct() - # This would raise a ValueError: - t.unicode = "foo\0bar\0\0" - - -func = ctypes.CDLL(_ctypes_test.__file__)._testfunc_p_p - -class StringTestCase(UnicodeTestCase): - def setUp(self): - func.argtypes = [ctypes.c_char_p] - func.restype = ctypes.c_char_p - - def tearDown(self): - func.argtypes = None - func.restype = ctypes.c_int - - def test_func(self): - self.assertEqual(func(b"abc\xe4"), b"abc\xe4") - - def test_buffers(self): - buf = ctypes.create_string_buffer(b"abc") - self.assertEqual(len(buf), 3+1) - - buf = ctypes.create_string_buffer(b"ab\xe4\xf6\xfc") - self.assertEqual(buf[:], b"ab\xe4\xf6\xfc\0") - self.assertEqual(buf[::], b"ab\xe4\xf6\xfc\0") - self.assertEqual(buf[::-1], b'\x00\xfc\xf6\xe4ba') - self.assertEqual(buf[::2], b'a\xe4\xfc') - self.assertEqual(buf[6:5:-1], b"") - - -if __name__ == '__main__': - unittest.main() diff --git a/Lib/ctypes/test/test_values.py b/Lib/ctypes/test/test_values.py deleted file mode 100644 index 435fdd2..0000000 --- a/Lib/ctypes/test/test_values.py +++ /dev/null @@ -1,103 +0,0 @@ -""" -A testcase which accesses *values* in a dll. -""" - -import _imp -import importlib.util -import unittest -import sys -from ctypes import * -from test.support import import_helper - -import _ctypes_test - -class ValuesTestCase(unittest.TestCase): - - def test_an_integer(self): - # This test checks and changes an integer stored inside the - # _ctypes_test dll/shared lib. - ctdll = CDLL(_ctypes_test.__file__) - an_integer = c_int.in_dll(ctdll, "an_integer") - x = an_integer.value - self.assertEqual(x, ctdll.get_an_integer()) - an_integer.value *= 2 - self.assertEqual(x*2, ctdll.get_an_integer()) - # To avoid test failures when this test is repeated several - # times the original value must be restored - an_integer.value = x - self.assertEqual(x, ctdll.get_an_integer()) - - def test_undefined(self): - ctdll = CDLL(_ctypes_test.__file__) - self.assertRaises(ValueError, c_int.in_dll, ctdll, "Undefined_Symbol") - -class PythonValuesTestCase(unittest.TestCase): - """This test only works when python itself is a dll/shared library""" - - def test_optimizeflag(self): - # This test accesses the Py_OptimizeFlag integer, which is - # exported by the Python dll and should match the sys.flags value - - opt = c_int.in_dll(pythonapi, "Py_OptimizeFlag").value - self.assertEqual(opt, sys.flags.optimize) - - def test_frozentable(self): - # Python exports a PyImport_FrozenModules symbol. This is a - # pointer to an array of struct _frozen entries. The end of the - # array is marked by an entry containing a NULL name and zero - # size. - - # In standard Python, this table contains a __hello__ - # module, and a __phello__ package containing a spam - # module. - class struct_frozen(Structure): - _fields_ = [("name", c_char_p), - ("code", POINTER(c_ubyte)), - ("size", c_int), - ("is_package", c_int), - ("get_code", POINTER(c_ubyte)), # Function ptr - ] - FrozenTable = POINTER(struct_frozen) - - modules = [] - for group in ["Bootstrap", "Stdlib", "Test"]: - ft = FrozenTable.in_dll(pythonapi, f"_PyImport_Frozen{group}") - # ft is a pointer to the struct_frozen entries: - for entry in ft: - # This is dangerous. We *can* iterate over a pointer, but - # the loop will not terminate (maybe with an access - # violation;-) because the pointer instance has no size. - if entry.name is None: - break - modname = entry.name.decode("ascii") - modules.append(modname) - with self.subTest(modname): - if entry.size != 0: - # Do a sanity check on entry.size and entry.code. - self.assertGreater(abs(entry.size), 10) - self.assertTrue([entry.code[i] for i in range(abs(entry.size))]) - # Check the module's package-ness. - with import_helper.frozen_modules(): - spec = importlib.util.find_spec(modname) - if entry.is_package: - # It's a package. - self.assertIsNotNone(spec.submodule_search_locations) - else: - self.assertIsNone(spec.submodule_search_locations) - - with import_helper.frozen_modules(): - expected = _imp._frozen_module_names() - self.maxDiff = None - self.assertEqual(modules, expected, - "_PyImport_FrozenBootstrap example " - "in Doc/library/ctypes.rst may be out of date") - - from ctypes import _pointer_type_cache - del _pointer_type_cache[struct_frozen] - - def test_undefined(self): - self.assertRaises(ValueError, c_int.in_dll, pythonapi, - "Undefined_Symbol") - -if __name__ == '__main__': - unittest.main() diff --git a/Lib/ctypes/test/test_varsize_struct.py b/Lib/ctypes/test/test_varsize_struct.py deleted file mode 100644 index f409500..0000000 --- a/Lib/ctypes/test/test_varsize_struct.py +++ /dev/null @@ -1,50 +0,0 @@ -from ctypes import * -import unittest - -class VarSizeTest(unittest.TestCase): - def test_resize(self): - class X(Structure): - _fields_ = [("item", c_int), - ("array", c_int * 1)] - - self.assertEqual(sizeof(X), sizeof(c_int) * 2) - x = X() - x.item = 42 - x.array[0] = 100 - self.assertEqual(sizeof(x), sizeof(c_int) * 2) - - # make room for one additional item - new_size = sizeof(X) + sizeof(c_int) * 1 - resize(x, new_size) - self.assertEqual(sizeof(x), new_size) - self.assertEqual((x.item, x.array[0]), (42, 100)) - - # make room for 10 additional items - new_size = sizeof(X) + sizeof(c_int) * 9 - resize(x, new_size) - self.assertEqual(sizeof(x), new_size) - self.assertEqual((x.item, x.array[0]), (42, 100)) - - # make room for one additional item - new_size = sizeof(X) + sizeof(c_int) * 1 - resize(x, new_size) - self.assertEqual(sizeof(x), new_size) - self.assertEqual((x.item, x.array[0]), (42, 100)) - - def test_array_invalid_length(self): - # cannot create arrays with non-positive size - self.assertRaises(ValueError, lambda: c_int * -1) - self.assertRaises(ValueError, lambda: c_int * -3) - - def test_zerosized_array(self): - array = (c_int * 0)() - # accessing elements of zero-sized arrays raise IndexError - self.assertRaises(IndexError, array.__setitem__, 0, None) - self.assertRaises(IndexError, array.__getitem__, 0) - self.assertRaises(IndexError, array.__setitem__, 1, None) - self.assertRaises(IndexError, array.__getitem__, 1) - self.assertRaises(IndexError, array.__setitem__, -1, None) - self.assertRaises(IndexError, array.__getitem__, -1) - -if __name__ == "__main__": - unittest.main() diff --git a/Lib/ctypes/test/test_win32.py b/Lib/ctypes/test/test_win32.py deleted file mode 100644 index e51bdc8..0000000 --- a/Lib/ctypes/test/test_win32.py +++ /dev/null @@ -1,136 +0,0 @@ -# Windows specific tests - -from ctypes import * -import unittest, sys -from test import support - -import _ctypes_test - -@unittest.skipUnless(sys.platform == "win32", 'Windows-specific test') -class FunctionCallTestCase(unittest.TestCase): - @unittest.skipUnless('MSC' in sys.version, "SEH only supported by MSC") - @unittest.skipIf(sys.executable.lower().endswith('_d.exe'), - "SEH not enabled in debug builds") - def test_SEH(self): - # Disable faulthandler to prevent logging the warning: - # "Windows fatal exception: access violation" - with support.disable_faulthandler(): - # Call functions with invalid arguments, and make sure - # that access violations are trapped and raise an - # exception. - self.assertRaises(OSError, windll.kernel32.GetModuleHandleA, 32) - - def test_noargs(self): - # This is a special case on win32 x64 - windll.user32.GetDesktopWindow() - - -@unittest.skipUnless(sys.platform == "win32", 'Windows-specific test') -class ReturnStructSizesTestCase(unittest.TestCase): - def test_sizes(self): - dll = CDLL(_ctypes_test.__file__) - for i in range(1, 11): - fields = [ (f"f{f}", c_char) for f in range(1, i + 1)] - class S(Structure): - _fields_ = fields - f = getattr(dll, f"TestSize{i}") - f.restype = S - res = f() - for i, f in enumerate(fields): - value = getattr(res, f[0]) - expected = bytes([ord('a') + i]) - self.assertEqual(value, expected) - - - -@unittest.skipUnless(sys.platform == "win32", 'Windows-specific test') -class TestWintypes(unittest.TestCase): - def test_HWND(self): - from ctypes import wintypes - self.assertEqual(sizeof(wintypes.HWND), sizeof(c_void_p)) - - def test_PARAM(self): - from ctypes import wintypes - self.assertEqual(sizeof(wintypes.WPARAM), - sizeof(c_void_p)) - self.assertEqual(sizeof(wintypes.LPARAM), - sizeof(c_void_p)) - - def test_COMError(self): - from _ctypes import COMError - if support.HAVE_DOCSTRINGS: - self.assertEqual(COMError.__doc__, - "Raised when a COM method call failed.") - - ex = COMError(-1, "text", ("details",)) - self.assertEqual(ex.hresult, -1) - self.assertEqual(ex.text, "text") - self.assertEqual(ex.details, ("details",)) - -@unittest.skipUnless(sys.platform == "win32", 'Windows-specific test') -class TestWinError(unittest.TestCase): - def test_winerror(self): - # see Issue 16169 - import errno - ERROR_INVALID_PARAMETER = 87 - msg = FormatError(ERROR_INVALID_PARAMETER).strip() - args = (errno.EINVAL, msg, None, ERROR_INVALID_PARAMETER) - - e = WinError(ERROR_INVALID_PARAMETER) - self.assertEqual(e.args, args) - self.assertEqual(e.errno, errno.EINVAL) - self.assertEqual(e.winerror, ERROR_INVALID_PARAMETER) - - windll.kernel32.SetLastError(ERROR_INVALID_PARAMETER) - try: - raise WinError() - except OSError as exc: - e = exc - self.assertEqual(e.args, args) - self.assertEqual(e.errno, errno.EINVAL) - self.assertEqual(e.winerror, ERROR_INVALID_PARAMETER) - -class Structures(unittest.TestCase): - def test_struct_by_value(self): - class POINT(Structure): - _fields_ = [("x", c_long), - ("y", c_long)] - - class RECT(Structure): - _fields_ = [("left", c_long), - ("top", c_long), - ("right", c_long), - ("bottom", c_long)] - - dll = CDLL(_ctypes_test.__file__) - - pt = POINT(15, 25) - left = c_long.in_dll(dll, 'left') - top = c_long.in_dll(dll, 'top') - right = c_long.in_dll(dll, 'right') - bottom = c_long.in_dll(dll, 'bottom') - rect = RECT(left, top, right, bottom) - PointInRect = dll.PointInRect - PointInRect.argtypes = [POINTER(RECT), POINT] - self.assertEqual(1, PointInRect(byref(rect), pt)) - - ReturnRect = dll.ReturnRect - ReturnRect.argtypes = [c_int, RECT, POINTER(RECT), POINT, RECT, - POINTER(RECT), POINT, RECT] - ReturnRect.restype = RECT - for i in range(4): - ret = ReturnRect(i, rect, pointer(rect), pt, rect, - byref(rect), pt, rect) - # the c function will check and modify ret if something is - # passed in improperly - self.assertEqual(ret.left, left.value) - self.assertEqual(ret.right, right.value) - self.assertEqual(ret.top, top.value) - self.assertEqual(ret.bottom, bottom.value) - - # to not leak references, we must clean _pointer_type_cache - from ctypes import _pointer_type_cache - del _pointer_type_cache[RECT] - -if __name__ == '__main__': - unittest.main() diff --git a/Lib/ctypes/test/test_wintypes.py b/Lib/ctypes/test/test_wintypes.py deleted file mode 100644 index 243d596..0000000 --- a/Lib/ctypes/test/test_wintypes.py +++ /dev/null @@ -1,43 +0,0 @@ -import unittest - -# also work on POSIX - -from ctypes import * -from ctypes import wintypes - - -class WinTypesTest(unittest.TestCase): - def test_variant_bool(self): - # reads 16-bits from memory, anything non-zero is True - for true_value in (1, 32767, 32768, 65535, 65537): - true = POINTER(c_int16)(c_int16(true_value)) - value = cast(true, POINTER(wintypes.VARIANT_BOOL)) - self.assertEqual(repr(value.contents), 'VARIANT_BOOL(True)') - - vb = wintypes.VARIANT_BOOL() - self.assertIs(vb.value, False) - vb.value = True - self.assertIs(vb.value, True) - vb.value = true_value - self.assertIs(vb.value, True) - - for false_value in (0, 65536, 262144, 2**33): - false = POINTER(c_int16)(c_int16(false_value)) - value = cast(false, POINTER(wintypes.VARIANT_BOOL)) - self.assertEqual(repr(value.contents), 'VARIANT_BOOL(False)') - - # allow any bool conversion on assignment to value - for set_value in (65536, 262144, 2**33): - vb = wintypes.VARIANT_BOOL() - vb.value = set_value - self.assertIs(vb.value, True) - - vb = wintypes.VARIANT_BOOL() - vb.value = [2, 3] - self.assertIs(vb.value, True) - vb.value = [] - self.assertIs(vb.value, False) - - -if __name__ == "__main__": - unittest.main() diff --git a/Lib/test/leakers/test_ctypes.py b/Lib/test/leakers/test_ctypes.py index 7d7e9ff..ec09ac3 100644 --- a/Lib/test/leakers/test_ctypes.py +++ b/Lib/test/leakers/test_ctypes.py @@ -1,5 +1,5 @@ -# Taken from Lib/ctypes/test/test_keeprefs.py, PointerToStructure.test(). +# Taken from Lib/test/test_ctypes/test_keeprefs.py, PointerToStructure.test(). from ctypes import Structure, c_int, POINTER import gc diff --git a/Lib/test/test_ctypes.py b/Lib/test/test_ctypes.py deleted file mode 100644 index b0a12c9..0000000 --- a/Lib/test/test_ctypes.py +++ /dev/null @@ -1,10 +0,0 @@ -import unittest -from test.support.import_helper import import_module - - -ctypes_test = import_module('ctypes.test') - -load_tests = ctypes_test.load_tests - -if __name__ == "__main__": - unittest.main() diff --git a/Lib/test/test_ctypes/__init__.py b/Lib/test/test_ctypes/__init__.py new file mode 100644 index 0000000..6e496fa --- /dev/null +++ b/Lib/test/test_ctypes/__init__.py @@ -0,0 +1,16 @@ +import os +import unittest +from test import support +from test.support import import_helper + + +# skip tests if _ctypes was not built +ctypes = import_helper.import_module('ctypes') +ctypes_symbols = dir(ctypes) + +def need_symbol(name): + return unittest.skipUnless(name in ctypes_symbols, + '{!r} is required'.format(name)) + +def load_tests(*args): + return support.load_package_tests(os.path.dirname(__file__), *args) diff --git a/Lib/test/test_ctypes/__main__.py b/Lib/test/test_ctypes/__main__.py new file mode 100644 index 0000000..3003d4d --- /dev/null +++ b/Lib/test/test_ctypes/__main__.py @@ -0,0 +1,4 @@ +from test.test_ctypes import load_tests +import unittest + +unittest.main() diff --git a/Lib/test/test_ctypes/test_anon.py b/Lib/test/test_ctypes/test_anon.py new file mode 100644 index 0000000..d378392 --- /dev/null +++ b/Lib/test/test_ctypes/test_anon.py @@ -0,0 +1,73 @@ +import unittest +import test.support +from ctypes import * + +class AnonTest(unittest.TestCase): + + def test_anon(self): + class ANON(Union): + _fields_ = [("a", c_int), + ("b", c_int)] + + class Y(Structure): + _fields_ = [("x", c_int), + ("_", ANON), + ("y", c_int)] + _anonymous_ = ["_"] + + self.assertEqual(Y.a.offset, sizeof(c_int)) + self.assertEqual(Y.b.offset, sizeof(c_int)) + + self.assertEqual(ANON.a.offset, 0) + self.assertEqual(ANON.b.offset, 0) + + def test_anon_nonseq(self): + # TypeError: _anonymous_ must be a sequence + self.assertRaises(TypeError, + lambda: type(Structure)("Name", + (Structure,), + {"_fields_": [], "_anonymous_": 42})) + + def test_anon_nonmember(self): + # AttributeError: type object 'Name' has no attribute 'x' + self.assertRaises(AttributeError, + lambda: type(Structure)("Name", + (Structure,), + {"_fields_": [], + "_anonymous_": ["x"]})) + + @test.support.cpython_only + def test_issue31490(self): + # There shouldn't be an assertion failure in case the class has an + # attribute whose name is specified in _anonymous_ but not in _fields_. + + # AttributeError: 'x' is specified in _anonymous_ but not in _fields_ + with self.assertRaises(AttributeError): + class Name(Structure): + _fields_ = [] + _anonymous_ = ["x"] + x = 42 + + def test_nested(self): + class ANON_S(Structure): + _fields_ = [("a", c_int)] + + class ANON_U(Union): + _fields_ = [("_", ANON_S), + ("b", c_int)] + _anonymous_ = ["_"] + + class Y(Structure): + _fields_ = [("x", c_int), + ("_", ANON_U), + ("y", c_int)] + _anonymous_ = ["_"] + + self.assertEqual(Y.x.offset, 0) + self.assertEqual(Y.a.offset, sizeof(c_int)) + self.assertEqual(Y.b.offset, sizeof(c_int)) + self.assertEqual(Y._.offset, sizeof(c_int)) + self.assertEqual(Y.y.offset, sizeof(c_int) * 2) + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_ctypes/test_array_in_pointer.py b/Lib/test/test_ctypes/test_array_in_pointer.py new file mode 100644 index 0000000..ca1edcf --- /dev/null +++ b/Lib/test/test_ctypes/test_array_in_pointer.py @@ -0,0 +1,64 @@ +import unittest +from ctypes import * +from binascii import hexlify +import re + +def dump(obj): + # helper function to dump memory contents in hex, with a hyphen + # between the bytes. + h = hexlify(memoryview(obj)).decode() + return re.sub(r"(..)", r"\1-", h)[:-1] + + +class Value(Structure): + _fields_ = [("val", c_byte)] + +class Container(Structure): + _fields_ = [("pvalues", POINTER(Value))] + +class Test(unittest.TestCase): + def test(self): + # create an array of 4 values + val_array = (Value * 4)() + + # create a container, which holds a pointer to the pvalues array. + c = Container() + c.pvalues = val_array + + # memory contains 4 NUL bytes now, that's correct + self.assertEqual("00-00-00-00", dump(val_array)) + + # set the values of the array through the pointer: + for i in range(4): + c.pvalues[i].val = i + 1 + + values = [c.pvalues[i].val for i in range(4)] + + # These are the expected results: here s the bug! + self.assertEqual( + (values, dump(val_array)), + ([1, 2, 3, 4], "01-02-03-04") + ) + + def test_2(self): + + val_array = (Value * 4)() + + # memory contains 4 NUL bytes now, that's correct + self.assertEqual("00-00-00-00", dump(val_array)) + + ptr = cast(val_array, POINTER(Value)) + # set the values of the array through the pointer: + for i in range(4): + ptr[i].val = i + 1 + + values = [ptr[i].val for i in range(4)] + + # These are the expected results: here s the bug! + self.assertEqual( + (values, dump(val_array)), + ([1, 2, 3, 4], "01-02-03-04") + ) + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_ctypes/test_arrays.py b/Lib/test/test_ctypes/test_arrays.py new file mode 100644 index 0000000..415a578 --- /dev/null +++ b/Lib/test/test_ctypes/test_arrays.py @@ -0,0 +1,238 @@ +import unittest +from test.support import bigmemtest, _2G +import sys +from ctypes import * + +from test.test_ctypes import need_symbol + +formats = "bBhHiIlLqQfd" + +formats = c_byte, c_ubyte, c_short, c_ushort, c_int, c_uint, \ + c_long, c_ulonglong, c_float, c_double, c_longdouble + +class ArrayTestCase(unittest.TestCase): + def test_simple(self): + # create classes holding simple numeric types, and check + # various properties. + + init = list(range(15, 25)) + + for fmt in formats: + alen = len(init) + int_array = ARRAY(fmt, alen) + + ia = int_array(*init) + # length of instance ok? + self.assertEqual(len(ia), alen) + + # slot values ok? + values = [ia[i] for i in range(alen)] + self.assertEqual(values, init) + + # out-of-bounds accesses should be caught + with self.assertRaises(IndexError): ia[alen] + with self.assertRaises(IndexError): ia[-alen-1] + + # change the items + from operator import setitem + new_values = list(range(42, 42+alen)) + [setitem(ia, n, new_values[n]) for n in range(alen)] + values = [ia[i] for i in range(alen)] + self.assertEqual(values, new_values) + + # are the items initialized to 0? + ia = int_array() + values = [ia[i] for i in range(alen)] + self.assertEqual(values, [0] * alen) + + # Too many initializers should be caught + self.assertRaises(IndexError, int_array, *range(alen*2)) + + CharArray = ARRAY(c_char, 3) + + ca = CharArray(b"a", b"b", b"c") + + # Should this work? It doesn't: + # CharArray("abc") + self.assertRaises(TypeError, CharArray, "abc") + + self.assertEqual(ca[0], b"a") + self.assertEqual(ca[1], b"b") + self.assertEqual(ca[2], b"c") + self.assertEqual(ca[-3], b"a") + self.assertEqual(ca[-2], b"b") + self.assertEqual(ca[-1], b"c") + + self.assertEqual(len(ca), 3) + + # cannot delete items + from operator import delitem + self.assertRaises(TypeError, delitem, ca, 0) + + def test_step_overflow(self): + a = (c_int * 5)() + a[3::sys.maxsize] = (1,) + self.assertListEqual(a[3::sys.maxsize], [1]) + a = (c_char * 5)() + a[3::sys.maxsize] = b"A" + self.assertEqual(a[3::sys.maxsize], b"A") + a = (c_wchar * 5)() + a[3::sys.maxsize] = u"X" + self.assertEqual(a[3::sys.maxsize], u"X") + + def test_numeric_arrays(self): + + alen = 5 + + numarray = ARRAY(c_int, alen) + + na = numarray() + values = [na[i] for i in range(alen)] + self.assertEqual(values, [0] * alen) + + na = numarray(*[c_int()] * alen) + values = [na[i] for i in range(alen)] + self.assertEqual(values, [0]*alen) + + na = numarray(1, 2, 3, 4, 5) + values = [i for i in na] + self.assertEqual(values, [1, 2, 3, 4, 5]) + + na = numarray(*map(c_int, (1, 2, 3, 4, 5))) + values = [i for i in na] + self.assertEqual(values, [1, 2, 3, 4, 5]) + + def test_classcache(self): + self.assertIsNot(ARRAY(c_int, 3), ARRAY(c_int, 4)) + self.assertIs(ARRAY(c_int, 3), ARRAY(c_int, 3)) + + def test_from_address(self): + # Failed with 0.9.8, reported by JUrner + p = create_string_buffer(b"foo") + sz = (c_char * 3).from_address(addressof(p)) + self.assertEqual(sz[:], b"foo") + self.assertEqual(sz[::], b"foo") + self.assertEqual(sz[::-1], b"oof") + self.assertEqual(sz[::3], b"f") + self.assertEqual(sz[1:4:2], b"o") + self.assertEqual(sz.value, b"foo") + + @need_symbol('create_unicode_buffer') + def test_from_addressW(self): + p = create_unicode_buffer("foo") + sz = (c_wchar * 3).from_address(addressof(p)) + self.assertEqual(sz[:], "foo") + self.assertEqual(sz[::], "foo") + self.assertEqual(sz[::-1], "oof") + self.assertEqual(sz[::3], "f") + self.assertEqual(sz[1:4:2], "o") + self.assertEqual(sz.value, "foo") + + def test_cache(self): + # Array types are cached internally in the _ctypes extension, + # in a WeakValueDictionary. Make sure the array type is + # removed from the cache when the itemtype goes away. This + # test will not fail, but will show a leak in the testsuite. + + # Create a new type: + class my_int(c_int): + pass + # Create a new array type based on it: + t1 = my_int * 1 + t2 = my_int * 1 + self.assertIs(t1, t2) + + def test_subclass(self): + class T(Array): + _type_ = c_int + _length_ = 13 + class U(T): + pass + class V(U): + pass + class W(V): + pass + class X(T): + _type_ = c_short + class Y(T): + _length_ = 187 + + for c in [T, U, V, W]: + self.assertEqual(c._type_, c_int) + self.assertEqual(c._length_, 13) + self.assertEqual(c()._type_, c_int) + self.assertEqual(c()._length_, 13) + + self.assertEqual(X._type_, c_short) + self.assertEqual(X._length_, 13) + self.assertEqual(X()._type_, c_short) + self.assertEqual(X()._length_, 13) + + self.assertEqual(Y._type_, c_int) + self.assertEqual(Y._length_, 187) + self.assertEqual(Y()._type_, c_int) + self.assertEqual(Y()._length_, 187) + + def test_bad_subclass(self): + with self.assertRaises(AttributeError): + class T(Array): + pass + with self.assertRaises(AttributeError): + class T(Array): + _type_ = c_int + with self.assertRaises(AttributeError): + class T(Array): + _length_ = 13 + + def test_bad_length(self): + with self.assertRaises(ValueError): + class T(Array): + _type_ = c_int + _length_ = - sys.maxsize * 2 + with self.assertRaises(ValueError): + class T(Array): + _type_ = c_int + _length_ = -1 + with self.assertRaises(TypeError): + class T(Array): + _type_ = c_int + _length_ = 1.87 + with self.assertRaises(OverflowError): + class T(Array): + _type_ = c_int + _length_ = sys.maxsize * 2 + + def test_zero_length(self): + # _length_ can be zero. + class T(Array): + _type_ = c_int + _length_ = 0 + + def test_empty_element_struct(self): + class EmptyStruct(Structure): + _fields_ = [] + + obj = (EmptyStruct * 2)() # bpo37188: Floating point exception + self.assertEqual(sizeof(obj), 0) + + def test_empty_element_array(self): + class EmptyArray(Array): + _type_ = c_int + _length_ = 0 + + obj = (EmptyArray * 2)() # bpo37188: Floating point exception + self.assertEqual(sizeof(obj), 0) + + def test_bpo36504_signed_int_overflow(self): + # The overflow check in PyCArrayType_new() could cause signed integer + # overflow. + with self.assertRaises(OverflowError): + c_char * sys.maxsize * 2 + + @unittest.skipUnless(sys.maxsize > 2**32, 'requires 64bit platform') + @bigmemtest(size=_2G, memuse=1, dry_run=False) + def test_large_array(self, size): + c_char * size + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/test_ctypes/test_as_parameter.py b/Lib/test/test_ctypes/test_as_parameter.py new file mode 100644 index 0000000..b35defb --- /dev/null +++ b/Lib/test/test_ctypes/test_as_parameter.py @@ -0,0 +1,230 @@ +import unittest +from ctypes import * +from test.test_ctypes import need_symbol +import _ctypes_test + +dll = CDLL(_ctypes_test.__file__) + +try: + CALLBACK_FUNCTYPE = WINFUNCTYPE +except NameError: + # fake to enable this test on Linux + CALLBACK_FUNCTYPE = CFUNCTYPE + +class POINT(Structure): + _fields_ = [("x", c_int), ("y", c_int)] + +class BasicWrapTestCase(unittest.TestCase): + def wrap(self, param): + return param + + @need_symbol('c_wchar') + def test_wchar_parm(self): + f = dll._testfunc_i_bhilfd + f.argtypes = [c_byte, c_wchar, c_int, c_long, c_float, c_double] + result = f(self.wrap(1), self.wrap("x"), self.wrap(3), self.wrap(4), self.wrap(5.0), self.wrap(6.0)) + self.assertEqual(result, 139) + self.assertIs(type(result), int) + + def test_pointers(self): + f = dll._testfunc_p_p + f.restype = POINTER(c_int) + f.argtypes = [POINTER(c_int)] + + # This only works if the value c_int(42) passed to the + # function is still alive while the pointer (the result) is + # used. + + v = c_int(42) + + self.assertEqual(pointer(v).contents.value, 42) + result = f(self.wrap(pointer(v))) + self.assertEqual(type(result), POINTER(c_int)) + self.assertEqual(result.contents.value, 42) + + # This on works... + result = f(self.wrap(pointer(v))) + self.assertEqual(result.contents.value, v.value) + + p = pointer(c_int(99)) + result = f(self.wrap(p)) + self.assertEqual(result.contents.value, 99) + + def test_shorts(self): + f = dll._testfunc_callback_i_if + + args = [] + expected = [262144, 131072, 65536, 32768, 16384, 8192, 4096, 2048, + 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1] + + def callback(v): + args.append(v) + return v + + CallBack = CFUNCTYPE(c_int, c_int) + + cb = CallBack(callback) + f(self.wrap(2**18), self.wrap(cb)) + self.assertEqual(args, expected) + + ################################################################ + + def test_callbacks(self): + f = dll._testfunc_callback_i_if + f.restype = c_int + f.argtypes = None + + MyCallback = CFUNCTYPE(c_int, c_int) + + def callback(value): + #print "called back with", value + return value + + cb = MyCallback(callback) + + result = f(self.wrap(-10), self.wrap(cb)) + self.assertEqual(result, -18) + + # test with prototype + f.argtypes = [c_int, MyCallback] + cb = MyCallback(callback) + + result = f(self.wrap(-10), self.wrap(cb)) + self.assertEqual(result, -18) + + result = f(self.wrap(-10), self.wrap(cb)) + self.assertEqual(result, -18) + + AnotherCallback = CALLBACK_FUNCTYPE(c_int, c_int, c_int, c_int, c_int) + + # check that the prototype works: we call f with wrong + # argument types + cb = AnotherCallback(callback) + self.assertRaises(ArgumentError, f, self.wrap(-10), self.wrap(cb)) + + def test_callbacks_2(self): + # Can also use simple datatypes as argument type specifiers + # for the callback function. + # In this case the call receives an instance of that type + f = dll._testfunc_callback_i_if + f.restype = c_int + + MyCallback = CFUNCTYPE(c_int, c_int) + + f.argtypes = [c_int, MyCallback] + + def callback(value): + #print "called back with", value + self.assertEqual(type(value), int) + return value + + cb = MyCallback(callback) + result = f(self.wrap(-10), self.wrap(cb)) + self.assertEqual(result, -18) + + def test_longlong_callbacks(self): + + f = dll._testfunc_callback_q_qf + f.restype = c_longlong + + MyCallback = CFUNCTYPE(c_longlong, c_longlong) + + f.argtypes = [c_longlong, MyCallback] + + def callback(value): + self.assertIsInstance(value, int) + return value & 0x7FFFFFFF + + cb = MyCallback(callback) + + self.assertEqual(13577625587, int(f(self.wrap(1000000000000), self.wrap(cb)))) + + def test_byval(self): + # without prototype + ptin = POINT(1, 2) + ptout = POINT() + # EXPORT int _testfunc_byval(point in, point *pout) + result = dll._testfunc_byval(ptin, byref(ptout)) + got = result, ptout.x, ptout.y + expected = 3, 1, 2 + self.assertEqual(got, expected) + + # with prototype + ptin = POINT(101, 102) + ptout = POINT() + dll._testfunc_byval.argtypes = (POINT, POINTER(POINT)) + dll._testfunc_byval.restype = c_int + result = dll._testfunc_byval(self.wrap(ptin), byref(ptout)) + got = result, ptout.x, ptout.y + expected = 203, 101, 102 + self.assertEqual(got, expected) + + def test_struct_return_2H(self): + class S2H(Structure): + _fields_ = [("x", c_short), + ("y", c_short)] + dll.ret_2h_func.restype = S2H + dll.ret_2h_func.argtypes = [S2H] + inp = S2H(99, 88) + s2h = dll.ret_2h_func(self.wrap(inp)) + self.assertEqual((s2h.x, s2h.y), (99*2, 88*3)) + + # Test also that the original struct was unmodified (i.e. was passed by + # value) + self.assertEqual((inp.x, inp.y), (99, 88)) + + def test_struct_return_8H(self): + class S8I(Structure): + _fields_ = [("a", c_int), + ("b", c_int), + ("c", c_int), + ("d", c_int), + ("e", c_int), + ("f", c_int), + ("g", c_int), + ("h", c_int)] + dll.ret_8i_func.restype = S8I + dll.ret_8i_func.argtypes = [S8I] + inp = S8I(9, 8, 7, 6, 5, 4, 3, 2) + s8i = dll.ret_8i_func(self.wrap(inp)) + self.assertEqual((s8i.a, s8i.b, s8i.c, s8i.d, s8i.e, s8i.f, s8i.g, s8i.h), + (9*2, 8*3, 7*4, 6*5, 5*6, 4*7, 3*8, 2*9)) + + def test_recursive_as_param(self): + from ctypes import c_int + + class A(object): + pass + + a = A() + a._as_parameter_ = a + with self.assertRaises(RecursionError): + c_int.from_param(a) + + +#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class AsParamWrapper(object): + def __init__(self, param): + self._as_parameter_ = param + +class AsParamWrapperTestCase(BasicWrapTestCase): + wrap = AsParamWrapper + +#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class AsParamPropertyWrapper(object): + def __init__(self, param): + self._param = param + + def getParameter(self): + return self._param + _as_parameter_ = property(getParameter) + +class AsParamPropertyWrapperTestCase(BasicWrapTestCase): + wrap = AsParamPropertyWrapper + +#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/test_ctypes/test_bitfields.py b/Lib/test/test_ctypes/test_bitfields.py new file mode 100644 index 0000000..dad71a0 --- /dev/null +++ b/Lib/test/test_ctypes/test_bitfields.py @@ -0,0 +1,297 @@ +from ctypes import * +from test.test_ctypes import need_symbol +from test import support +import unittest +import os + +import _ctypes_test + +class BITS(Structure): + _fields_ = [("A", c_int, 1), + ("B", c_int, 2), + ("C", c_int, 3), + ("D", c_int, 4), + ("E", c_int, 5), + ("F", c_int, 6), + ("G", c_int, 7), + ("H", c_int, 8), + ("I", c_int, 9), + + ("M", c_short, 1), + ("N", c_short, 2), + ("O", c_short, 3), + ("P", c_short, 4), + ("Q", c_short, 5), + ("R", c_short, 6), + ("S", c_short, 7)] + +func = CDLL(_ctypes_test.__file__).unpack_bitfields +func.argtypes = POINTER(BITS), c_char + +##for n in "ABCDEFGHIMNOPQRS": +## print n, hex(getattr(BITS, n).size), getattr(BITS, n).offset + +class C_Test(unittest.TestCase): + + def test_ints(self): + for i in range(512): + for name in "ABCDEFGHI": + b = BITS() + setattr(b, name, i) + self.assertEqual(getattr(b, name), func(byref(b), name.encode('ascii'))) + + # bpo-46913: _ctypes/cfield.c h_get() has an undefined behavior + @support.skip_if_sanitizer(ub=True) + def test_shorts(self): + b = BITS() + name = "M" + if func(byref(b), name.encode('ascii')) == 999: + self.skipTest("Compiler does not support signed short bitfields") + for i in range(256): + for name in "MNOPQRS": + b = BITS() + setattr(b, name, i) + self.assertEqual(getattr(b, name), func(byref(b), name.encode('ascii'))) + +signed_int_types = (c_byte, c_short, c_int, c_long, c_longlong) +unsigned_int_types = (c_ubyte, c_ushort, c_uint, c_ulong, c_ulonglong) +int_types = unsigned_int_types + signed_int_types + +class BitFieldTest(unittest.TestCase): + + def test_longlong(self): + class X(Structure): + _fields_ = [("a", c_longlong, 1), + ("b", c_longlong, 62), + ("c", c_longlong, 1)] + + self.assertEqual(sizeof(X), sizeof(c_longlong)) + x = X() + x.a, x.b, x.c = -1, 7, -1 + self.assertEqual((x.a, x.b, x.c), (-1, 7, -1)) + + def test_ulonglong(self): + class X(Structure): + _fields_ = [("a", c_ulonglong, 1), + ("b", c_ulonglong, 62), + ("c", c_ulonglong, 1)] + + self.assertEqual(sizeof(X), sizeof(c_longlong)) + x = X() + self.assertEqual((x.a, x.b, x.c), (0, 0, 0)) + x.a, x.b, x.c = 7, 7, 7 + self.assertEqual((x.a, x.b, x.c), (1, 7, 1)) + + def test_signed(self): + for c_typ in signed_int_types: + class X(Structure): + _fields_ = [("dummy", c_typ), + ("a", c_typ, 3), + ("b", c_typ, 3), + ("c", c_typ, 1)] + self.assertEqual(sizeof(X), sizeof(c_typ)*2) + + x = X() + self.assertEqual((c_typ, x.a, x.b, x.c), (c_typ, 0, 0, 0)) + x.a = -1 + self.assertEqual((c_typ, x.a, x.b, x.c), (c_typ, -1, 0, 0)) + x.a, x.b = 0, -1 + self.assertEqual((c_typ, x.a, x.b, x.c), (c_typ, 0, -1, 0)) + + + def test_unsigned(self): + for c_typ in unsigned_int_types: + class X(Structure): + _fields_ = [("a", c_typ, 3), + ("b", c_typ, 3), + ("c", c_typ, 1)] + self.assertEqual(sizeof(X), sizeof(c_typ)) + + x = X() + self.assertEqual((c_typ, x.a, x.b, x.c), (c_typ, 0, 0, 0)) + x.a = -1 + self.assertEqual((c_typ, x.a, x.b, x.c), (c_typ, 7, 0, 0)) + x.a, x.b = 0, -1 + self.assertEqual((c_typ, x.a, x.b, x.c), (c_typ, 0, 7, 0)) + + + def fail_fields(self, *fields): + return self.get_except(type(Structure), "X", (), + {"_fields_": fields}) + + def test_nonint_types(self): + # bit fields are not allowed on non-integer types. + result = self.fail_fields(("a", c_char_p, 1)) + self.assertEqual(result, (TypeError, 'bit fields not allowed for type c_char_p')) + + result = self.fail_fields(("a", c_void_p, 1)) + self.assertEqual(result, (TypeError, 'bit fields not allowed for type c_void_p')) + + if c_int != c_long: + result = self.fail_fields(("a", POINTER(c_int), 1)) + self.assertEqual(result, (TypeError, 'bit fields not allowed for type LP_c_int')) + + result = self.fail_fields(("a", c_char, 1)) + self.assertEqual(result, (TypeError, 'bit fields not allowed for type c_char')) + + class Dummy(Structure): + _fields_ = [] + + result = self.fail_fields(("a", Dummy, 1)) + self.assertEqual(result, (TypeError, 'bit fields not allowed for type Dummy')) + + @need_symbol('c_wchar') + def test_c_wchar(self): + result = self.fail_fields(("a", c_wchar, 1)) + self.assertEqual(result, + (TypeError, 'bit fields not allowed for type c_wchar')) + + def test_single_bitfield_size(self): + for c_typ in int_types: + result = self.fail_fields(("a", c_typ, -1)) + self.assertEqual(result, (ValueError, 'number of bits invalid for bit field')) + + result = self.fail_fields(("a", c_typ, 0)) + self.assertEqual(result, (ValueError, 'number of bits invalid for bit field')) + + class X(Structure): + _fields_ = [("a", c_typ, 1)] + self.assertEqual(sizeof(X), sizeof(c_typ)) + + class X(Structure): + _fields_ = [("a", c_typ, sizeof(c_typ)*8)] + self.assertEqual(sizeof(X), sizeof(c_typ)) + + result = self.fail_fields(("a", c_typ, sizeof(c_typ)*8 + 1)) + self.assertEqual(result, (ValueError, 'number of bits invalid for bit field')) + + def test_multi_bitfields_size(self): + class X(Structure): + _fields_ = [("a", c_short, 1), + ("b", c_short, 14), + ("c", c_short, 1)] + self.assertEqual(sizeof(X), sizeof(c_short)) + + class X(Structure): + _fields_ = [("a", c_short, 1), + ("a1", c_short), + ("b", c_short, 14), + ("c", c_short, 1)] + self.assertEqual(sizeof(X), sizeof(c_short)*3) + self.assertEqual(X.a.offset, 0) + self.assertEqual(X.a1.offset, sizeof(c_short)) + self.assertEqual(X.b.offset, sizeof(c_short)*2) + self.assertEqual(X.c.offset, sizeof(c_short)*2) + + class X(Structure): + _fields_ = [("a", c_short, 3), + ("b", c_short, 14), + ("c", c_short, 14)] + self.assertEqual(sizeof(X), sizeof(c_short)*3) + self.assertEqual(X.a.offset, sizeof(c_short)*0) + self.assertEqual(X.b.offset, sizeof(c_short)*1) + self.assertEqual(X.c.offset, sizeof(c_short)*2) + + + def get_except(self, func, *args, **kw): + try: + func(*args, **kw) + except Exception as detail: + return detail.__class__, str(detail) + + def test_mixed_1(self): + class X(Structure): + _fields_ = [("a", c_byte, 4), + ("b", c_int, 4)] + if os.name == "nt": + self.assertEqual(sizeof(X), sizeof(c_int)*2) + else: + self.assertEqual(sizeof(X), sizeof(c_int)) + + def test_mixed_2(self): + class X(Structure): + _fields_ = [("a", c_byte, 4), + ("b", c_int, 32)] + self.assertEqual(sizeof(X), alignment(c_int)+sizeof(c_int)) + + def test_mixed_3(self): + class X(Structure): + _fields_ = [("a", c_byte, 4), + ("b", c_ubyte, 4)] + self.assertEqual(sizeof(X), sizeof(c_byte)) + + def test_mixed_4(self): + class X(Structure): + _fields_ = [("a", c_short, 4), + ("b", c_short, 4), + ("c", c_int, 24), + ("d", c_short, 4), + ("e", c_short, 4), + ("f", c_int, 24)] + # MSVC does NOT combine c_short and c_int into one field, GCC + # does (unless GCC is run with '-mms-bitfields' which + # produces code compatible with MSVC). + if os.name == "nt": + self.assertEqual(sizeof(X), sizeof(c_int) * 4) + else: + self.assertEqual(sizeof(X), sizeof(c_int) * 2) + + def test_anon_bitfields(self): + # anonymous bit-fields gave a strange error message + class X(Structure): + _fields_ = [("a", c_byte, 4), + ("b", c_ubyte, 4)] + class Y(Structure): + _anonymous_ = ["_"] + _fields_ = [("_", X)] + + @need_symbol('c_uint32') + def test_uint32(self): + class X(Structure): + _fields_ = [("a", c_uint32, 32)] + x = X() + x.a = 10 + self.assertEqual(x.a, 10) + x.a = 0xFDCBA987 + self.assertEqual(x.a, 0xFDCBA987) + + @need_symbol('c_uint64') + def test_uint64(self): + class X(Structure): + _fields_ = [("a", c_uint64, 64)] + x = X() + x.a = 10 + self.assertEqual(x.a, 10) + x.a = 0xFEDCBA9876543211 + self.assertEqual(x.a, 0xFEDCBA9876543211) + + @need_symbol('c_uint32') + def test_uint32_swap_little_endian(self): + # Issue #23319 + class Little(LittleEndianStructure): + _fields_ = [("a", c_uint32, 24), + ("b", c_uint32, 4), + ("c", c_uint32, 4)] + b = bytearray(4) + x = Little.from_buffer(b) + x.a = 0xabcdef + x.b = 1 + x.c = 2 + self.assertEqual(b, b'\xef\xcd\xab\x21') + + @need_symbol('c_uint32') + def test_uint32_swap_big_endian(self): + # Issue #23319 + class Big(BigEndianStructure): + _fields_ = [("a", c_uint32, 24), + ("b", c_uint32, 4), + ("c", c_uint32, 4)] + b = bytearray(4) + x = Big.from_buffer(b) + x.a = 0xabcdef + x.b = 1 + x.c = 2 + self.assertEqual(b, b'\xab\xcd\xef\x12') + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_ctypes/test_buffers.py b/Lib/test/test_ctypes/test_buffers.py new file mode 100644 index 0000000..a9be202 --- /dev/null +++ b/Lib/test/test_ctypes/test_buffers.py @@ -0,0 +1,73 @@ +from ctypes import * +from test.test_ctypes import need_symbol +import unittest + +class StringBufferTestCase(unittest.TestCase): + + def test_buffer(self): + b = create_string_buffer(32) + self.assertEqual(len(b), 32) + self.assertEqual(sizeof(b), 32 * sizeof(c_char)) + self.assertIs(type(b[0]), bytes) + + b = create_string_buffer(b"abc") + self.assertEqual(len(b), 4) # trailing nul char + self.assertEqual(sizeof(b), 4 * sizeof(c_char)) + self.assertIs(type(b[0]), bytes) + self.assertEqual(b[0], b"a") + self.assertEqual(b[:], b"abc\0") + self.assertEqual(b[::], b"abc\0") + self.assertEqual(b[::-1], b"\0cba") + self.assertEqual(b[::2], b"ac") + self.assertEqual(b[::5], b"a") + + self.assertRaises(TypeError, create_string_buffer, "abc") + + def test_buffer_interface(self): + self.assertEqual(len(bytearray(create_string_buffer(0))), 0) + self.assertEqual(len(bytearray(create_string_buffer(1))), 1) + + @need_symbol('c_wchar') + def test_unicode_buffer(self): + b = create_unicode_buffer(32) + self.assertEqual(len(b), 32) + self.assertEqual(sizeof(b), 32 * sizeof(c_wchar)) + self.assertIs(type(b[0]), str) + + b = create_unicode_buffer("abc") + self.assertEqual(len(b), 4) # trailing nul char + self.assertEqual(sizeof(b), 4 * sizeof(c_wchar)) + self.assertIs(type(b[0]), str) + self.assertEqual(b[0], "a") + self.assertEqual(b[:], "abc\0") + self.assertEqual(b[::], "abc\0") + self.assertEqual(b[::-1], "\0cba") + self.assertEqual(b[::2], "ac") + self.assertEqual(b[::5], "a") + + self.assertRaises(TypeError, create_unicode_buffer, b"abc") + + @need_symbol('c_wchar') + def test_unicode_conversion(self): + b = create_unicode_buffer("abc") + self.assertEqual(len(b), 4) # trailing nul char + self.assertEqual(sizeof(b), 4 * sizeof(c_wchar)) + self.assertIs(type(b[0]), str) + self.assertEqual(b[0], "a") + self.assertEqual(b[:], "abc\0") + self.assertEqual(b[::], "abc\0") + self.assertEqual(b[::-1], "\0cba") + self.assertEqual(b[::2], "ac") + self.assertEqual(b[::5], "a") + + @need_symbol('c_wchar') + def test_create_unicode_buffer_non_bmp(self): + expected = 5 if sizeof(c_wchar) == 2 else 3 + for s in '\U00010000\U00100000', '\U00010000\U0010ffff': + b = create_unicode_buffer(s) + self.assertEqual(len(b), expected) + self.assertEqual(b[-1], '\0') + + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_ctypes/test_bytes.py b/Lib/test/test_ctypes/test_bytes.py new file mode 100644 index 0000000..092ec5a --- /dev/null +++ b/Lib/test/test_ctypes/test_bytes.py @@ -0,0 +1,66 @@ +"""Test where byte objects are accepted""" +import unittest +import sys +from ctypes import * + +class BytesTest(unittest.TestCase): + def test_c_char(self): + x = c_char(b"x") + self.assertRaises(TypeError, c_char, "x") + x.value = b"y" + with self.assertRaises(TypeError): + x.value = "y" + c_char.from_param(b"x") + self.assertRaises(TypeError, c_char.from_param, "x") + self.assertIn('xbd', repr(c_char.from_param(b"\xbd"))) + (c_char * 3)(b"a", b"b", b"c") + self.assertRaises(TypeError, c_char * 3, "a", "b", "c") + + def test_c_wchar(self): + x = c_wchar("x") + self.assertRaises(TypeError, c_wchar, b"x") + x.value = "y" + with self.assertRaises(TypeError): + x.value = b"y" + c_wchar.from_param("x") + self.assertRaises(TypeError, c_wchar.from_param, b"x") + (c_wchar * 3)("a", "b", "c") + self.assertRaises(TypeError, c_wchar * 3, b"a", b"b", b"c") + + def test_c_char_p(self): + c_char_p(b"foo bar") + self.assertRaises(TypeError, c_char_p, "foo bar") + + def test_c_wchar_p(self): + c_wchar_p("foo bar") + self.assertRaises(TypeError, c_wchar_p, b"foo bar") + + def test_struct(self): + class X(Structure): + _fields_ = [("a", c_char * 3)] + + x = X(b"abc") + self.assertRaises(TypeError, X, "abc") + self.assertEqual(x.a, b"abc") + self.assertEqual(type(x.a), bytes) + + def test_struct_W(self): + class X(Structure): + _fields_ = [("a", c_wchar * 3)] + + x = X("abc") + self.assertRaises(TypeError, X, b"abc") + self.assertEqual(x.a, "abc") + self.assertEqual(type(x.a), str) + + @unittest.skipUnless(sys.platform == "win32", 'Windows-specific test') + def test_BSTR(self): + from _ctypes import _SimpleCData + class BSTR(_SimpleCData): + _type_ = "X" + + BSTR("abc") + + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/test_ctypes/test_byteswap.py b/Lib/test/test_ctypes/test_byteswap.py new file mode 100644 index 0000000..7e98559 --- /dev/null +++ b/Lib/test/test_ctypes/test_byteswap.py @@ -0,0 +1,364 @@ +import sys, unittest, struct, math, ctypes +from binascii import hexlify + +from ctypes import * + +def bin(s): + return hexlify(memoryview(s)).decode().upper() + +# Each *simple* type that supports different byte orders has an +# __ctype_be__ attribute that specifies the same type in BIG ENDIAN +# byte order, and a __ctype_le__ attribute that is the same type in +# LITTLE ENDIAN byte order. +# +# For Structures and Unions, these types are created on demand. + +class Test(unittest.TestCase): + @unittest.skip('test disabled') + def test_X(self): + print(sys.byteorder, file=sys.stderr) + for i in range(32): + bits = BITS() + setattr(bits, "i%s" % i, 1) + dump(bits) + + def test_slots(self): + class BigPoint(BigEndianStructure): + __slots__ = () + _fields_ = [("x", c_int), ("y", c_int)] + + class LowPoint(LittleEndianStructure): + __slots__ = () + _fields_ = [("x", c_int), ("y", c_int)] + + big = BigPoint() + little = LowPoint() + big.x = 4 + big.y = 2 + little.x = 2 + little.y = 4 + with self.assertRaises(AttributeError): + big.z = 42 + with self.assertRaises(AttributeError): + little.z = 24 + + def test_endian_short(self): + if sys.byteorder == "little": + self.assertIs(c_short.__ctype_le__, c_short) + self.assertIs(c_short.__ctype_be__.__ctype_le__, c_short) + else: + self.assertIs(c_short.__ctype_be__, c_short) + self.assertIs(c_short.__ctype_le__.__ctype_be__, c_short) + s = c_short.__ctype_be__(0x1234) + self.assertEqual(bin(struct.pack(">h", 0x1234)), "1234") + self.assertEqual(bin(s), "1234") + self.assertEqual(s.value, 0x1234) + + s = c_short.__ctype_le__(0x1234) + self.assertEqual(bin(struct.pack("h", 0x1234)), "1234") + self.assertEqual(bin(s), "1234") + self.assertEqual(s.value, 0x1234) + + s = c_ushort.__ctype_le__(0x1234) + self.assertEqual(bin(struct.pack("i", 0x12345678)), "12345678") + self.assertEqual(bin(s), "12345678") + self.assertEqual(s.value, 0x12345678) + + s = c_int.__ctype_le__(0x12345678) + self.assertEqual(bin(struct.pack("I", 0x12345678)), "12345678") + self.assertEqual(bin(s), "12345678") + self.assertEqual(s.value, 0x12345678) + + s = c_uint.__ctype_le__(0x12345678) + self.assertEqual(bin(struct.pack("q", 0x1234567890ABCDEF)), "1234567890ABCDEF") + self.assertEqual(bin(s), "1234567890ABCDEF") + self.assertEqual(s.value, 0x1234567890ABCDEF) + + s = c_longlong.__ctype_le__(0x1234567890ABCDEF) + self.assertEqual(bin(struct.pack("Q", 0x1234567890ABCDEF)), "1234567890ABCDEF") + self.assertEqual(bin(s), "1234567890ABCDEF") + self.assertEqual(s.value, 0x1234567890ABCDEF) + + s = c_ulonglong.__ctype_le__(0x1234567890ABCDEF) + self.assertEqual(bin(struct.pack("f", math.pi)), bin(s)) + + def test_endian_double(self): + if sys.byteorder == "little": + self.assertIs(c_double.__ctype_le__, c_double) + self.assertIs(c_double.__ctype_be__.__ctype_le__, c_double) + else: + self.assertIs(c_double.__ctype_be__, c_double) + self.assertIs(c_double.__ctype_le__.__ctype_be__, c_double) + s = c_double(math.pi) + self.assertEqual(s.value, math.pi) + self.assertEqual(bin(struct.pack("d", math.pi)), bin(s)) + s = c_double.__ctype_le__(math.pi) + self.assertEqual(s.value, math.pi) + self.assertEqual(bin(struct.pack("d", math.pi)), bin(s)) + + def test_endian_other(self): + self.assertIs(c_byte.__ctype_le__, c_byte) + self.assertIs(c_byte.__ctype_be__, c_byte) + + self.assertIs(c_ubyte.__ctype_le__, c_ubyte) + self.assertIs(c_ubyte.__ctype_be__, c_ubyte) + + self.assertIs(c_char.__ctype_le__, c_char) + self.assertIs(c_char.__ctype_be__, c_char) + + def test_struct_fields_unsupported_byte_order(self): + + fields = [ + ("a", c_ubyte), + ("b", c_byte), + ("c", c_short), + ("d", c_ushort), + ("e", c_int), + ("f", c_uint), + ("g", c_long), + ("h", c_ulong), + ("i", c_longlong), + ("k", c_ulonglong), + ("l", c_float), + ("m", c_double), + ("n", c_char), + ("b1", c_byte, 3), + ("b2", c_byte, 3), + ("b3", c_byte, 2), + ("a", c_int * 3 * 3 * 3) + ] + + # these fields do not support different byte order: + for typ in c_wchar, c_void_p, POINTER(c_int): + with self.assertRaises(TypeError): + class T(BigEndianStructure if sys.byteorder == "little" else LittleEndianStructure): + _fields_ = fields + [("x", typ)] + + + def test_struct_struct(self): + # nested structures with different byteorders + + # create nested structures with given byteorders and set memory to data + + for nested, data in ( + (BigEndianStructure, b'\0\0\0\1\0\0\0\2'), + (LittleEndianStructure, b'\1\0\0\0\2\0\0\0'), + ): + for parent in ( + BigEndianStructure, + LittleEndianStructure, + Structure, + ): + class NestedStructure(nested): + _fields_ = [("x", c_uint32), + ("y", c_uint32)] + + class TestStructure(parent): + _fields_ = [("point", NestedStructure)] + + self.assertEqual(len(data), sizeof(TestStructure)) + ptr = POINTER(TestStructure) + s = cast(data, ptr)[0] + del ctypes._pointer_type_cache[TestStructure] + self.assertEqual(s.point.x, 1) + self.assertEqual(s.point.y, 2) + + def test_struct_field_alignment(self): + # standard packing in struct uses no alignment. + # So, we have to align using pad bytes. + # + # Unaligned accesses will crash Python (on those platforms that + # don't allow it, like sparc solaris). + if sys.byteorder == "little": + base = BigEndianStructure + fmt = ">bxhid" + else: + base = LittleEndianStructure + fmt = " float -> double + import math + self.check_type(c_float, math.e) + self.check_type(c_float, -math.e) + + def test_double(self): + self.check_type(c_double, 3.14) + self.check_type(c_double, -3.14) + + def test_longdouble(self): + self.check_type(c_longdouble, 3.14) + self.check_type(c_longdouble, -3.14) + + def test_char(self): + self.check_type(c_char, b"x") + self.check_type(c_char, b"a") + + # disabled: would now (correctly) raise a RuntimeWarning about + # a memory leak. A callback function cannot return a non-integral + # C type without causing a memory leak. + @unittest.skip('test disabled') + def test_char_p(self): + self.check_type(c_char_p, "abc") + self.check_type(c_char_p, "def") + + def test_pyobject(self): + o = () + from sys import getrefcount as grc + for o in (), [], object(): + initial = grc(o) + # This call leaks a reference to 'o'... + self.check_type(py_object, o) + before = grc(o) + # ...but this call doesn't leak any more. Where is the refcount? + self.check_type(py_object, o) + after = grc(o) + self.assertEqual((after, o), (before, o)) + + def test_unsupported_restype_1(self): + # Only "fundamental" result types are supported for callback + # functions, the type must have a non-NULL stgdict->setfunc. + # POINTER(c_double), for example, is not supported. + + prototype = self.functype.__func__(POINTER(c_double)) + # The type is checked when the prototype is called + self.assertRaises(TypeError, prototype, lambda: None) + + def test_unsupported_restype_2(self): + prototype = self.functype.__func__(object) + self.assertRaises(TypeError, prototype, lambda: None) + + def test_issue_7959(self): + proto = self.functype.__func__(None) + + class X(object): + def func(self): pass + def __init__(self): + self.v = proto(self.func) + + import gc + for i in range(32): + X() + gc.collect() + live = [x for x in gc.get_objects() + if isinstance(x, X)] + self.assertEqual(len(live), 0) + + def test_issue12483(self): + import gc + class Nasty: + def __del__(self): + gc.collect() + CFUNCTYPE(None)(lambda x=Nasty(): None) + + +@need_symbol('WINFUNCTYPE') +class StdcallCallbacks(Callbacks): + try: + functype = WINFUNCTYPE + except NameError: + pass + +################################################################ + +class SampleCallbacksTestCase(unittest.TestCase): + + def test_integrate(self): + # Derived from some then non-working code, posted by David Foster + dll = CDLL(_ctypes_test.__file__) + + # The function prototype called by 'integrate': double func(double); + CALLBACK = CFUNCTYPE(c_double, c_double) + + # The integrate function itself, exposed from the _ctypes_test dll + integrate = dll.integrate + integrate.argtypes = (c_double, c_double, CALLBACK, c_long) + integrate.restype = c_double + + def func(x): + return x**2 + + result = integrate(0.0, 1.0, CALLBACK(func), 10) + diff = abs(result - 1./3.) + + self.assertLess(diff, 0.01, "%s not less than 0.01" % diff) + + def test_issue_8959_a(self): + from ctypes.util import find_library + libc_path = find_library("c") + if not libc_path: + self.skipTest('could not find libc') + libc = CDLL(libc_path) + + @CFUNCTYPE(c_int, POINTER(c_int), POINTER(c_int)) + def cmp_func(a, b): + return a[0] - b[0] + + array = (c_int * 5)(5, 1, 99, 7, 33) + + libc.qsort(array, len(array), sizeof(c_int), cmp_func) + self.assertEqual(array[:], [1, 5, 7, 33, 99]) + + @need_symbol('WINFUNCTYPE') + def test_issue_8959_b(self): + from ctypes.wintypes import BOOL, HWND, LPARAM + global windowCount + windowCount = 0 + + @WINFUNCTYPE(BOOL, HWND, LPARAM) + def EnumWindowsCallbackFunc(hwnd, lParam): + global windowCount + windowCount += 1 + return True #Allow windows to keep enumerating + + windll.user32.EnumWindows(EnumWindowsCallbackFunc, 0) + + def test_callback_register_int(self): + # Issue #8275: buggy handling of callback args under Win64 + # NOTE: should be run on release builds as well + dll = CDLL(_ctypes_test.__file__) + CALLBACK = CFUNCTYPE(c_int, c_int, c_int, c_int, c_int, c_int) + # All this function does is call the callback with its args squared + func = dll._testfunc_cbk_reg_int + func.argtypes = (c_int, c_int, c_int, c_int, c_int, CALLBACK) + func.restype = c_int + + def callback(a, b, c, d, e): + return a + b + c + d + e + + result = func(2, 3, 4, 5, 6, CALLBACK(callback)) + self.assertEqual(result, callback(2*2, 3*3, 4*4, 5*5, 6*6)) + + def test_callback_register_double(self): + # Issue #8275: buggy handling of callback args under Win64 + # NOTE: should be run on release builds as well + dll = CDLL(_ctypes_test.__file__) + CALLBACK = CFUNCTYPE(c_double, c_double, c_double, c_double, + c_double, c_double) + # All this function does is call the callback with its args squared + func = dll._testfunc_cbk_reg_double + func.argtypes = (c_double, c_double, c_double, + c_double, c_double, CALLBACK) + func.restype = c_double + + def callback(a, b, c, d, e): + return a + b + c + d + e + + result = func(1.1, 2.2, 3.3, 4.4, 5.5, CALLBACK(callback)) + self.assertEqual(result, + callback(1.1*1.1, 2.2*2.2, 3.3*3.3, 4.4*4.4, 5.5*5.5)) + + def test_callback_large_struct(self): + class Check: pass + + # This should mirror the structure in Modules/_ctypes/_ctypes_test.c + class X(Structure): + _fields_ = [ + ('first', c_ulong), + ('second', c_ulong), + ('third', c_ulong), + ] + + def callback(check, s): + check.first = s.first + check.second = s.second + check.third = s.third + # See issue #29565. + # The structure should be passed by value, so + # any changes to it should not be reflected in + # the value passed + s.first = s.second = s.third = 0x0badf00d + + check = Check() + s = X() + s.first = 0xdeadbeef + s.second = 0xcafebabe + s.third = 0x0bad1dea + + CALLBACK = CFUNCTYPE(None, X) + dll = CDLL(_ctypes_test.__file__) + func = dll._testfunc_cbk_large_struct + func.argtypes = (X, CALLBACK) + func.restype = None + # the function just calls the callback with the passed structure + func(s, CALLBACK(functools.partial(callback, check))) + self.assertEqual(check.first, s.first) + self.assertEqual(check.second, s.second) + self.assertEqual(check.third, s.third) + self.assertEqual(check.first, 0xdeadbeef) + self.assertEqual(check.second, 0xcafebabe) + self.assertEqual(check.third, 0x0bad1dea) + # See issue #29565. + # Ensure that the original struct is unchanged. + self.assertEqual(s.first, check.first) + self.assertEqual(s.second, check.second) + self.assertEqual(s.third, check.third) + + def test_callback_too_many_args(self): + def func(*args): + return len(args) + + # valid call with nargs <= CTYPES_MAX_ARGCOUNT + proto = CFUNCTYPE(c_int, *(c_int,) * CTYPES_MAX_ARGCOUNT) + cb = proto(func) + args1 = (1,) * CTYPES_MAX_ARGCOUNT + self.assertEqual(cb(*args1), CTYPES_MAX_ARGCOUNT) + + # invalid call with nargs > CTYPES_MAX_ARGCOUNT + args2 = (1,) * (CTYPES_MAX_ARGCOUNT + 1) + with self.assertRaises(ArgumentError): + cb(*args2) + + # error when creating the type with too many arguments + with self.assertRaises(ArgumentError): + CFUNCTYPE(c_int, *(c_int,) * (CTYPES_MAX_ARGCOUNT + 1)) + + def test_convert_result_error(self): + def func(): + return ("tuple",) + + proto = CFUNCTYPE(c_int) + ctypes_func = proto(func) + with support.catch_unraisable_exception() as cm: + # don't test the result since it is an uninitialized value + result = ctypes_func() + + self.assertIsInstance(cm.unraisable.exc_value, TypeError) + self.assertEqual(cm.unraisable.err_msg, + "Exception ignored on converting result " + "of ctypes callback function") + self.assertIs(cm.unraisable.object, func) + + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/test_ctypes/test_cast.py b/Lib/test/test_ctypes/test_cast.py new file mode 100644 index 0000000..7ee23b1 --- /dev/null +++ b/Lib/test/test_ctypes/test_cast.py @@ -0,0 +1,99 @@ +from ctypes import * +from test.test_ctypes import need_symbol +import unittest +import sys + +class Test(unittest.TestCase): + + def test_array2pointer(self): + array = (c_int * 3)(42, 17, 2) + + # casting an array to a pointer works. + ptr = cast(array, POINTER(c_int)) + self.assertEqual([ptr[i] for i in range(3)], [42, 17, 2]) + + if 2*sizeof(c_short) == sizeof(c_int): + ptr = cast(array, POINTER(c_short)) + if sys.byteorder == "little": + self.assertEqual([ptr[i] for i in range(6)], + [42, 0, 17, 0, 2, 0]) + else: + self.assertEqual([ptr[i] for i in range(6)], + [0, 42, 0, 17, 0, 2]) + + def test_address2pointer(self): + array = (c_int * 3)(42, 17, 2) + + address = addressof(array) + ptr = cast(c_void_p(address), POINTER(c_int)) + self.assertEqual([ptr[i] for i in range(3)], [42, 17, 2]) + + ptr = cast(address, POINTER(c_int)) + self.assertEqual([ptr[i] for i in range(3)], [42, 17, 2]) + + def test_p2a_objects(self): + array = (c_char_p * 5)() + self.assertEqual(array._objects, None) + array[0] = b"foo bar" + self.assertEqual(array._objects, {'0': b"foo bar"}) + + p = cast(array, POINTER(c_char_p)) + # array and p share a common _objects attribute + self.assertIs(p._objects, array._objects) + self.assertEqual(array._objects, {'0': b"foo bar", id(array): array}) + p[0] = b"spam spam" + self.assertEqual(p._objects, {'0': b"spam spam", id(array): array}) + self.assertIs(array._objects, p._objects) + p[1] = b"foo bar" + self.assertEqual(p._objects, {'1': b'foo bar', '0': b"spam spam", id(array): array}) + self.assertIs(array._objects, p._objects) + + def test_other(self): + p = cast((c_int * 4)(1, 2, 3, 4), POINTER(c_int)) + self.assertEqual(p[:4], [1,2, 3, 4]) + self.assertEqual(p[:4:], [1, 2, 3, 4]) + self.assertEqual(p[3:-1:-1], [4, 3, 2, 1]) + self.assertEqual(p[:4:3], [1, 4]) + c_int() + self.assertEqual(p[:4], [1, 2, 3, 4]) + self.assertEqual(p[:4:], [1, 2, 3, 4]) + self.assertEqual(p[3:-1:-1], [4, 3, 2, 1]) + self.assertEqual(p[:4:3], [1, 4]) + p[2] = 96 + self.assertEqual(p[:4], [1, 2, 96, 4]) + self.assertEqual(p[:4:], [1, 2, 96, 4]) + self.assertEqual(p[3:-1:-1], [4, 96, 2, 1]) + self.assertEqual(p[:4:3], [1, 4]) + c_int() + self.assertEqual(p[:4], [1, 2, 96, 4]) + self.assertEqual(p[:4:], [1, 2, 96, 4]) + self.assertEqual(p[3:-1:-1], [4, 96, 2, 1]) + self.assertEqual(p[:4:3], [1, 4]) + + def test_char_p(self): + # This didn't work: bad argument to internal function + s = c_char_p(b"hiho") + self.assertEqual(cast(cast(s, c_void_p), c_char_p).value, + b"hiho") + + @need_symbol('c_wchar_p') + def test_wchar_p(self): + s = c_wchar_p("hiho") + self.assertEqual(cast(cast(s, c_void_p), c_wchar_p).value, + "hiho") + + def test_bad_type_arg(self): + # The type argument must be a ctypes pointer type. + array_type = c_byte * sizeof(c_int) + array = array_type() + self.assertRaises(TypeError, cast, array, None) + self.assertRaises(TypeError, cast, array, array_type) + class Struct(Structure): + _fields_ = [("a", c_int)] + self.assertRaises(TypeError, cast, array, Struct) + class MyUnion(Union): + _fields_ = [("a", c_int)] + self.assertRaises(TypeError, cast, array, MyUnion) + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_ctypes/test_cfuncs.py b/Lib/test/test_ctypes/test_cfuncs.py new file mode 100644 index 0000000..0a9394b --- /dev/null +++ b/Lib/test/test_ctypes/test_cfuncs.py @@ -0,0 +1,212 @@ +# A lot of failures in these tests on Mac OS X. +# Byte order related? + +import unittest +from ctypes import * +from test.test_ctypes import need_symbol + +import _ctypes_test + +class CFunctions(unittest.TestCase): + _dll = CDLL(_ctypes_test.__file__) + + def S(self): + return c_longlong.in_dll(self._dll, "last_tf_arg_s").value + def U(self): + return c_ulonglong.in_dll(self._dll, "last_tf_arg_u").value + + def test_byte(self): + self._dll.tf_b.restype = c_byte + self._dll.tf_b.argtypes = (c_byte,) + self.assertEqual(self._dll.tf_b(-126), -42) + self.assertEqual(self.S(), -126) + + def test_byte_plus(self): + self._dll.tf_bb.restype = c_byte + self._dll.tf_bb.argtypes = (c_byte, c_byte) + self.assertEqual(self._dll.tf_bb(0, -126), -42) + self.assertEqual(self.S(), -126) + + def test_ubyte(self): + self._dll.tf_B.restype = c_ubyte + self._dll.tf_B.argtypes = (c_ubyte,) + self.assertEqual(self._dll.tf_B(255), 85) + self.assertEqual(self.U(), 255) + + def test_ubyte_plus(self): + self._dll.tf_bB.restype = c_ubyte + self._dll.tf_bB.argtypes = (c_byte, c_ubyte) + self.assertEqual(self._dll.tf_bB(0, 255), 85) + self.assertEqual(self.U(), 255) + + def test_short(self): + self._dll.tf_h.restype = c_short + self._dll.tf_h.argtypes = (c_short,) + self.assertEqual(self._dll.tf_h(-32766), -10922) + self.assertEqual(self.S(), -32766) + + def test_short_plus(self): + self._dll.tf_bh.restype = c_short + self._dll.tf_bh.argtypes = (c_byte, c_short) + self.assertEqual(self._dll.tf_bh(0, -32766), -10922) + self.assertEqual(self.S(), -32766) + + def test_ushort(self): + self._dll.tf_H.restype = c_ushort + self._dll.tf_H.argtypes = (c_ushort,) + self.assertEqual(self._dll.tf_H(65535), 21845) + self.assertEqual(self.U(), 65535) + + def test_ushort_plus(self): + self._dll.tf_bH.restype = c_ushort + self._dll.tf_bH.argtypes = (c_byte, c_ushort) + self.assertEqual(self._dll.tf_bH(0, 65535), 21845) + self.assertEqual(self.U(), 65535) + + def test_int(self): + self._dll.tf_i.restype = c_int + self._dll.tf_i.argtypes = (c_int,) + self.assertEqual(self._dll.tf_i(-2147483646), -715827882) + self.assertEqual(self.S(), -2147483646) + + def test_int_plus(self): + self._dll.tf_bi.restype = c_int + self._dll.tf_bi.argtypes = (c_byte, c_int) + self.assertEqual(self._dll.tf_bi(0, -2147483646), -715827882) + self.assertEqual(self.S(), -2147483646) + + def test_uint(self): + self._dll.tf_I.restype = c_uint + self._dll.tf_I.argtypes = (c_uint,) + self.assertEqual(self._dll.tf_I(4294967295), 1431655765) + self.assertEqual(self.U(), 4294967295) + + def test_uint_plus(self): + self._dll.tf_bI.restype = c_uint + self._dll.tf_bI.argtypes = (c_byte, c_uint) + self.assertEqual(self._dll.tf_bI(0, 4294967295), 1431655765) + self.assertEqual(self.U(), 4294967295) + + def test_long(self): + self._dll.tf_l.restype = c_long + self._dll.tf_l.argtypes = (c_long,) + self.assertEqual(self._dll.tf_l(-2147483646), -715827882) + self.assertEqual(self.S(), -2147483646) + + def test_long_plus(self): + self._dll.tf_bl.restype = c_long + self._dll.tf_bl.argtypes = (c_byte, c_long) + self.assertEqual(self._dll.tf_bl(0, -2147483646), -715827882) + self.assertEqual(self.S(), -2147483646) + + def test_ulong(self): + self._dll.tf_L.restype = c_ulong + self._dll.tf_L.argtypes = (c_ulong,) + self.assertEqual(self._dll.tf_L(4294967295), 1431655765) + self.assertEqual(self.U(), 4294967295) + + def test_ulong_plus(self): + self._dll.tf_bL.restype = c_ulong + self._dll.tf_bL.argtypes = (c_char, c_ulong) + self.assertEqual(self._dll.tf_bL(b' ', 4294967295), 1431655765) + self.assertEqual(self.U(), 4294967295) + + def test_longlong(self): + self._dll.tf_q.restype = c_longlong + self._dll.tf_q.argtypes = (c_longlong, ) + self.assertEqual(self._dll.tf_q(-9223372036854775806), -3074457345618258602) + self.assertEqual(self.S(), -9223372036854775806) + + def test_longlong_plus(self): + self._dll.tf_bq.restype = c_longlong + self._dll.tf_bq.argtypes = (c_byte, c_longlong) + self.assertEqual(self._dll.tf_bq(0, -9223372036854775806), -3074457345618258602) + self.assertEqual(self.S(), -9223372036854775806) + + def test_ulonglong(self): + self._dll.tf_Q.restype = c_ulonglong + self._dll.tf_Q.argtypes = (c_ulonglong, ) + self.assertEqual(self._dll.tf_Q(18446744073709551615), 6148914691236517205) + self.assertEqual(self.U(), 18446744073709551615) + + def test_ulonglong_plus(self): + self._dll.tf_bQ.restype = c_ulonglong + self._dll.tf_bQ.argtypes = (c_byte, c_ulonglong) + self.assertEqual(self._dll.tf_bQ(0, 18446744073709551615), 6148914691236517205) + self.assertEqual(self.U(), 18446744073709551615) + + def test_float(self): + self._dll.tf_f.restype = c_float + self._dll.tf_f.argtypes = (c_float,) + self.assertEqual(self._dll.tf_f(-42.), -14.) + self.assertEqual(self.S(), -42) + + def test_float_plus(self): + self._dll.tf_bf.restype = c_float + self._dll.tf_bf.argtypes = (c_byte, c_float) + self.assertEqual(self._dll.tf_bf(0, -42.), -14.) + self.assertEqual(self.S(), -42) + + def test_double(self): + self._dll.tf_d.restype = c_double + self._dll.tf_d.argtypes = (c_double,) + self.assertEqual(self._dll.tf_d(42.), 14.) + self.assertEqual(self.S(), 42) + + def test_double_plus(self): + self._dll.tf_bd.restype = c_double + self._dll.tf_bd.argtypes = (c_byte, c_double) + self.assertEqual(self._dll.tf_bd(0, 42.), 14.) + self.assertEqual(self.S(), 42) + + def test_longdouble(self): + self._dll.tf_D.restype = c_longdouble + self._dll.tf_D.argtypes = (c_longdouble,) + self.assertEqual(self._dll.tf_D(42.), 14.) + self.assertEqual(self.S(), 42) + + def test_longdouble_plus(self): + self._dll.tf_bD.restype = c_longdouble + self._dll.tf_bD.argtypes = (c_byte, c_longdouble) + self.assertEqual(self._dll.tf_bD(0, 42.), 14.) + self.assertEqual(self.S(), 42) + + def test_callwithresult(self): + def process_result(result): + return result * 2 + self._dll.tf_i.restype = process_result + self._dll.tf_i.argtypes = (c_int,) + self.assertEqual(self._dll.tf_i(42), 28) + self.assertEqual(self.S(), 42) + self.assertEqual(self._dll.tf_i(-42), -28) + self.assertEqual(self.S(), -42) + + def test_void(self): + self._dll.tv_i.restype = None + self._dll.tv_i.argtypes = (c_int,) + self.assertEqual(self._dll.tv_i(42), None) + self.assertEqual(self.S(), 42) + self.assertEqual(self._dll.tv_i(-42), None) + self.assertEqual(self.S(), -42) + +# The following repeats the above tests with stdcall functions (where +# they are available) +try: + WinDLL +except NameError: + def stdcall_dll(*_): pass +else: + class stdcall_dll(WinDLL): + def __getattr__(self, name): + if name[:2] == '__' and name[-2:] == '__': + raise AttributeError(name) + func = self._FuncPtr(("s_" + name, self)) + setattr(self, name, func) + return func + +@need_symbol('WinDLL') +class stdcallCFunctions(CFunctions): + _dll = stdcall_dll(_ctypes_test.__file__) + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/test_ctypes/test_checkretval.py b/Lib/test/test_ctypes/test_checkretval.py new file mode 100644 index 0000000..1492099 --- /dev/null +++ b/Lib/test/test_ctypes/test_checkretval.py @@ -0,0 +1,36 @@ +import unittest + +from ctypes import * +from test.test_ctypes import need_symbol + +class CHECKED(c_int): + def _check_retval_(value): + # Receives a CHECKED instance. + return str(value.value) + _check_retval_ = staticmethod(_check_retval_) + +class Test(unittest.TestCase): + + def test_checkretval(self): + + import _ctypes_test + dll = CDLL(_ctypes_test.__file__) + self.assertEqual(42, dll._testfunc_p_p(42)) + + dll._testfunc_p_p.restype = CHECKED + self.assertEqual("42", dll._testfunc_p_p(42)) + + dll._testfunc_p_p.restype = None + self.assertEqual(None, dll._testfunc_p_p(42)) + + del dll._testfunc_p_p.restype + self.assertEqual(42, dll._testfunc_p_p(42)) + + @need_symbol('oledll') + def test_oledll(self): + self.assertRaises(OSError, + oledll.oleaut32.CreateTypeLib2, + 0, None, None) + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_ctypes/test_delattr.py b/Lib/test/test_ctypes/test_delattr.py new file mode 100644 index 0000000..0f4d586 --- /dev/null +++ b/Lib/test/test_ctypes/test_delattr.py @@ -0,0 +1,21 @@ +import unittest +from ctypes import * + +class X(Structure): + _fields_ = [("foo", c_int)] + +class TestCase(unittest.TestCase): + def test_simple(self): + self.assertRaises(TypeError, + delattr, c_int(42), "value") + + def test_chararray(self): + self.assertRaises(TypeError, + delattr, (c_char * 5)(), "value") + + def test_struct(self): + self.assertRaises(TypeError, + delattr, X(), "foo") + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_ctypes/test_errno.py b/Lib/test/test_ctypes/test_errno.py new file mode 100644 index 0000000..3685164 --- /dev/null +++ b/Lib/test/test_ctypes/test_errno.py @@ -0,0 +1,76 @@ +import unittest, os, errno +import threading + +from ctypes import * +from ctypes.util import find_library + +class Test(unittest.TestCase): + def test_open(self): + libc_name = find_library("c") + if libc_name is None: + raise unittest.SkipTest("Unable to find C library") + libc = CDLL(libc_name, use_errno=True) + if os.name == "nt": + libc_open = libc._open + else: + libc_open = libc.open + + libc_open.argtypes = c_char_p, c_int + + self.assertEqual(libc_open(b"", 0), -1) + self.assertEqual(get_errno(), errno.ENOENT) + + self.assertEqual(set_errno(32), errno.ENOENT) + self.assertEqual(get_errno(), 32) + + def _worker(): + set_errno(0) + + libc = CDLL(libc_name, use_errno=False) + if os.name == "nt": + libc_open = libc._open + else: + libc_open = libc.open + libc_open.argtypes = c_char_p, c_int + self.assertEqual(libc_open(b"", 0), -1) + self.assertEqual(get_errno(), 0) + + t = threading.Thread(target=_worker) + t.start() + t.join() + + self.assertEqual(get_errno(), 32) + set_errno(0) + + @unittest.skipUnless(os.name == "nt", 'Test specific to Windows') + def test_GetLastError(self): + dll = WinDLL("kernel32", use_last_error=True) + GetModuleHandle = dll.GetModuleHandleA + GetModuleHandle.argtypes = [c_wchar_p] + + self.assertEqual(0, GetModuleHandle("foo")) + self.assertEqual(get_last_error(), 126) + + self.assertEqual(set_last_error(32), 126) + self.assertEqual(get_last_error(), 32) + + def _worker(): + set_last_error(0) + + dll = WinDLL("kernel32", use_last_error=False) + GetModuleHandle = dll.GetModuleHandleW + GetModuleHandle.argtypes = [c_wchar_p] + GetModuleHandle("bar") + + self.assertEqual(get_last_error(), 0) + + t = threading.Thread(target=_worker) + t.start() + t.join() + + self.assertEqual(get_last_error(), 32) + + set_last_error(0) + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_ctypes/test_find.py b/Lib/test/test_ctypes/test_find.py new file mode 100644 index 0000000..1ff9d01 --- /dev/null +++ b/Lib/test/test_ctypes/test_find.py @@ -0,0 +1,127 @@ +import unittest +import unittest.mock +import os.path +import sys +import test.support +from test.support import os_helper +from ctypes import * +from ctypes.util import find_library + +# On some systems, loading the OpenGL libraries needs the RTLD_GLOBAL mode. +class Test_OpenGL_libs(unittest.TestCase): + @classmethod + def setUpClass(cls): + lib_gl = lib_glu = lib_gle = None + if sys.platform == "win32": + lib_gl = find_library("OpenGL32") + lib_glu = find_library("Glu32") + elif sys.platform == "darwin": + lib_gl = lib_glu = find_library("OpenGL") + else: + lib_gl = find_library("GL") + lib_glu = find_library("GLU") + lib_gle = find_library("gle") + + ## print, for debugging + if test.support.verbose: + print("OpenGL libraries:") + for item in (("GL", lib_gl), + ("GLU", lib_glu), + ("gle", lib_gle)): + print("\t", item) + + cls.gl = cls.glu = cls.gle = None + if lib_gl: + try: + cls.gl = CDLL(lib_gl, mode=RTLD_GLOBAL) + except OSError: + pass + if lib_glu: + try: + cls.glu = CDLL(lib_glu, RTLD_GLOBAL) + except OSError: + pass + if lib_gle: + try: + cls.gle = CDLL(lib_gle) + except OSError: + pass + + @classmethod + def tearDownClass(cls): + cls.gl = cls.glu = cls.gle = None + + def test_gl(self): + if self.gl is None: + self.skipTest('lib_gl not available') + self.gl.glClearIndex + + def test_glu(self): + if self.glu is None: + self.skipTest('lib_glu not available') + self.glu.gluBeginCurve + + def test_gle(self): + if self.gle is None: + self.skipTest('lib_gle not available') + self.gle.gleGetJoinStyle + + def test_shell_injection(self): + result = find_library('; echo Hello shell > ' + os_helper.TESTFN) + self.assertFalse(os.path.lexists(os_helper.TESTFN)) + self.assertIsNone(result) + + +@unittest.skipUnless(sys.platform.startswith('linux'), + 'Test only valid for Linux') +class FindLibraryLinux(unittest.TestCase): + def test_find_on_libpath(self): + import subprocess + import tempfile + + try: + p = subprocess.Popen(['gcc', '--version'], stdout=subprocess.PIPE, + stderr=subprocess.DEVNULL) + out, _ = p.communicate() + except OSError: + raise unittest.SkipTest('gcc, needed for test, not available') + with tempfile.TemporaryDirectory() as d: + # create an empty temporary file + srcname = os.path.join(d, 'dummy.c') + libname = 'py_ctypes_test_dummy' + dstname = os.path.join(d, 'lib%s.so' % libname) + with open(srcname, 'wb') as f: + pass + self.assertTrue(os.path.exists(srcname)) + # compile the file to a shared library + cmd = ['gcc', '-o', dstname, '--shared', + '-Wl,-soname,lib%s.so' % libname, srcname] + out = subprocess.check_output(cmd) + self.assertTrue(os.path.exists(dstname)) + # now check that the .so can't be found (since not in + # LD_LIBRARY_PATH) + self.assertIsNone(find_library(libname)) + # now add the location to LD_LIBRARY_PATH + with os_helper.EnvironmentVarGuard() as env: + KEY = 'LD_LIBRARY_PATH' + if KEY not in env: + v = d + else: + v = '%s:%s' % (env[KEY], d) + env.set(KEY, v) + # now check that the .so can be found (since in + # LD_LIBRARY_PATH) + self.assertEqual(find_library(libname), 'lib%s.so' % libname) + + def test_find_library_with_gcc(self): + with unittest.mock.patch("ctypes.util._findSoname_ldconfig", lambda *args: None): + self.assertNotEqual(find_library('c'), None) + + def test_find_library_with_ld(self): + with unittest.mock.patch("ctypes.util._findSoname_ldconfig", lambda *args: None), \ + unittest.mock.patch("ctypes.util._findLib_gcc", lambda *args: None): + self.assertNotEqual(find_library('c'), None) + + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_ctypes/test_frombuffer.py b/Lib/test/test_ctypes/test_frombuffer.py new file mode 100644 index 0000000..55c2443 --- /dev/null +++ b/Lib/test/test_ctypes/test_frombuffer.py @@ -0,0 +1,141 @@ +from ctypes import * +import array +import gc +import unittest + +class X(Structure): + _fields_ = [("c_int", c_int)] + init_called = False + def __init__(self): + self._init_called = True + +class Test(unittest.TestCase): + def test_from_buffer(self): + a = array.array("i", range(16)) + x = (c_int * 16).from_buffer(a) + + y = X.from_buffer(a) + self.assertEqual(y.c_int, a[0]) + self.assertFalse(y.init_called) + + self.assertEqual(x[:], a.tolist()) + + a[0], a[-1] = 200, -200 + self.assertEqual(x[:], a.tolist()) + + self.assertRaises(BufferError, a.append, 100) + self.assertRaises(BufferError, a.pop) + + del x; del y; gc.collect(); gc.collect(); gc.collect() + a.append(100) + a.pop() + x = (c_int * 16).from_buffer(a) + + self.assertIn(a, [obj.obj if isinstance(obj, memoryview) else obj + for obj in x._objects.values()]) + + expected = x[:] + del a; gc.collect(); gc.collect(); gc.collect() + self.assertEqual(x[:], expected) + + with self.assertRaisesRegex(TypeError, "not writable"): + (c_char * 16).from_buffer(b"a" * 16) + with self.assertRaisesRegex(TypeError, "not writable"): + (c_char * 16).from_buffer(memoryview(b"a" * 16)) + with self.assertRaisesRegex(TypeError, "not C contiguous"): + (c_char * 16).from_buffer(memoryview(bytearray(b"a" * 16))[::-1]) + msg = "bytes-like object is required" + with self.assertRaisesRegex(TypeError, msg): + (c_char * 16).from_buffer("a" * 16) + + def test_fortran_contiguous(self): + try: + import _testbuffer + except ImportError as err: + self.skipTest(str(err)) + flags = _testbuffer.ND_WRITABLE | _testbuffer.ND_FORTRAN + array = _testbuffer.ndarray( + [97] * 16, format="B", shape=[4, 4], flags=flags) + with self.assertRaisesRegex(TypeError, "not C contiguous"): + (c_char * 16).from_buffer(array) + array = memoryview(array) + self.assertTrue(array.f_contiguous) + self.assertFalse(array.c_contiguous) + with self.assertRaisesRegex(TypeError, "not C contiguous"): + (c_char * 16).from_buffer(array) + + def test_from_buffer_with_offset(self): + a = array.array("i", range(16)) + x = (c_int * 15).from_buffer(a, sizeof(c_int)) + + self.assertEqual(x[:], a.tolist()[1:]) + with self.assertRaises(ValueError): + c_int.from_buffer(a, -1) + with self.assertRaises(ValueError): + (c_int * 16).from_buffer(a, sizeof(c_int)) + with self.assertRaises(ValueError): + (c_int * 1).from_buffer(a, 16 * sizeof(c_int)) + + def test_from_buffer_memoryview(self): + a = [c_char.from_buffer(memoryview(bytearray(b'a')))] + a.append(a) + del a + gc.collect() # Should not crash + + def test_from_buffer_copy(self): + a = array.array("i", range(16)) + x = (c_int * 16).from_buffer_copy(a) + + y = X.from_buffer_copy(a) + self.assertEqual(y.c_int, a[0]) + self.assertFalse(y.init_called) + + self.assertEqual(x[:], list(range(16))) + + a[0], a[-1] = 200, -200 + self.assertEqual(x[:], list(range(16))) + + a.append(100) + self.assertEqual(x[:], list(range(16))) + + self.assertEqual(x._objects, None) + + del a; gc.collect(); gc.collect(); gc.collect() + self.assertEqual(x[:], list(range(16))) + + x = (c_char * 16).from_buffer_copy(b"a" * 16) + self.assertEqual(x[:], b"a" * 16) + with self.assertRaises(TypeError): + (c_char * 16).from_buffer_copy("a" * 16) + + def test_from_buffer_copy_with_offset(self): + a = array.array("i", range(16)) + x = (c_int * 15).from_buffer_copy(a, sizeof(c_int)) + + self.assertEqual(x[:], a.tolist()[1:]) + with self.assertRaises(ValueError): + c_int.from_buffer_copy(a, -1) + with self.assertRaises(ValueError): + (c_int * 16).from_buffer_copy(a, sizeof(c_int)) + with self.assertRaises(ValueError): + (c_int * 1).from_buffer_copy(a, 16 * sizeof(c_int)) + + def test_abstract(self): + from ctypes import _Pointer, _SimpleCData, _CFuncPtr + + self.assertRaises(TypeError, Array.from_buffer, bytearray(10)) + self.assertRaises(TypeError, Structure.from_buffer, bytearray(10)) + self.assertRaises(TypeError, Union.from_buffer, bytearray(10)) + self.assertRaises(TypeError, _CFuncPtr.from_buffer, bytearray(10)) + self.assertRaises(TypeError, _Pointer.from_buffer, bytearray(10)) + self.assertRaises(TypeError, _SimpleCData.from_buffer, bytearray(10)) + + self.assertRaises(TypeError, Array.from_buffer_copy, b"123") + self.assertRaises(TypeError, Structure.from_buffer_copy, b"123") + self.assertRaises(TypeError, Union.from_buffer_copy, b"123") + self.assertRaises(TypeError, _CFuncPtr.from_buffer_copy, b"123") + self.assertRaises(TypeError, _Pointer.from_buffer_copy, b"123") + self.assertRaises(TypeError, _SimpleCData.from_buffer_copy, b"123") + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/test_ctypes/test_funcptr.py b/Lib/test/test_ctypes/test_funcptr.py new file mode 100644 index 0000000..e0b9b54 --- /dev/null +++ b/Lib/test/test_ctypes/test_funcptr.py @@ -0,0 +1,132 @@ +import unittest +from ctypes import * + +try: + WINFUNCTYPE +except NameError: + # fake to enable this test on Linux + WINFUNCTYPE = CFUNCTYPE + +import _ctypes_test +lib = CDLL(_ctypes_test.__file__) + +class CFuncPtrTestCase(unittest.TestCase): + def test_basic(self): + X = WINFUNCTYPE(c_int, c_int, c_int) + + def func(*args): + return len(args) + + x = X(func) + self.assertEqual(x.restype, c_int) + self.assertEqual(x.argtypes, (c_int, c_int)) + self.assertEqual(sizeof(x), sizeof(c_voidp)) + self.assertEqual(sizeof(X), sizeof(c_voidp)) + + def test_first(self): + StdCallback = WINFUNCTYPE(c_int, c_int, c_int) + CdeclCallback = CFUNCTYPE(c_int, c_int, c_int) + + def func(a, b): + return a + b + + s = StdCallback(func) + c = CdeclCallback(func) + + self.assertEqual(s(1, 2), 3) + self.assertEqual(c(1, 2), 3) + # The following no longer raises a TypeError - it is now + # possible, as in C, to call cdecl functions with more parameters. + #self.assertRaises(TypeError, c, 1, 2, 3) + self.assertEqual(c(1, 2, 3, 4, 5, 6), 3) + if not WINFUNCTYPE is CFUNCTYPE: + self.assertRaises(TypeError, s, 1, 2, 3) + + def test_structures(self): + WNDPROC = WINFUNCTYPE(c_long, c_int, c_int, c_int, c_int) + + def wndproc(hwnd, msg, wParam, lParam): + return hwnd + msg + wParam + lParam + + HINSTANCE = c_int + HICON = c_int + HCURSOR = c_int + LPCTSTR = c_char_p + + class WNDCLASS(Structure): + _fields_ = [("style", c_uint), + ("lpfnWndProc", WNDPROC), + ("cbClsExtra", c_int), + ("cbWndExtra", c_int), + ("hInstance", HINSTANCE), + ("hIcon", HICON), + ("hCursor", HCURSOR), + ("lpszMenuName", LPCTSTR), + ("lpszClassName", LPCTSTR)] + + wndclass = WNDCLASS() + wndclass.lpfnWndProc = WNDPROC(wndproc) + + WNDPROC_2 = WINFUNCTYPE(c_long, c_int, c_int, c_int, c_int) + + # This is no longer true, now that WINFUNCTYPE caches created types internally. + ## # CFuncPtr subclasses are compared by identity, so this raises a TypeError: + ## self.assertRaises(TypeError, setattr, wndclass, + ## "lpfnWndProc", WNDPROC_2(wndproc)) + # instead: + + self.assertIs(WNDPROC, WNDPROC_2) + # 'wndclass.lpfnWndProc' leaks 94 references. Why? + self.assertEqual(wndclass.lpfnWndProc(1, 2, 3, 4), 10) + + + f = wndclass.lpfnWndProc + + del wndclass + del wndproc + + self.assertEqual(f(10, 11, 12, 13), 46) + + def test_dllfunctions(self): + + def NoNullHandle(value): + if not value: + raise WinError() + return value + + strchr = lib.my_strchr + strchr.restype = c_char_p + strchr.argtypes = (c_char_p, c_char) + self.assertEqual(strchr(b"abcdefghi", b"b"), b"bcdefghi") + self.assertEqual(strchr(b"abcdefghi", b"x"), None) + + + strtok = lib.my_strtok + strtok.restype = c_char_p + # Neither of this does work: strtok changes the buffer it is passed +## strtok.argtypes = (c_char_p, c_char_p) +## strtok.argtypes = (c_string, c_char_p) + + def c_string(init): + size = len(init) + 1 + return (c_char*size)(*init) + + s = b"a\nb\nc" + b = c_string(s) + +## b = (c_char * (len(s)+1))() +## b.value = s + +## b = c_string(s) + self.assertEqual(strtok(b, b"\n"), b"a") + self.assertEqual(strtok(None, b"\n"), b"b") + self.assertEqual(strtok(None, b"\n"), b"c") + self.assertEqual(strtok(None, b"\n"), None) + + def test_abstract(self): + from ctypes import _CFuncPtr + + self.assertRaises(TypeError, _CFuncPtr, 13, "name", 42, "iid") + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/test_ctypes/test_functions.py b/Lib/test/test_ctypes/test_functions.py new file mode 100644 index 0000000..4a784c8 --- /dev/null +++ b/Lib/test/test_ctypes/test_functions.py @@ -0,0 +1,383 @@ +""" +Here is probably the place to write the docs, since the test-cases +show how the type behave. + +Later... +""" + +from ctypes import * +from test.test_ctypes import need_symbol +import sys, unittest + +try: + WINFUNCTYPE +except NameError: + # fake to enable this test on Linux + WINFUNCTYPE = CFUNCTYPE + +import _ctypes_test +dll = CDLL(_ctypes_test.__file__) +if sys.platform == "win32": + windll = WinDLL(_ctypes_test.__file__) + +class POINT(Structure): + _fields_ = [("x", c_int), ("y", c_int)] +class RECT(Structure): + _fields_ = [("left", c_int), ("top", c_int), + ("right", c_int), ("bottom", c_int)] +class FunctionTestCase(unittest.TestCase): + + def test_mro(self): + # in Python 2.3, this raises TypeError: MRO conflict among bases classes, + # in Python 2.2 it works. + # + # But in early versions of _ctypes.c, the result of tp_new + # wasn't checked, and it even crashed Python. + # Found by Greg Chapman. + + with self.assertRaises(TypeError): + class X(object, Array): + _length_ = 5 + _type_ = "i" + + from _ctypes import _Pointer + with self.assertRaises(TypeError): + class X(object, _Pointer): + pass + + from _ctypes import _SimpleCData + with self.assertRaises(TypeError): + class X(object, _SimpleCData): + _type_ = "i" + + with self.assertRaises(TypeError): + class X(object, Structure): + _fields_ = [] + + @need_symbol('c_wchar') + def test_wchar_parm(self): + f = dll._testfunc_i_bhilfd + f.argtypes = [c_byte, c_wchar, c_int, c_long, c_float, c_double] + result = f(1, "x", 3, 4, 5.0, 6.0) + self.assertEqual(result, 139) + self.assertEqual(type(result), int) + + @need_symbol('c_wchar') + def test_wchar_result(self): + f = dll._testfunc_i_bhilfd + f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double] + f.restype = c_wchar + result = f(0, 0, 0, 0, 0, 0) + self.assertEqual(result, '\x00') + + def test_voidresult(self): + f = dll._testfunc_v + f.restype = None + f.argtypes = [c_int, c_int, POINTER(c_int)] + result = c_int() + self.assertEqual(None, f(1, 2, byref(result))) + self.assertEqual(result.value, 3) + + def test_intresult(self): + f = dll._testfunc_i_bhilfd + f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double] + f.restype = c_int + result = f(1, 2, 3, 4, 5.0, 6.0) + self.assertEqual(result, 21) + self.assertEqual(type(result), int) + + result = f(-1, -2, -3, -4, -5.0, -6.0) + self.assertEqual(result, -21) + self.assertEqual(type(result), int) + + # If we declare the function to return a short, + # is the high part split off? + f.restype = c_short + result = f(1, 2, 3, 4, 5.0, 6.0) + self.assertEqual(result, 21) + self.assertEqual(type(result), int) + + result = f(1, 2, 3, 0x10004, 5.0, 6.0) + self.assertEqual(result, 21) + self.assertEqual(type(result), int) + + # You cannot assign character format codes as restype any longer + self.assertRaises(TypeError, setattr, f, "restype", "i") + + def test_floatresult(self): + f = dll._testfunc_f_bhilfd + f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double] + f.restype = c_float + result = f(1, 2, 3, 4, 5.0, 6.0) + self.assertEqual(result, 21) + self.assertEqual(type(result), float) + + result = f(-1, -2, -3, -4, -5.0, -6.0) + self.assertEqual(result, -21) + self.assertEqual(type(result), float) + + def test_doubleresult(self): + f = dll._testfunc_d_bhilfd + f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double] + f.restype = c_double + result = f(1, 2, 3, 4, 5.0, 6.0) + self.assertEqual(result, 21) + self.assertEqual(type(result), float) + + result = f(-1, -2, -3, -4, -5.0, -6.0) + self.assertEqual(result, -21) + self.assertEqual(type(result), float) + + def test_longdoubleresult(self): + f = dll._testfunc_D_bhilfD + f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_longdouble] + f.restype = c_longdouble + result = f(1, 2, 3, 4, 5.0, 6.0) + self.assertEqual(result, 21) + self.assertEqual(type(result), float) + + result = f(-1, -2, -3, -4, -5.0, -6.0) + self.assertEqual(result, -21) + self.assertEqual(type(result), float) + + @need_symbol('c_longlong') + def test_longlongresult(self): + f = dll._testfunc_q_bhilfd + f.restype = c_longlong + f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double] + result = f(1, 2, 3, 4, 5.0, 6.0) + self.assertEqual(result, 21) + + f = dll._testfunc_q_bhilfdq + f.restype = c_longlong + f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double, c_longlong] + result = f(1, 2, 3, 4, 5.0, 6.0, 21) + self.assertEqual(result, 42) + + def test_stringresult(self): + f = dll._testfunc_p_p + f.argtypes = None + f.restype = c_char_p + result = f(b"123") + self.assertEqual(result, b"123") + + result = f(None) + self.assertEqual(result, None) + + def test_pointers(self): + f = dll._testfunc_p_p + f.restype = POINTER(c_int) + f.argtypes = [POINTER(c_int)] + + # This only works if the value c_int(42) passed to the + # function is still alive while the pointer (the result) is + # used. + + v = c_int(42) + + self.assertEqual(pointer(v).contents.value, 42) + result = f(pointer(v)) + self.assertEqual(type(result), POINTER(c_int)) + self.assertEqual(result.contents.value, 42) + + # This on works... + result = f(pointer(v)) + self.assertEqual(result.contents.value, v.value) + + p = pointer(c_int(99)) + result = f(p) + self.assertEqual(result.contents.value, 99) + + arg = byref(v) + result = f(arg) + self.assertNotEqual(result.contents, v.value) + + self.assertRaises(ArgumentError, f, byref(c_short(22))) + + # It is dangerous, however, because you don't control the lifetime + # of the pointer: + result = f(byref(c_int(99))) + self.assertNotEqual(result.contents, 99) + + ################################################################ + def test_shorts(self): + f = dll._testfunc_callback_i_if + + args = [] + expected = [262144, 131072, 65536, 32768, 16384, 8192, 4096, 2048, + 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1] + + def callback(v): + args.append(v) + return v + + CallBack = CFUNCTYPE(c_int, c_int) + + cb = CallBack(callback) + f(2**18, cb) + self.assertEqual(args, expected) + + ################################################################ + + + def test_callbacks(self): + f = dll._testfunc_callback_i_if + f.restype = c_int + f.argtypes = None + + MyCallback = CFUNCTYPE(c_int, c_int) + + def callback(value): + #print "called back with", value + return value + + cb = MyCallback(callback) + result = f(-10, cb) + self.assertEqual(result, -18) + + # test with prototype + f.argtypes = [c_int, MyCallback] + cb = MyCallback(callback) + result = f(-10, cb) + self.assertEqual(result, -18) + + AnotherCallback = WINFUNCTYPE(c_int, c_int, c_int, c_int, c_int) + + # check that the prototype works: we call f with wrong + # argument types + cb = AnotherCallback(callback) + self.assertRaises(ArgumentError, f, -10, cb) + + + def test_callbacks_2(self): + # Can also use simple datatypes as argument type specifiers + # for the callback function. + # In this case the call receives an instance of that type + f = dll._testfunc_callback_i_if + f.restype = c_int + + MyCallback = CFUNCTYPE(c_int, c_int) + + f.argtypes = [c_int, MyCallback] + + def callback(value): + #print "called back with", value + self.assertEqual(type(value), int) + return value + + cb = MyCallback(callback) + result = f(-10, cb) + self.assertEqual(result, -18) + + @need_symbol('c_longlong') + def test_longlong_callbacks(self): + + f = dll._testfunc_callback_q_qf + f.restype = c_longlong + + MyCallback = CFUNCTYPE(c_longlong, c_longlong) + + f.argtypes = [c_longlong, MyCallback] + + def callback(value): + self.assertIsInstance(value, int) + return value & 0x7FFFFFFF + + cb = MyCallback(callback) + + self.assertEqual(13577625587, f(1000000000000, cb)) + + def test_errors(self): + self.assertRaises(AttributeError, getattr, dll, "_xxx_yyy") + self.assertRaises(ValueError, c_int.in_dll, dll, "_xxx_yyy") + + def test_byval(self): + + # without prototype + ptin = POINT(1, 2) + ptout = POINT() + # EXPORT int _testfunc_byval(point in, point *pout) + result = dll._testfunc_byval(ptin, byref(ptout)) + got = result, ptout.x, ptout.y + expected = 3, 1, 2 + self.assertEqual(got, expected) + + # with prototype + ptin = POINT(101, 102) + ptout = POINT() + dll._testfunc_byval.argtypes = (POINT, POINTER(POINT)) + dll._testfunc_byval.restype = c_int + result = dll._testfunc_byval(ptin, byref(ptout)) + got = result, ptout.x, ptout.y + expected = 203, 101, 102 + self.assertEqual(got, expected) + + def test_struct_return_2H(self): + class S2H(Structure): + _fields_ = [("x", c_short), + ("y", c_short)] + dll.ret_2h_func.restype = S2H + dll.ret_2h_func.argtypes = [S2H] + inp = S2H(99, 88) + s2h = dll.ret_2h_func(inp) + self.assertEqual((s2h.x, s2h.y), (99*2, 88*3)) + + @unittest.skipUnless(sys.platform == "win32", 'Windows-specific test') + def test_struct_return_2H_stdcall(self): + class S2H(Structure): + _fields_ = [("x", c_short), + ("y", c_short)] + + windll.s_ret_2h_func.restype = S2H + windll.s_ret_2h_func.argtypes = [S2H] + s2h = windll.s_ret_2h_func(S2H(99, 88)) + self.assertEqual((s2h.x, s2h.y), (99*2, 88*3)) + + def test_struct_return_8H(self): + class S8I(Structure): + _fields_ = [("a", c_int), + ("b", c_int), + ("c", c_int), + ("d", c_int), + ("e", c_int), + ("f", c_int), + ("g", c_int), + ("h", c_int)] + dll.ret_8i_func.restype = S8I + dll.ret_8i_func.argtypes = [S8I] + inp = S8I(9, 8, 7, 6, 5, 4, 3, 2) + s8i = dll.ret_8i_func(inp) + self.assertEqual((s8i.a, s8i.b, s8i.c, s8i.d, s8i.e, s8i.f, s8i.g, s8i.h), + (9*2, 8*3, 7*4, 6*5, 5*6, 4*7, 3*8, 2*9)) + + @unittest.skipUnless(sys.platform == "win32", 'Windows-specific test') + def test_struct_return_8H_stdcall(self): + class S8I(Structure): + _fields_ = [("a", c_int), + ("b", c_int), + ("c", c_int), + ("d", c_int), + ("e", c_int), + ("f", c_int), + ("g", c_int), + ("h", c_int)] + windll.s_ret_8i_func.restype = S8I + windll.s_ret_8i_func.argtypes = [S8I] + inp = S8I(9, 8, 7, 6, 5, 4, 3, 2) + s8i = windll.s_ret_8i_func(inp) + self.assertEqual( + (s8i.a, s8i.b, s8i.c, s8i.d, s8i.e, s8i.f, s8i.g, s8i.h), + (9*2, 8*3, 7*4, 6*5, 5*6, 4*7, 3*8, 2*9)) + + def test_sf1651235(self): + # see https://www.python.org/sf/1651235 + + proto = CFUNCTYPE(c_int, RECT, POINT) + def callback(*args): + return 0 + + callback = proto(callback) + self.assertRaises(ArgumentError, lambda: callback((1, 2, 3, 4), POINT())) + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/test_ctypes/test_incomplete.py b/Lib/test/test_ctypes/test_incomplete.py new file mode 100644 index 0000000..00c430e --- /dev/null +++ b/Lib/test/test_ctypes/test_incomplete.py @@ -0,0 +1,42 @@ +import unittest +from ctypes import * + +################################################################ +# +# The incomplete pointer example from the tutorial +# + +class MyTestCase(unittest.TestCase): + + def test_incomplete_example(self): + lpcell = POINTER("cell") + class cell(Structure): + _fields_ = [("name", c_char_p), + ("next", lpcell)] + + SetPointerType(lpcell, cell) + + c1 = cell() + c1.name = b"foo" + c2 = cell() + c2.name = b"bar" + + c1.next = pointer(c2) + c2.next = pointer(c1) + + p = c1 + + result = [] + for i in range(8): + result.append(p.name) + p = p.next[0] + self.assertEqual(result, [b"foo", b"bar"] * 4) + + # to not leak references, we must clean _pointer_type_cache + from ctypes import _pointer_type_cache + del _pointer_type_cache[cell] + +################################################################ + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/test_ctypes/test_init.py b/Lib/test/test_ctypes/test_init.py new file mode 100644 index 0000000..75fad11 --- /dev/null +++ b/Lib/test/test_ctypes/test_init.py @@ -0,0 +1,40 @@ +from ctypes import * +import unittest + +class X(Structure): + _fields_ = [("a", c_int), + ("b", c_int)] + new_was_called = False + + def __new__(cls): + result = super().__new__(cls) + result.new_was_called = True + return result + + def __init__(self): + self.a = 9 + self.b = 12 + +class Y(Structure): + _fields_ = [("x", X)] + + +class InitTest(unittest.TestCase): + def test_get(self): + # make sure the only accessing a nested structure + # doesn't call the structure's __new__ and __init__ + y = Y() + self.assertEqual((y.x.a, y.x.b), (0, 0)) + self.assertEqual(y.x.new_was_called, False) + + # But explicitly creating an X structure calls __new__ and __init__, of course. + x = X() + self.assertEqual((x.a, x.b), (9, 12)) + self.assertEqual(x.new_was_called, True) + + y.x = x + self.assertEqual((y.x.a, y.x.b), (9, 12)) + self.assertEqual(y.x.new_was_called, False) + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_ctypes/test_internals.py b/Lib/test/test_ctypes/test_internals.py new file mode 100644 index 0000000..271e3f5 --- /dev/null +++ b/Lib/test/test_ctypes/test_internals.py @@ -0,0 +1,100 @@ +# This tests the internal _objects attribute +import unittest +from ctypes import * +from sys import getrefcount as grc + +# XXX This test must be reviewed for correctness!!! + +# ctypes' types are container types. +# +# They have an internal memory block, which only consists of some bytes, +# but it has to keep references to other objects as well. This is not +# really needed for trivial C types like int or char, but it is important +# for aggregate types like strings or pointers in particular. +# +# What about pointers? + +class ObjectsTestCase(unittest.TestCase): + def assertSame(self, a, b): + self.assertEqual(id(a), id(b)) + + def test_ints(self): + i = 42000123 + refcnt = grc(i) + ci = c_int(i) + self.assertEqual(refcnt, grc(i)) + self.assertEqual(ci._objects, None) + + def test_c_char_p(self): + s = b"Hello, World" + refcnt = grc(s) + cs = c_char_p(s) + self.assertEqual(refcnt + 1, grc(s)) + self.assertSame(cs._objects, s) + + def test_simple_struct(self): + class X(Structure): + _fields_ = [("a", c_int), ("b", c_int)] + + a = 421234 + b = 421235 + x = X() + self.assertEqual(x._objects, None) + x.a = a + x.b = b + self.assertEqual(x._objects, None) + + def test_embedded_structs(self): + class X(Structure): + _fields_ = [("a", c_int), ("b", c_int)] + + class Y(Structure): + _fields_ = [("x", X), ("y", X)] + + y = Y() + self.assertEqual(y._objects, None) + + x1, x2 = X(), X() + y.x, y.y = x1, x2 + self.assertEqual(y._objects, {"0": {}, "1": {}}) + x1.a, x2.b = 42, 93 + self.assertEqual(y._objects, {"0": {}, "1": {}}) + + def test_xxx(self): + class X(Structure): + _fields_ = [("a", c_char_p), ("b", c_char_p)] + + class Y(Structure): + _fields_ = [("x", X), ("y", X)] + + s1 = b"Hello, World" + s2 = b"Hallo, Welt" + + x = X() + x.a = s1 + x.b = s2 + self.assertEqual(x._objects, {"0": s1, "1": s2}) + + y = Y() + y.x = x + self.assertEqual(y._objects, {"0": {"0": s1, "1": s2}}) +## x = y.x +## del y +## print x._b_base_._objects + + def test_ptr_struct(self): + class X(Structure): + _fields_ = [("data", POINTER(c_int))] + + A = c_int*4 + a = A(11, 22, 33, 44) + self.assertEqual(a._objects, None) + + x = X() + x.data = a +##XXX print x._objects +##XXX print x.data[0] +##XXX print x.data._objects + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/test_ctypes/test_keeprefs.py b/Lib/test/test_ctypes/test_keeprefs.py new file mode 100644 index 0000000..94c0257 --- /dev/null +++ b/Lib/test/test_ctypes/test_keeprefs.py @@ -0,0 +1,153 @@ +from ctypes import * +import unittest + +class SimpleTestCase(unittest.TestCase): + def test_cint(self): + x = c_int() + self.assertEqual(x._objects, None) + x.value = 42 + self.assertEqual(x._objects, None) + x = c_int(99) + self.assertEqual(x._objects, None) + + def test_ccharp(self): + x = c_char_p() + self.assertEqual(x._objects, None) + x.value = b"abc" + self.assertEqual(x._objects, b"abc") + x = c_char_p(b"spam") + self.assertEqual(x._objects, b"spam") + +class StructureTestCase(unittest.TestCase): + def test_cint_struct(self): + class X(Structure): + _fields_ = [("a", c_int), + ("b", c_int)] + + x = X() + self.assertEqual(x._objects, None) + x.a = 42 + x.b = 99 + self.assertEqual(x._objects, None) + + def test_ccharp_struct(self): + class X(Structure): + _fields_ = [("a", c_char_p), + ("b", c_char_p)] + x = X() + self.assertEqual(x._objects, None) + + x.a = b"spam" + x.b = b"foo" + self.assertEqual(x._objects, {"0": b"spam", "1": b"foo"}) + + def test_struct_struct(self): + class POINT(Structure): + _fields_ = [("x", c_int), ("y", c_int)] + class RECT(Structure): + _fields_ = [("ul", POINT), ("lr", POINT)] + + r = RECT() + r.ul.x = 0 + r.ul.y = 1 + r.lr.x = 2 + r.lr.y = 3 + self.assertEqual(r._objects, None) + + r = RECT() + pt = POINT(1, 2) + r.ul = pt + self.assertEqual(r._objects, {'0': {}}) + r.ul.x = 22 + r.ul.y = 44 + self.assertEqual(r._objects, {'0': {}}) + r.lr = POINT() + self.assertEqual(r._objects, {'0': {}, '1': {}}) + +class ArrayTestCase(unittest.TestCase): + def test_cint_array(self): + INTARR = c_int * 3 + + ia = INTARR() + self.assertEqual(ia._objects, None) + ia[0] = 1 + ia[1] = 2 + ia[2] = 3 + self.assertEqual(ia._objects, None) + + class X(Structure): + _fields_ = [("x", c_int), + ("a", INTARR)] + + x = X() + x.x = 1000 + x.a[0] = 42 + x.a[1] = 96 + self.assertEqual(x._objects, None) + x.a = ia + self.assertEqual(x._objects, {'1': {}}) + +class PointerTestCase(unittest.TestCase): + def test_p_cint(self): + i = c_int(42) + x = pointer(i) + self.assertEqual(x._objects, {'1': i}) + +class DeletePointerTestCase(unittest.TestCase): + @unittest.skip('test disabled') + def test_X(self): + class X(Structure): + _fields_ = [("p", POINTER(c_char_p))] + x = X() + i = c_char_p("abc def") + from sys import getrefcount as grc + print("2?", grc(i)) + x.p = pointer(i) + print("3?", grc(i)) + for i in range(320): + c_int(99) + x.p[0] + print(x.p[0]) +## del x +## print "2?", grc(i) +## del i + import gc + gc.collect() + for i in range(320): + c_int(99) + x.p[0] + print(x.p[0]) + print(x.p.contents) +## print x._objects + + x.p[0] = "spam spam" +## print x.p[0] + print("+" * 42) + print(x._objects) + +class PointerToStructure(unittest.TestCase): + def test(self): + class POINT(Structure): + _fields_ = [("x", c_int), ("y", c_int)] + class RECT(Structure): + _fields_ = [("a", POINTER(POINT)), + ("b", POINTER(POINT))] + r = RECT() + p1 = POINT(1, 2) + + r.a = pointer(p1) + r.b = pointer(p1) +## from pprint import pprint as pp +## pp(p1._objects) +## pp(r._objects) + + r.a[0].x = 42 + r.a[0].y = 99 + + # to avoid leaking when tests are run several times + # clean up the types left in the cache. + from ctypes import _pointer_type_cache + del _pointer_type_cache[POINT] + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_ctypes/test_libc.py b/Lib/test/test_ctypes/test_libc.py new file mode 100644 index 0000000..56285b5 --- /dev/null +++ b/Lib/test/test_ctypes/test_libc.py @@ -0,0 +1,33 @@ +import unittest + +from ctypes import * +import _ctypes_test + +lib = CDLL(_ctypes_test.__file__) + +def three_way_cmp(x, y): + """Return -1 if x < y, 0 if x == y and 1 if x > y""" + return (x > y) - (x < y) + +class LibTest(unittest.TestCase): + def test_sqrt(self): + lib.my_sqrt.argtypes = c_double, + lib.my_sqrt.restype = c_double + self.assertEqual(lib.my_sqrt(4.0), 2.0) + import math + self.assertEqual(lib.my_sqrt(2.0), math.sqrt(2.0)) + + def test_qsort(self): + comparefunc = CFUNCTYPE(c_int, POINTER(c_char), POINTER(c_char)) + lib.my_qsort.argtypes = c_void_p, c_size_t, c_size_t, comparefunc + lib.my_qsort.restype = None + + def sort(a, b): + return three_way_cmp(a[0], b[0]) + + chars = create_string_buffer(b"spam, spam, and spam") + lib.my_qsort(chars, len(chars)-1, sizeof(c_char), comparefunc(sort)) + self.assertEqual(chars.raw, b" ,,aaaadmmmnpppsss\x00") + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_ctypes/test_loading.py b/Lib/test/test_ctypes/test_loading.py new file mode 100644 index 0000000..ea89227 --- /dev/null +++ b/Lib/test/test_ctypes/test_loading.py @@ -0,0 +1,182 @@ +from ctypes import * +import os +import shutil +import subprocess +import sys +import unittest +import test.support +from test.support import import_helper +from test.support import os_helper +from ctypes.util import find_library + +libc_name = None + +def setUpModule(): + global libc_name + if os.name == "nt": + libc_name = find_library("c") + elif sys.platform == "cygwin": + libc_name = "cygwin1.dll" + else: + libc_name = find_library("c") + + if test.support.verbose: + print("libc_name is", libc_name) + +class LoaderTest(unittest.TestCase): + + unknowndll = "xxrandomnamexx" + + def test_load(self): + if libc_name is None: + self.skipTest('could not find libc') + CDLL(libc_name) + CDLL(os.path.basename(libc_name)) + self.assertRaises(OSError, CDLL, self.unknowndll) + + def test_load_version(self): + if libc_name is None: + self.skipTest('could not find libc') + if os.path.basename(libc_name) != 'libc.so.6': + self.skipTest('wrong libc path for test') + cdll.LoadLibrary("libc.so.6") + # linux uses version, libc 9 should not exist + self.assertRaises(OSError, cdll.LoadLibrary, "libc.so.9") + self.assertRaises(OSError, cdll.LoadLibrary, self.unknowndll) + + def test_find(self): + for name in ("c", "m"): + lib = find_library(name) + if lib: + cdll.LoadLibrary(lib) + CDLL(lib) + + @unittest.skipUnless(os.name == "nt", + 'test specific to Windows') + def test_load_library(self): + # CRT is no longer directly loadable. See issue23606 for the + # discussion about alternative approaches. + #self.assertIsNotNone(libc_name) + if test.support.verbose: + print(find_library("kernel32")) + print(find_library("user32")) + + if os.name == "nt": + windll.kernel32.GetModuleHandleW + windll["kernel32"].GetModuleHandleW + windll.LoadLibrary("kernel32").GetModuleHandleW + WinDLL("kernel32").GetModuleHandleW + # embedded null character + self.assertRaises(ValueError, windll.LoadLibrary, "kernel32\0") + + @unittest.skipUnless(os.name == "nt", + 'test specific to Windows') + def test_load_ordinal_functions(self): + import _ctypes_test + dll = WinDLL(_ctypes_test.__file__) + # We load the same function both via ordinal and name + func_ord = dll[2] + func_name = dll.GetString + # addressof gets the address where the function pointer is stored + a_ord = addressof(func_ord) + a_name = addressof(func_name) + f_ord_addr = c_void_p.from_address(a_ord).value + f_name_addr = c_void_p.from_address(a_name).value + self.assertEqual(hex(f_ord_addr), hex(f_name_addr)) + + self.assertRaises(AttributeError, dll.__getitem__, 1234) + + @unittest.skipUnless(os.name == "nt", 'Windows-specific test') + def test_1703286_A(self): + from _ctypes import LoadLibrary, FreeLibrary + # On winXP 64-bit, advapi32 loads at an address that does + # NOT fit into a 32-bit integer. FreeLibrary must be able + # to accept this address. + + # These are tests for https://www.python.org/sf/1703286 + handle = LoadLibrary("advapi32") + FreeLibrary(handle) + + @unittest.skipUnless(os.name == "nt", 'Windows-specific test') + def test_1703286_B(self): + # Since on winXP 64-bit advapi32 loads like described + # above, the (arbitrarily selected) CloseEventLog function + # also has a high address. 'call_function' should accept + # addresses so large. + from _ctypes import call_function + advapi32 = windll.advapi32 + # Calling CloseEventLog with a NULL argument should fail, + # but the call should not segfault or so. + self.assertEqual(0, advapi32.CloseEventLog(None)) + windll.kernel32.GetProcAddress.argtypes = c_void_p, c_char_p + windll.kernel32.GetProcAddress.restype = c_void_p + proc = windll.kernel32.GetProcAddress(advapi32._handle, + b"CloseEventLog") + self.assertTrue(proc) + # This is the real test: call the function via 'call_function' + self.assertEqual(0, call_function(proc, (None,))) + + @unittest.skipUnless(os.name == "nt", + 'test specific to Windows') + def test_load_dll_with_flags(self): + _sqlite3 = import_helper.import_module("_sqlite3") + src = _sqlite3.__file__ + if src.lower().endswith("_d.pyd"): + ext = "_d.dll" + else: + ext = ".dll" + + with os_helper.temp_dir() as tmp: + # We copy two files and load _sqlite3.dll (formerly .pyd), + # which has a dependency on sqlite3.dll. Then we test + # loading it in subprocesses to avoid it starting in memory + # for each test. + target = os.path.join(tmp, "_sqlite3.dll") + shutil.copy(src, target) + shutil.copy(os.path.join(os.path.dirname(src), "sqlite3" + ext), + os.path.join(tmp, "sqlite3" + ext)) + + def should_pass(command): + with self.subTest(command): + subprocess.check_output( + [sys.executable, "-c", + "from ctypes import *; import nt;" + command], + cwd=tmp + ) + + def should_fail(command): + with self.subTest(command): + with self.assertRaises(subprocess.CalledProcessError): + subprocess.check_output( + [sys.executable, "-c", + "from ctypes import *; import nt;" + command], + cwd=tmp, stderr=subprocess.STDOUT, + ) + + # Default load should not find this in CWD + should_fail("WinDLL('_sqlite3.dll')") + + # Relative path (but not just filename) should succeed + should_pass("WinDLL('./_sqlite3.dll')") + + # Insecure load flags should succeed + # Clear the DLL directory to avoid safe search settings propagating + should_pass("windll.kernel32.SetDllDirectoryW(None); WinDLL('_sqlite3.dll', winmode=0)") + + # Full path load without DLL_LOAD_DIR shouldn't find dependency + should_fail("WinDLL(nt._getfullpathname('_sqlite3.dll'), " + + "winmode=nt._LOAD_LIBRARY_SEARCH_SYSTEM32)") + + # Full path load with DLL_LOAD_DIR should succeed + should_pass("WinDLL(nt._getfullpathname('_sqlite3.dll'), " + + "winmode=nt._LOAD_LIBRARY_SEARCH_SYSTEM32|" + + "nt._LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR)") + + # User-specified directory should succeed + should_pass("import os; p = os.add_dll_directory(os.getcwd());" + + "WinDLL('_sqlite3.dll'); p.close()") + + + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_ctypes/test_macholib.py b/Lib/test/test_ctypes/test_macholib.py new file mode 100644 index 0000000..bc75f1a --- /dev/null +++ b/Lib/test/test_ctypes/test_macholib.py @@ -0,0 +1,110 @@ +import os +import sys +import unittest + +# Bob Ippolito: +# +# Ok.. the code to find the filename for __getattr__ should look +# something like: +# +# import os +# from macholib.dyld import dyld_find +# +# def find_lib(name): +# possible = ['lib'+name+'.dylib', name+'.dylib', +# name+'.framework/'+name] +# for dylib in possible: +# try: +# return os.path.realpath(dyld_find(dylib)) +# except ValueError: +# pass +# raise ValueError, "%s not found" % (name,) +# +# It'll have output like this: +# +# >>> find_lib('pthread') +# '/usr/lib/libSystem.B.dylib' +# >>> find_lib('z') +# '/usr/lib/libz.1.dylib' +# >>> find_lib('IOKit') +# '/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit' +# +# -bob + +from ctypes.macholib.dyld import dyld_find +from ctypes.macholib.dylib import dylib_info +from ctypes.macholib.framework import framework_info + +def find_lib(name): + possible = ['lib'+name+'.dylib', name+'.dylib', name+'.framework/'+name] + for dylib in possible: + try: + return os.path.realpath(dyld_find(dylib)) + except ValueError: + pass + raise ValueError("%s not found" % (name,)) + + +def d(location=None, name=None, shortname=None, version=None, suffix=None): + return {'location': location, 'name': name, 'shortname': shortname, + 'version': version, 'suffix': suffix} + + +class MachOTest(unittest.TestCase): + @unittest.skipUnless(sys.platform == "darwin", 'OSX-specific test') + def test_find(self): + self.assertEqual(dyld_find('libSystem.dylib'), + '/usr/lib/libSystem.dylib') + self.assertEqual(dyld_find('System.framework/System'), + '/System/Library/Frameworks/System.framework/System') + + # On Mac OS 11, system dylibs are only present in the shared cache, + # so symlinks like libpthread.dylib -> libSystem.B.dylib will not + # be resolved by dyld_find + self.assertIn(find_lib('pthread'), + ('/usr/lib/libSystem.B.dylib', '/usr/lib/libpthread.dylib')) + + result = find_lib('z') + # Issue #21093: dyld default search path includes $HOME/lib and + # /usr/local/lib before /usr/lib, which caused test failures if + # a local copy of libz exists in one of them. Now ignore the head + # of the path. + self.assertRegex(result, r".*/lib/libz.*\.dylib") + + self.assertIn(find_lib('IOKit'), + ('/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit', + '/System/Library/Frameworks/IOKit.framework/IOKit')) + + @unittest.skipUnless(sys.platform == "darwin", 'OSX-specific test') + def test_info(self): + self.assertIsNone(dylib_info('completely/invalid')) + self.assertIsNone(dylib_info('completely/invalide_debug')) + self.assertEqual(dylib_info('P/Foo.dylib'), d('P', 'Foo.dylib', 'Foo')) + self.assertEqual(dylib_info('P/Foo_debug.dylib'), + d('P', 'Foo_debug.dylib', 'Foo', suffix='debug')) + self.assertEqual(dylib_info('P/Foo.A.dylib'), + d('P', 'Foo.A.dylib', 'Foo', 'A')) + self.assertEqual(dylib_info('P/Foo_debug.A.dylib'), + d('P', 'Foo_debug.A.dylib', 'Foo_debug', 'A')) + self.assertEqual(dylib_info('P/Foo.A_debug.dylib'), + d('P', 'Foo.A_debug.dylib', 'Foo', 'A', 'debug')) + + @unittest.skipUnless(sys.platform == "darwin", 'OSX-specific test') + def test_framework_info(self): + self.assertIsNone(framework_info('completely/invalid')) + self.assertIsNone(framework_info('completely/invalid/_debug')) + self.assertIsNone(framework_info('P/F.framework')) + self.assertIsNone(framework_info('P/F.framework/_debug')) + self.assertEqual(framework_info('P/F.framework/F'), + d('P', 'F.framework/F', 'F')) + self.assertEqual(framework_info('P/F.framework/F_debug'), + d('P', 'F.framework/F_debug', 'F', suffix='debug')) + self.assertIsNone(framework_info('P/F.framework/Versions')) + self.assertIsNone(framework_info('P/F.framework/Versions/A')) + self.assertEqual(framework_info('P/F.framework/Versions/A/F'), + d('P', 'F.framework/Versions/A/F', 'F', 'A')) + self.assertEqual(framework_info('P/F.framework/Versions/A/F_debug'), + d('P', 'F.framework/Versions/A/F_debug', 'F', 'A', 'debug')) + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_ctypes/test_memfunctions.py b/Lib/test/test_ctypes/test_memfunctions.py new file mode 100644 index 0000000..d5c9735 --- /dev/null +++ b/Lib/test/test_ctypes/test_memfunctions.py @@ -0,0 +1,79 @@ +import sys +from test import support +import unittest +from ctypes import * +from test.test_ctypes import need_symbol + +class MemFunctionsTest(unittest.TestCase): + @unittest.skip('test disabled') + def test_overflow(self): + # string_at and wstring_at must use the Python calling + # convention (which acquires the GIL and checks the Python + # error flag). Provoke an error and catch it; see also issue + # #3554: + self.assertRaises((OverflowError, MemoryError, SystemError), + lambda: wstring_at(u"foo", sys.maxint - 1)) + self.assertRaises((OverflowError, MemoryError, SystemError), + lambda: string_at("foo", sys.maxint - 1)) + + def test_memmove(self): + # large buffers apparently increase the chance that the memory + # is allocated in high address space. + a = create_string_buffer(1000000) + p = b"Hello, World" + result = memmove(a, p, len(p)) + self.assertEqual(a.value, b"Hello, World") + + self.assertEqual(string_at(result), b"Hello, World") + self.assertEqual(string_at(result, 5), b"Hello") + self.assertEqual(string_at(result, 16), b"Hello, World\0\0\0\0") + self.assertEqual(string_at(result, 0), b"") + + def test_memset(self): + a = create_string_buffer(1000000) + result = memset(a, ord('x'), 16) + self.assertEqual(a.value, b"xxxxxxxxxxxxxxxx") + + self.assertEqual(string_at(result), b"xxxxxxxxxxxxxxxx") + self.assertEqual(string_at(a), b"xxxxxxxxxxxxxxxx") + self.assertEqual(string_at(a, 20), b"xxxxxxxxxxxxxxxx\0\0\0\0") + + def test_cast(self): + a = (c_ubyte * 32)(*map(ord, "abcdef")) + self.assertEqual(cast(a, c_char_p).value, b"abcdef") + self.assertEqual(cast(a, POINTER(c_byte))[:7], + [97, 98, 99, 100, 101, 102, 0]) + self.assertEqual(cast(a, POINTER(c_byte))[:7:], + [97, 98, 99, 100, 101, 102, 0]) + self.assertEqual(cast(a, POINTER(c_byte))[6:-1:-1], + [0, 102, 101, 100, 99, 98, 97]) + self.assertEqual(cast(a, POINTER(c_byte))[:7:2], + [97, 99, 101, 0]) + self.assertEqual(cast(a, POINTER(c_byte))[:7:7], + [97]) + + @support.refcount_test + def test_string_at(self): + s = string_at(b"foo bar") + # XXX The following may be wrong, depending on how Python + # manages string instances + self.assertEqual(2, sys.getrefcount(s)) + self.assertTrue(s, "foo bar") + + self.assertEqual(string_at(b"foo bar", 7), b"foo bar") + self.assertEqual(string_at(b"foo bar", 3), b"foo") + + @need_symbol('create_unicode_buffer') + def test_wstring_at(self): + p = create_unicode_buffer("Hello, World") + a = create_unicode_buffer(1000000) + result = memmove(a, p, len(p) * sizeof(c_wchar)) + self.assertEqual(a.value, "Hello, World") + + self.assertEqual(wstring_at(a), "Hello, World") + self.assertEqual(wstring_at(a, 5), "Hello") + self.assertEqual(wstring_at(a, 16), "Hello, World\0\0\0\0") + self.assertEqual(wstring_at(a, 0), "") + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_ctypes/test_numbers.py b/Lib/test/test_ctypes/test_numbers.py new file mode 100644 index 0000000..db500e8 --- /dev/null +++ b/Lib/test/test_ctypes/test_numbers.py @@ -0,0 +1,295 @@ +from ctypes import * +import unittest +import struct + +def valid_ranges(*types): + # given a sequence of numeric types, collect their _type_ + # attribute, which is a single format character compatible with + # the struct module, use the struct module to calculate the + # minimum and maximum value allowed for this format. + # Returns a list of (min, max) values. + result = [] + for t in types: + fmt = t._type_ + size = struct.calcsize(fmt) + a = struct.unpack(fmt, (b"\x00"*32)[:size])[0] + b = struct.unpack(fmt, (b"\xFF"*32)[:size])[0] + c = struct.unpack(fmt, (b"\x7F"+b"\x00"*32)[:size])[0] + d = struct.unpack(fmt, (b"\x80"+b"\xFF"*32)[:size])[0] + result.append((min(a, b, c, d), max(a, b, c, d))) + return result + +ArgType = type(byref(c_int(0))) + +unsigned_types = [c_ubyte, c_ushort, c_uint, c_ulong] +signed_types = [c_byte, c_short, c_int, c_long, c_longlong] + +bool_types = [] + +float_types = [c_double, c_float] + +try: + c_ulonglong + c_longlong +except NameError: + pass +else: + unsigned_types.append(c_ulonglong) + signed_types.append(c_longlong) + +try: + c_bool +except NameError: + pass +else: + bool_types.append(c_bool) + +unsigned_ranges = valid_ranges(*unsigned_types) +signed_ranges = valid_ranges(*signed_types) +bool_values = [True, False, 0, 1, -1, 5000, 'test', [], [1]] + +################################################################ + +class NumberTestCase(unittest.TestCase): + + def test_default_init(self): + # default values are set to zero + for t in signed_types + unsigned_types + float_types: + self.assertEqual(t().value, 0) + + def test_unsigned_values(self): + # the value given to the constructor is available + # as the 'value' attribute + for t, (l, h) in zip(unsigned_types, unsigned_ranges): + self.assertEqual(t(l).value, l) + self.assertEqual(t(h).value, h) + + def test_signed_values(self): + # see above + for t, (l, h) in zip(signed_types, signed_ranges): + self.assertEqual(t(l).value, l) + self.assertEqual(t(h).value, h) + + def test_bool_values(self): + from operator import truth + for t, v in zip(bool_types, bool_values): + self.assertEqual(t(v).value, truth(v)) + + def test_typeerror(self): + # Only numbers are allowed in the constructor, + # otherwise TypeError is raised + for t in signed_types + unsigned_types + float_types: + self.assertRaises(TypeError, t, "") + self.assertRaises(TypeError, t, None) + + @unittest.skip('test disabled') + def test_valid_ranges(self): + # invalid values of the correct type + # raise ValueError (not OverflowError) + for t, (l, h) in zip(unsigned_types, unsigned_ranges): + self.assertRaises(ValueError, t, l-1) + self.assertRaises(ValueError, t, h+1) + + def test_from_param(self): + # the from_param class method attribute always + # returns PyCArgObject instances + for t in signed_types + unsigned_types + float_types: + self.assertEqual(ArgType, type(t.from_param(0))) + + def test_byref(self): + # calling byref returns also a PyCArgObject instance + for t in signed_types + unsigned_types + float_types + bool_types: + parm = byref(t()) + self.assertEqual(ArgType, type(parm)) + + + def test_floats(self): + # c_float and c_double can be created from + # Python int and float + class FloatLike(object): + def __float__(self): + return 2.0 + f = FloatLike() + for t in float_types: + self.assertEqual(t(2.0).value, 2.0) + self.assertEqual(t(2).value, 2.0) + self.assertEqual(t(2).value, 2.0) + self.assertEqual(t(f).value, 2.0) + + def test_integers(self): + class FloatLike(object): + def __float__(self): + return 2.0 + f = FloatLike() + class IntLike(object): + def __int__(self): + return 2 + d = IntLike() + class IndexLike(object): + def __index__(self): + return 2 + i = IndexLike() + # integers cannot be constructed from floats, + # but from integer-like objects + for t in signed_types + unsigned_types: + self.assertRaises(TypeError, t, 3.14) + self.assertRaises(TypeError, t, f) + self.assertRaises(TypeError, t, d) + self.assertEqual(t(i).value, 2) + + def test_sizes(self): + for t in signed_types + unsigned_types + float_types + bool_types: + try: + size = struct.calcsize(t._type_) + except struct.error: + continue + # sizeof of the type... + self.assertEqual(sizeof(t), size) + # and sizeof of an instance + self.assertEqual(sizeof(t()), size) + + def test_alignments(self): + for t in signed_types + unsigned_types + float_types: + code = t._type_ # the typecode + align = struct.calcsize("c%c" % code) - struct.calcsize(code) + + # alignment of the type... + self.assertEqual((code, alignment(t)), + (code, align)) + # and alignment of an instance + self.assertEqual((code, alignment(t())), + (code, align)) + + def test_int_from_address(self): + from array import array + for t in signed_types + unsigned_types: + # the array module doesn't support all format codes + # (no 'q' or 'Q') + try: + array(t._type_) + except ValueError: + continue + a = array(t._type_, [100]) + + # v now is an integer at an 'external' memory location + v = t.from_address(a.buffer_info()[0]) + self.assertEqual(v.value, a[0]) + self.assertEqual(type(v), t) + + # changing the value at the memory location changes v's value also + a[0] = 42 + self.assertEqual(v.value, a[0]) + + + def test_float_from_address(self): + from array import array + for t in float_types: + a = array(t._type_, [3.14]) + v = t.from_address(a.buffer_info()[0]) + self.assertEqual(v.value, a[0]) + self.assertIs(type(v), t) + a[0] = 2.3456e17 + self.assertEqual(v.value, a[0]) + self.assertIs(type(v), t) + + def test_char_from_address(self): + from ctypes import c_char + from array import array + + a = array('b', [0]) + a[0] = ord('x') + v = c_char.from_address(a.buffer_info()[0]) + self.assertEqual(v.value, b'x') + self.assertIs(type(v), c_char) + + a[0] = ord('?') + self.assertEqual(v.value, b'?') + + # array does not support c_bool / 't' + @unittest.skip('test disabled') + def test_bool_from_address(self): + from ctypes import c_bool + from array import array + a = array(c_bool._type_, [True]) + v = t.from_address(a.buffer_info()[0]) + self.assertEqual(v.value, a[0]) + self.assertEqual(type(v) is t) + a[0] = False + self.assertEqual(v.value, a[0]) + self.assertEqual(type(v) is t) + + def test_init(self): + # c_int() can be initialized from Python's int, and c_int. + # Not from c_long or so, which seems strange, abc should + # probably be changed: + self.assertRaises(TypeError, c_int, c_long(42)) + + def test_float_overflow(self): + import sys + big_int = int(sys.float_info.max) * 2 + for t in float_types + [c_longdouble]: + self.assertRaises(OverflowError, t, big_int) + if (hasattr(t, "__ctype_be__")): + self.assertRaises(OverflowError, t.__ctype_be__, big_int) + if (hasattr(t, "__ctype_le__")): + self.assertRaises(OverflowError, t.__ctype_le__, big_int) + + @unittest.skip('test disabled') + def test_perf(self): + check_perf() + +from ctypes import _SimpleCData +class c_int_S(_SimpleCData): + _type_ = "i" + __slots__ = [] + +def run_test(rep, msg, func, arg=None): +## items = [None] * rep + items = range(rep) + from time import perf_counter as clock + if arg is not None: + start = clock() + for i in items: + func(arg); func(arg); func(arg); func(arg); func(arg) + stop = clock() + else: + start = clock() + for i in items: + func(); func(); func(); func(); func() + stop = clock() + print("%15s: %.2f us" % (msg, ((stop-start)*1e6/5/rep))) + +def check_perf(): + # Construct 5 objects + from ctypes import c_int + + REP = 200000 + + run_test(REP, "int()", int) + run_test(REP, "int(999)", int) + run_test(REP, "c_int()", c_int) + run_test(REP, "c_int(999)", c_int) + run_test(REP, "c_int_S()", c_int_S) + run_test(REP, "c_int_S(999)", c_int_S) + +# Python 2.3 -OO, win2k, P4 700 MHz: +# +# int(): 0.87 us +# int(999): 0.87 us +# c_int(): 3.35 us +# c_int(999): 3.34 us +# c_int_S(): 3.23 us +# c_int_S(999): 3.24 us + +# Python 2.2 -OO, win2k, P4 700 MHz: +# +# int(): 0.89 us +# int(999): 0.89 us +# c_int(): 9.99 us +# c_int(999): 10.02 us +# c_int_S(): 9.87 us +# c_int_S(999): 9.85 us + +if __name__ == '__main__': +## check_perf() + unittest.main() diff --git a/Lib/test/test_ctypes/test_objects.py b/Lib/test/test_ctypes/test_objects.py new file mode 100644 index 0000000..44a3c61 --- /dev/null +++ b/Lib/test/test_ctypes/test_objects.py @@ -0,0 +1,67 @@ +r''' +This tests the '_objects' attribute of ctypes instances. '_objects' +holds references to objects that must be kept alive as long as the +ctypes instance, to make sure that the memory buffer is valid. + +WARNING: The '_objects' attribute is exposed ONLY for debugging ctypes itself, +it MUST NEVER BE MODIFIED! + +'_objects' is initialized to a dictionary on first use, before that it +is None. + +Here is an array of string pointers: + +>>> from ctypes import * +>>> array = (c_char_p * 5)() +>>> print(array._objects) +None +>>> + +The memory block stores pointers to strings, and the strings itself +assigned from Python must be kept. + +>>> array[4] = b'foo bar' +>>> array._objects +{'4': b'foo bar'} +>>> array[4] +b'foo bar' +>>> + +It gets more complicated when the ctypes instance itself is contained +in a 'base' object. + +>>> class X(Structure): +... _fields_ = [("x", c_int), ("y", c_int), ("array", c_char_p * 5)] +... +>>> x = X() +>>> print(x._objects) +None +>>> + +The'array' attribute of the 'x' object shares part of the memory buffer +of 'x' ('_b_base_' is either None, or the root object owning the memory block): + +>>> print(x.array._b_base_) # doctest: +ELLIPSIS + +>>> + +>>> x.array[0] = b'spam spam spam' +>>> x._objects +{'0:2': b'spam spam spam'} +>>> x.array._b_base_._objects +{'0:2': b'spam spam spam'} +>>> + +''' + +import unittest, doctest + +import test.test_ctypes.test_objects + +class TestCase(unittest.TestCase): + def test(self): + failures, tests = doctest.testmod(test.test_ctypes.test_objects) + self.assertFalse(failures, 'doctests failed, see output above') + +if __name__ == '__main__': + doctest.testmod(test.test_ctypes.test_objects) diff --git a/Lib/test/test_ctypes/test_parameters.py b/Lib/test/test_ctypes/test_parameters.py new file mode 100644 index 0000000..2f755a6 --- /dev/null +++ b/Lib/test/test_ctypes/test_parameters.py @@ -0,0 +1,250 @@ +import unittest +from test.test_ctypes import need_symbol +import test.support + +class SimpleTypesTestCase(unittest.TestCase): + + def setUp(self): + import ctypes + try: + from _ctypes import set_conversion_mode + except ImportError: + pass + else: + self.prev_conv_mode = set_conversion_mode("ascii", "strict") + + def tearDown(self): + try: + from _ctypes import set_conversion_mode + except ImportError: + pass + else: + set_conversion_mode(*self.prev_conv_mode) + + def test_subclasses(self): + from ctypes import c_void_p, c_char_p + # ctypes 0.9.5 and before did overwrite from_param in SimpleType_new + class CVOIDP(c_void_p): + def from_param(cls, value): + return value * 2 + from_param = classmethod(from_param) + + class CCHARP(c_char_p): + def from_param(cls, value): + return value * 4 + from_param = classmethod(from_param) + + self.assertEqual(CVOIDP.from_param("abc"), "abcabc") + self.assertEqual(CCHARP.from_param("abc"), "abcabcabcabc") + + @need_symbol('c_wchar_p') + def test_subclasses_c_wchar_p(self): + from ctypes import c_wchar_p + + class CWCHARP(c_wchar_p): + def from_param(cls, value): + return value * 3 + from_param = classmethod(from_param) + + self.assertEqual(CWCHARP.from_param("abc"), "abcabcabc") + + # XXX Replace by c_char_p tests + def test_cstrings(self): + from ctypes import c_char_p + + # c_char_p.from_param on a Python String packs the string + # into a cparam object + s = b"123" + self.assertIs(c_char_p.from_param(s)._obj, s) + + # new in 0.9.1: convert (encode) unicode to ascii + self.assertEqual(c_char_p.from_param(b"123")._obj, b"123") + self.assertRaises(TypeError, c_char_p.from_param, "123\377") + self.assertRaises(TypeError, c_char_p.from_param, 42) + + # calling c_char_p.from_param with a c_char_p instance + # returns the argument itself: + a = c_char_p(b"123") + self.assertIs(c_char_p.from_param(a), a) + + @need_symbol('c_wchar_p') + def test_cw_strings(self): + from ctypes import c_wchar_p + + c_wchar_p.from_param("123") + + self.assertRaises(TypeError, c_wchar_p.from_param, 42) + self.assertRaises(TypeError, c_wchar_p.from_param, b"123\377") + + pa = c_wchar_p.from_param(c_wchar_p("123")) + self.assertEqual(type(pa), c_wchar_p) + + def test_int_pointers(self): + from ctypes import c_short, c_uint, c_int, c_long, POINTER, pointer + LPINT = POINTER(c_int) + +## p = pointer(c_int(42)) +## x = LPINT.from_param(p) + x = LPINT.from_param(pointer(c_int(42))) + self.assertEqual(x.contents.value, 42) + self.assertEqual(LPINT(c_int(42)).contents.value, 42) + + self.assertEqual(LPINT.from_param(None), None) + + if c_int != c_long: + self.assertRaises(TypeError, LPINT.from_param, pointer(c_long(42))) + self.assertRaises(TypeError, LPINT.from_param, pointer(c_uint(42))) + self.assertRaises(TypeError, LPINT.from_param, pointer(c_short(42))) + + def test_byref_pointer(self): + # The from_param class method of POINTER(typ) classes accepts what is + # returned by byref(obj), it type(obj) == typ + from ctypes import c_short, c_uint, c_int, c_long, POINTER, byref + LPINT = POINTER(c_int) + + LPINT.from_param(byref(c_int(42))) + + self.assertRaises(TypeError, LPINT.from_param, byref(c_short(22))) + if c_int != c_long: + self.assertRaises(TypeError, LPINT.from_param, byref(c_long(22))) + self.assertRaises(TypeError, LPINT.from_param, byref(c_uint(22))) + + def test_byref_pointerpointer(self): + # See above + from ctypes import c_short, c_uint, c_int, c_long, pointer, POINTER, byref + + LPLPINT = POINTER(POINTER(c_int)) + LPLPINT.from_param(byref(pointer(c_int(42)))) + + self.assertRaises(TypeError, LPLPINT.from_param, byref(pointer(c_short(22)))) + if c_int != c_long: + self.assertRaises(TypeError, LPLPINT.from_param, byref(pointer(c_long(22)))) + self.assertRaises(TypeError, LPLPINT.from_param, byref(pointer(c_uint(22)))) + + def test_array_pointers(self): + from ctypes import c_short, c_uint, c_int, c_long, POINTER + INTARRAY = c_int * 3 + ia = INTARRAY() + self.assertEqual(len(ia), 3) + self.assertEqual([ia[i] for i in range(3)], [0, 0, 0]) + + # Pointers are only compatible with arrays containing items of + # the same type! + LPINT = POINTER(c_int) + LPINT.from_param((c_int*3)()) + self.assertRaises(TypeError, LPINT.from_param, c_short*3) + self.assertRaises(TypeError, LPINT.from_param, c_long*3) + self.assertRaises(TypeError, LPINT.from_param, c_uint*3) + + def test_noctypes_argtype(self): + import _ctypes_test + from ctypes import CDLL, c_void_p, ArgumentError + + func = CDLL(_ctypes_test.__file__)._testfunc_p_p + func.restype = c_void_p + # TypeError: has no from_param method + self.assertRaises(TypeError, setattr, func, "argtypes", (object,)) + + class Adapter(object): + def from_param(cls, obj): + return None + + func.argtypes = (Adapter(),) + self.assertEqual(func(None), None) + self.assertEqual(func(object()), None) + + class Adapter(object): + def from_param(cls, obj): + return obj + + func.argtypes = (Adapter(),) + # don't know how to convert parameter 1 + self.assertRaises(ArgumentError, func, object()) + self.assertEqual(func(c_void_p(42)), 42) + + class Adapter(object): + def from_param(cls, obj): + raise ValueError(obj) + + func.argtypes = (Adapter(),) + # ArgumentError: argument 1: ValueError: 99 + self.assertRaises(ArgumentError, func, 99) + + def test_abstract(self): + from ctypes import (Array, Structure, Union, _Pointer, + _SimpleCData, _CFuncPtr) + + self.assertRaises(TypeError, Array.from_param, 42) + self.assertRaises(TypeError, Structure.from_param, 42) + self.assertRaises(TypeError, Union.from_param, 42) + self.assertRaises(TypeError, _CFuncPtr.from_param, 42) + self.assertRaises(TypeError, _Pointer.from_param, 42) + self.assertRaises(TypeError, _SimpleCData.from_param, 42) + + @test.support.cpython_only + def test_issue31311(self): + # __setstate__ should neither raise a SystemError nor crash in case + # of a bad __dict__. + from ctypes import Structure + + class BadStruct(Structure): + @property + def __dict__(self): + pass + with self.assertRaises(TypeError): + BadStruct().__setstate__({}, b'foo') + + class WorseStruct(Structure): + @property + def __dict__(self): + 1/0 + with self.assertRaises(ZeroDivisionError): + WorseStruct().__setstate__({}, b'foo') + + def test_parameter_repr(self): + from ctypes import ( + c_bool, + c_char, + c_wchar, + c_byte, + c_ubyte, + c_short, + c_ushort, + c_int, + c_uint, + c_long, + c_ulong, + c_longlong, + c_ulonglong, + c_float, + c_double, + c_longdouble, + c_char_p, + c_wchar_p, + c_void_p, + ) + self.assertRegex(repr(c_bool.from_param(True)), r"^$") + self.assertEqual(repr(c_char.from_param(97)), "") + self.assertRegex(repr(c_wchar.from_param('a')), r"^$") + self.assertEqual(repr(c_byte.from_param(98)), "") + self.assertEqual(repr(c_ubyte.from_param(98)), "") + self.assertEqual(repr(c_short.from_param(511)), "") + self.assertEqual(repr(c_ushort.from_param(511)), "") + self.assertRegex(repr(c_int.from_param(20000)), r"^$") + self.assertRegex(repr(c_uint.from_param(20000)), r"^$") + self.assertRegex(repr(c_long.from_param(20000)), r"^$") + self.assertRegex(repr(c_ulong.from_param(20000)), r"^$") + self.assertRegex(repr(c_longlong.from_param(20000)), r"^$") + self.assertRegex(repr(c_ulonglong.from_param(20000)), r"^$") + self.assertEqual(repr(c_float.from_param(1.5)), "") + self.assertEqual(repr(c_double.from_param(1.5)), "") + self.assertEqual(repr(c_double.from_param(1e300)), "") + self.assertRegex(repr(c_longdouble.from_param(1.5)), r"^$") + self.assertRegex(repr(c_char_p.from_param(b'hihi')), r"^$") + self.assertRegex(repr(c_wchar_p.from_param('hihi')), r"^$") + self.assertRegex(repr(c_void_p.from_param(0x12)), r"^$") + +################################################################ + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/test_ctypes/test_pep3118.py b/Lib/test/test_ctypes/test_pep3118.py new file mode 100644 index 0000000..81e8ca7 --- /dev/null +++ b/Lib/test/test_ctypes/test_pep3118.py @@ -0,0 +1,233 @@ +import unittest +from ctypes import * +import re, sys + +if sys.byteorder == "little": + THIS_ENDIAN = "<" + OTHER_ENDIAN = ">" +else: + THIS_ENDIAN = ">" + OTHER_ENDIAN = "<" + +def normalize(format): + # Remove current endian specifier and white space from a format + # string + if format is None: + return "" + format = format.replace(OTHER_ENDIAN, THIS_ENDIAN) + return re.sub(r"\s", "", format) + +class Test(unittest.TestCase): + + def test_native_types(self): + for tp, fmt, shape, itemtp in native_types: + ob = tp() + v = memoryview(ob) + try: + self.assertEqual(normalize(v.format), normalize(fmt)) + if shape: + self.assertEqual(len(v), shape[0]) + else: + self.assertEqual(len(v) * sizeof(itemtp), sizeof(ob)) + self.assertEqual(v.itemsize, sizeof(itemtp)) + self.assertEqual(v.shape, shape) + # XXX Issue #12851: PyCData_NewGetBuffer() must provide strides + # if requested. memoryview currently reconstructs missing + # stride information, so this assert will fail. + # self.assertEqual(v.strides, ()) + + # they are always read/write + self.assertFalse(v.readonly) + + if v.shape: + n = 1 + for dim in v.shape: + n = n * dim + self.assertEqual(n * v.itemsize, len(v.tobytes())) + except: + # so that we can see the failing type + print(tp) + raise + + def test_endian_types(self): + for tp, fmt, shape, itemtp in endian_types: + ob = tp() + v = memoryview(ob) + try: + self.assertEqual(v.format, fmt) + if shape: + self.assertEqual(len(v), shape[0]) + else: + self.assertEqual(len(v) * sizeof(itemtp), sizeof(ob)) + self.assertEqual(v.itemsize, sizeof(itemtp)) + self.assertEqual(v.shape, shape) + # XXX Issue #12851 + # self.assertEqual(v.strides, ()) + + # they are always read/write + self.assertFalse(v.readonly) + + if v.shape: + n = 1 + for dim in v.shape: + n = n * dim + self.assertEqual(n, len(v)) + except: + # so that we can see the failing type + print(tp) + raise + +# define some structure classes + +class Point(Structure): + _fields_ = [("x", c_long), ("y", c_long)] + +class PackedPoint(Structure): + _pack_ = 2 + _fields_ = [("x", c_long), ("y", c_long)] + +class Point2(Structure): + pass +Point2._fields_ = [("x", c_long), ("y", c_long)] + +class EmptyStruct(Structure): + _fields_ = [] + +class aUnion(Union): + _fields_ = [("a", c_int)] + +class StructWithArrays(Structure): + _fields_ = [("x", c_long * 3 * 2), ("y", Point * 4)] + +class Incomplete(Structure): + pass + +class Complete(Structure): + pass +PComplete = POINTER(Complete) +Complete._fields_ = [("a", c_long)] + +################################################################ +# +# This table contains format strings as they look on little endian +# machines. The test replaces '<' with '>' on big endian machines. +# + +# Platform-specific type codes +s_bool = {1: '?', 2: 'H', 4: 'L', 8: 'Q'}[sizeof(c_bool)] +s_short = {2: 'h', 4: 'l', 8: 'q'}[sizeof(c_short)] +s_ushort = {2: 'H', 4: 'L', 8: 'Q'}[sizeof(c_ushort)] +s_int = {2: 'h', 4: 'i', 8: 'q'}[sizeof(c_int)] +s_uint = {2: 'H', 4: 'I', 8: 'Q'}[sizeof(c_uint)] +s_long = {4: 'l', 8: 'q'}[sizeof(c_long)] +s_ulong = {4: 'L', 8: 'Q'}[sizeof(c_ulong)] +s_longlong = "q" +s_ulonglong = "Q" +s_float = "f" +s_double = "d" +s_longdouble = "g" + +# Alias definitions in ctypes/__init__.py +if c_int is c_long: + s_int = s_long +if c_uint is c_ulong: + s_uint = s_ulong +if c_longlong is c_long: + s_longlong = s_long +if c_ulonglong is c_ulong: + s_ulonglong = s_ulong +if c_longdouble is c_double: + s_longdouble = s_double + + +native_types = [ + # type format shape calc itemsize + + ## simple types + + (c_char, "l:x:>l:y:}".replace('l', s_long), (), BEPoint), + (LEPoint, "T{l:x:>l:y:}".replace('l', s_long), (), POINTER(BEPoint)), + (POINTER(LEPoint), "&T{= 0: + return a + # View the bits in `a` as unsigned instead. + import struct + num_bits = struct.calcsize("P") * 8 # num bits in native machine address + a += 1 << num_bits + assert a >= 0 + return a + +def c_wbuffer(init): + n = len(init) + 1 + return (c_wchar * n)(*init) + +class CharPointersTestCase(unittest.TestCase): + + def setUp(self): + func = testdll._testfunc_p_p + func.restype = c_long + func.argtypes = None + + def test_paramflags(self): + # function returns c_void_p result, + # and has a required parameter named 'input' + prototype = CFUNCTYPE(c_void_p, c_void_p) + func = prototype(("_testfunc_p_p", testdll), + ((1, "input"),)) + + try: + func() + except TypeError as details: + self.assertEqual(str(details), "required argument 'input' missing") + else: + self.fail("TypeError not raised") + + self.assertEqual(func(None), None) + self.assertEqual(func(input=None), None) + + + def test_int_pointer_arg(self): + func = testdll._testfunc_p_p + if sizeof(c_longlong) == sizeof(c_void_p): + func.restype = c_longlong + else: + func.restype = c_long + self.assertEqual(0, func(0)) + + ci = c_int(0) + + func.argtypes = POINTER(c_int), + self.assertEqual(positive_address(addressof(ci)), + positive_address(func(byref(ci)))) + + func.argtypes = c_char_p, + self.assertRaises(ArgumentError, func, byref(ci)) + + func.argtypes = POINTER(c_short), + self.assertRaises(ArgumentError, func, byref(ci)) + + func.argtypes = POINTER(c_double), + self.assertRaises(ArgumentError, func, byref(ci)) + + def test_POINTER_c_char_arg(self): + func = testdll._testfunc_p_p + func.restype = c_char_p + func.argtypes = POINTER(c_char), + + self.assertEqual(None, func(None)) + self.assertEqual(b"123", func(b"123")) + self.assertEqual(None, func(c_char_p(None))) + self.assertEqual(b"123", func(c_char_p(b"123"))) + + self.assertEqual(b"123", func(c_buffer(b"123"))) + ca = c_char(b"a") + self.assertEqual(ord(b"a"), func(pointer(ca))[0]) + self.assertEqual(ord(b"a"), func(byref(ca))[0]) + + def test_c_char_p_arg(self): + func = testdll._testfunc_p_p + func.restype = c_char_p + func.argtypes = c_char_p, + + self.assertEqual(None, func(None)) + self.assertEqual(b"123", func(b"123")) + self.assertEqual(None, func(c_char_p(None))) + self.assertEqual(b"123", func(c_char_p(b"123"))) + + self.assertEqual(b"123", func(c_buffer(b"123"))) + ca = c_char(b"a") + self.assertEqual(ord(b"a"), func(pointer(ca))[0]) + self.assertEqual(ord(b"a"), func(byref(ca))[0]) + + def test_c_void_p_arg(self): + func = testdll._testfunc_p_p + func.restype = c_char_p + func.argtypes = c_void_p, + + self.assertEqual(None, func(None)) + self.assertEqual(b"123", func(b"123")) + self.assertEqual(b"123", func(c_char_p(b"123"))) + self.assertEqual(None, func(c_char_p(None))) + + self.assertEqual(b"123", func(c_buffer(b"123"))) + ca = c_char(b"a") + self.assertEqual(ord(b"a"), func(pointer(ca))[0]) + self.assertEqual(ord(b"a"), func(byref(ca))[0]) + + func(byref(c_int())) + func(pointer(c_int())) + func((c_int * 3)()) + + @need_symbol('c_wchar_p') + def test_c_void_p_arg_with_c_wchar_p(self): + func = testdll._testfunc_p_p + func.restype = c_wchar_p + func.argtypes = c_void_p, + + self.assertEqual(None, func(c_wchar_p(None))) + self.assertEqual("123", func(c_wchar_p("123"))) + + def test_instance(self): + func = testdll._testfunc_p_p + func.restype = c_void_p + + class X: + _as_parameter_ = None + + func.argtypes = c_void_p, + self.assertEqual(None, func(X())) + + func.argtypes = None + self.assertEqual(None, func(X())) + +@need_symbol('c_wchar') +class WCharPointersTestCase(unittest.TestCase): + + def setUp(self): + func = testdll._testfunc_p_p + func.restype = c_int + func.argtypes = None + + + def test_POINTER_c_wchar_arg(self): + func = testdll._testfunc_p_p + func.restype = c_wchar_p + func.argtypes = POINTER(c_wchar), + + self.assertEqual(None, func(None)) + self.assertEqual("123", func("123")) + self.assertEqual(None, func(c_wchar_p(None))) + self.assertEqual("123", func(c_wchar_p("123"))) + + self.assertEqual("123", func(c_wbuffer("123"))) + ca = c_wchar("a") + self.assertEqual("a", func(pointer(ca))[0]) + self.assertEqual("a", func(byref(ca))[0]) + + def test_c_wchar_p_arg(self): + func = testdll._testfunc_p_p + func.restype = c_wchar_p + func.argtypes = c_wchar_p, + + c_wchar_p.from_param("123") + + self.assertEqual(None, func(None)) + self.assertEqual("123", func("123")) + self.assertEqual(None, func(c_wchar_p(None))) + self.assertEqual("123", func(c_wchar_p("123"))) + + # XXX Currently, these raise TypeErrors, although they shouldn't: + self.assertEqual("123", func(c_wbuffer("123"))) + ca = c_wchar("a") + self.assertEqual("a", func(pointer(ca))[0]) + self.assertEqual("a", func(byref(ca))[0]) + +class ArrayTest(unittest.TestCase): + def test(self): + func = testdll._testfunc_ai8 + func.restype = POINTER(c_int) + func.argtypes = c_int * 8, + + func((c_int * 8)(1, 2, 3, 4, 5, 6, 7, 8)) + + # This did crash before: + + def func(): pass + CFUNCTYPE(None, c_int * 3)(func) + +################################################################ + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/test_ctypes/test_python_api.py b/Lib/test/test_ctypes/test_python_api.py new file mode 100644 index 0000000..49571f9 --- /dev/null +++ b/Lib/test/test_ctypes/test_python_api.py @@ -0,0 +1,85 @@ +from ctypes import * +import unittest +from test import support + +################################################################ +# This section should be moved into ctypes\__init__.py, when it's ready. + +from _ctypes import PyObj_FromPtr + +################################################################ + +from sys import getrefcount as grc + +class PythonAPITestCase(unittest.TestCase): + + def test_PyBytes_FromStringAndSize(self): + PyBytes_FromStringAndSize = pythonapi.PyBytes_FromStringAndSize + + PyBytes_FromStringAndSize.restype = py_object + PyBytes_FromStringAndSize.argtypes = c_char_p, c_size_t + + self.assertEqual(PyBytes_FromStringAndSize(b"abcdefghi", 3), b"abc") + + @support.refcount_test + def test_PyString_FromString(self): + pythonapi.PyBytes_FromString.restype = py_object + pythonapi.PyBytes_FromString.argtypes = (c_char_p,) + + s = b"abc" + refcnt = grc(s) + pyob = pythonapi.PyBytes_FromString(s) + self.assertEqual(grc(s), refcnt) + self.assertEqual(s, pyob) + del pyob + self.assertEqual(grc(s), refcnt) + + @support.refcount_test + def test_PyLong_Long(self): + ref42 = grc(42) + pythonapi.PyLong_FromLong.restype = py_object + self.assertEqual(pythonapi.PyLong_FromLong(42), 42) + + self.assertEqual(grc(42), ref42) + + pythonapi.PyLong_AsLong.argtypes = (py_object,) + pythonapi.PyLong_AsLong.restype = c_long + + res = pythonapi.PyLong_AsLong(42) + self.assertEqual(grc(res), ref42 + 1) + del res + self.assertEqual(grc(42), ref42) + + @support.refcount_test + def test_PyObj_FromPtr(self): + s = "abc def ghi jkl" + ref = grc(s) + # id(python-object) is the address + pyobj = PyObj_FromPtr(id(s)) + self.assertIs(s, pyobj) + + self.assertEqual(grc(s), ref + 1) + del pyobj + self.assertEqual(grc(s), ref) + + def test_PyOS_snprintf(self): + PyOS_snprintf = pythonapi.PyOS_snprintf + PyOS_snprintf.argtypes = POINTER(c_char), c_size_t, c_char_p + + buf = c_buffer(256) + PyOS_snprintf(buf, sizeof(buf), b"Hello from %s", b"ctypes") + self.assertEqual(buf.value, b"Hello from ctypes") + + PyOS_snprintf(buf, sizeof(buf), b"Hello from %s (%d, %d, %d)", b"ctypes", 1, 2, 3) + self.assertEqual(buf.value, b"Hello from ctypes (1, 2, 3)") + + # not enough arguments + self.assertRaises(TypeError, PyOS_snprintf, buf) + + def test_pyobject_repr(self): + self.assertEqual(repr(py_object()), "py_object()") + self.assertEqual(repr(py_object(42)), "py_object(42)") + self.assertEqual(repr(py_object(object)), "py_object(%r)" % object) + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_ctypes/test_random_things.py b/Lib/test/test_ctypes/test_random_things.py new file mode 100644 index 0000000..2988e27 --- /dev/null +++ b/Lib/test/test_ctypes/test_random_things.py @@ -0,0 +1,77 @@ +from ctypes import * +import contextlib +from test import support +import unittest +import sys + + +def callback_func(arg): + 42 / arg + raise ValueError(arg) + +@unittest.skipUnless(sys.platform == "win32", 'Windows-specific test') +class call_function_TestCase(unittest.TestCase): + # _ctypes.call_function is deprecated and private, but used by + # Gary Bishp's readline module. If we have it, we must test it as well. + + def test(self): + from _ctypes import call_function + windll.kernel32.LoadLibraryA.restype = c_void_p + windll.kernel32.GetProcAddress.argtypes = c_void_p, c_char_p + windll.kernel32.GetProcAddress.restype = c_void_p + + hdll = windll.kernel32.LoadLibraryA(b"kernel32") + funcaddr = windll.kernel32.GetProcAddress(hdll, b"GetModuleHandleA") + + self.assertEqual(call_function(funcaddr, (None,)), + windll.kernel32.GetModuleHandleA(None)) + +class CallbackTracbackTestCase(unittest.TestCase): + # When an exception is raised in a ctypes callback function, the C + # code prints a traceback. + # + # This test makes sure the exception types *and* the exception + # value is printed correctly. + # + # Changed in 0.9.3: No longer is '(in callback)' prepended to the + # error message - instead an additional frame for the C code is + # created, then a full traceback printed. When SystemExit is + # raised in a callback function, the interpreter exits. + + @contextlib.contextmanager + def expect_unraisable(self, exc_type, exc_msg=None): + with support.catch_unraisable_exception() as cm: + yield + + self.assertIsInstance(cm.unraisable.exc_value, exc_type) + if exc_msg is not None: + self.assertEqual(str(cm.unraisable.exc_value), exc_msg) + self.assertEqual(cm.unraisable.err_msg, + "Exception ignored on calling ctypes " + "callback function") + self.assertIs(cm.unraisable.object, callback_func) + + def test_ValueError(self): + cb = CFUNCTYPE(c_int, c_int)(callback_func) + with self.expect_unraisable(ValueError, '42'): + cb(42) + + def test_IntegerDivisionError(self): + cb = CFUNCTYPE(c_int, c_int)(callback_func) + with self.expect_unraisable(ZeroDivisionError): + cb(0) + + def test_FloatDivisionError(self): + cb = CFUNCTYPE(c_int, c_double)(callback_func) + with self.expect_unraisable(ZeroDivisionError): + cb(0.0) + + def test_TypeErrorDivisionError(self): + cb = CFUNCTYPE(c_int, c_char_p)(callback_func) + err_msg = "unsupported operand type(s) for /: 'int' and 'bytes'" + with self.expect_unraisable(TypeError, err_msg): + cb(b"spam") + + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/test_ctypes/test_refcounts.py b/Lib/test/test_ctypes/test_refcounts.py new file mode 100644 index 0000000..f2edfa6 --- /dev/null +++ b/Lib/test/test_ctypes/test_refcounts.py @@ -0,0 +1,101 @@ +import unittest +from test import support +import ctypes +import gc + +MyCallback = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_int) +OtherCallback = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_int, ctypes.c_ulonglong) + +import _ctypes_test +dll = ctypes.CDLL(_ctypes_test.__file__) + +class RefcountTestCase(unittest.TestCase): + + @support.refcount_test + def test_1(self): + from sys import getrefcount as grc + + f = dll._testfunc_callback_i_if + f.restype = ctypes.c_int + f.argtypes = [ctypes.c_int, MyCallback] + + def callback(value): + #print "called back with", value + return value + + self.assertEqual(grc(callback), 2) + cb = MyCallback(callback) + + self.assertGreater(grc(callback), 2) + result = f(-10, cb) + self.assertEqual(result, -18) + cb = None + + gc.collect() + + self.assertEqual(grc(callback), 2) + + + @support.refcount_test + def test_refcount(self): + from sys import getrefcount as grc + def func(*args): + pass + # this is the standard refcount for func + self.assertEqual(grc(func), 2) + + # the CFuncPtr instance holds at least one refcount on func: + f = OtherCallback(func) + self.assertGreater(grc(func), 2) + + # and may release it again + del f + self.assertGreaterEqual(grc(func), 2) + + # but now it must be gone + gc.collect() + self.assertEqual(grc(func), 2) + + class X(ctypes.Structure): + _fields_ = [("a", OtherCallback)] + x = X() + x.a = OtherCallback(func) + + # the CFuncPtr instance holds at least one refcount on func: + self.assertGreater(grc(func), 2) + + # and may release it again + del x + self.assertGreaterEqual(grc(func), 2) + + # and now it must be gone again + gc.collect() + self.assertEqual(grc(func), 2) + + f = OtherCallback(func) + + # the CFuncPtr instance holds at least one refcount on func: + self.assertGreater(grc(func), 2) + + # create a cycle + f.cycle = f + + del f + gc.collect() + self.assertEqual(grc(func), 2) + +class AnotherLeak(unittest.TestCase): + def test_callback(self): + import sys + + proto = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_int, ctypes.c_int) + def func(a, b): + return a * b * 2 + f = proto(func) + + a = sys.getrefcount(ctypes.c_int) + f(1, 2) + self.assertEqual(sys.getrefcount(ctypes.c_int), a) + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/test_ctypes/test_repr.py b/Lib/test/test_ctypes/test_repr.py new file mode 100644 index 0000000..60a2c80 --- /dev/null +++ b/Lib/test/test_ctypes/test_repr.py @@ -0,0 +1,29 @@ +from ctypes import * +import unittest + +subclasses = [] +for base in [c_byte, c_short, c_int, c_long, c_longlong, + c_ubyte, c_ushort, c_uint, c_ulong, c_ulonglong, + c_float, c_double, c_longdouble, c_bool]: + class X(base): + pass + subclasses.append(X) + +class X(c_char): + pass + +# This test checks if the __repr__ is correct for subclasses of simple types + +class ReprTest(unittest.TestCase): + def test_numbers(self): + for typ in subclasses: + base = typ.__bases__[0] + self.assertTrue(repr(base(42)).startswith(base.__name__)) + self.assertEqual(": " + "expected bytes, int found") + + cls, msg = self.get_except(Person, b"Someone", (b"a", b"b", b"c")) + self.assertEqual(cls, RuntimeError) + self.assertEqual(msg, + "(Phone) : too many initializers") + + def test_huge_field_name(self): + # issue12881: segfault with large structure field names + def create_class(length): + class S(Structure): + _fields_ = [('x' * length, c_int)] + + for length in [10 ** i for i in range(0, 8)]: + try: + create_class(length) + except MemoryError: + # MemoryErrors are OK, we just don't want to segfault + pass + + def get_except(self, func, *args): + try: + func(*args) + except Exception as detail: + return detail.__class__, str(detail) + + @unittest.skip('test disabled') + def test_subclass_creation(self): + meta = type(Structure) + # same as 'class X(Structure): pass' + # fails, since we need either a _fields_ or a _abstract_ attribute + cls, msg = self.get_except(meta, "X", (Structure,), {}) + self.assertEqual((cls, msg), + (AttributeError, "class must define a '_fields_' attribute")) + + def test_abstract_class(self): + class X(Structure): + _abstract_ = "something" + # try 'X()' + cls, msg = self.get_except(eval, "X()", locals()) + self.assertEqual((cls, msg), (TypeError, "abstract class")) + + def test_methods(self): +## class X(Structure): +## _fields_ = [] + + self.assertIn("in_dll", dir(type(Structure))) + self.assertIn("from_address", dir(type(Structure))) + self.assertIn("in_dll", dir(type(Structure))) + + def test_positional_args(self): + # see also http://bugs.python.org/issue5042 + class W(Structure): + _fields_ = [("a", c_int), ("b", c_int)] + class X(W): + _fields_ = [("c", c_int)] + class Y(X): + pass + class Z(Y): + _fields_ = [("d", c_int), ("e", c_int), ("f", c_int)] + + z = Z(1, 2, 3, 4, 5, 6) + self.assertEqual((z.a, z.b, z.c, z.d, z.e, z.f), + (1, 2, 3, 4, 5, 6)) + z = Z(1) + self.assertEqual((z.a, z.b, z.c, z.d, z.e, z.f), + (1, 0, 0, 0, 0, 0)) + self.assertRaises(TypeError, lambda: Z(1, 2, 3, 4, 5, 6, 7)) + + def test_pass_by_value(self): + # This should mirror the Test structure + # in Modules/_ctypes/_ctypes_test.c + class Test(Structure): + _fields_ = [ + ('first', c_ulong), + ('second', c_ulong), + ('third', c_ulong), + ] + + s = Test() + s.first = 0xdeadbeef + s.second = 0xcafebabe + s.third = 0x0bad1dea + dll = CDLL(_ctypes_test.__file__) + func = dll._testfunc_large_struct_update_value + func.argtypes = (Test,) + func.restype = None + func(s) + self.assertEqual(s.first, 0xdeadbeef) + self.assertEqual(s.second, 0xcafebabe) + self.assertEqual(s.third, 0x0bad1dea) + + def test_pass_by_value_finalizer(self): + # bpo-37140: Similar to test_pass_by_value(), but the Python structure + # has a finalizer (__del__() method): the finalizer must only be called + # once. + + finalizer_calls = [] + + class Test(Structure): + _fields_ = [ + ('first', c_ulong), + ('second', c_ulong), + ('third', c_ulong), + ] + def __del__(self): + finalizer_calls.append("called") + + s = Test(1, 2, 3) + # Test the StructUnionType_paramfunc() code path which copies the + # structure: if the structure is larger than sizeof(void*). + self.assertGreater(sizeof(s), sizeof(c_void_p)) + + dll = CDLL(_ctypes_test.__file__) + func = dll._testfunc_large_struct_update_value + func.argtypes = (Test,) + func.restype = None + func(s) + # bpo-37140: Passing the structure by reference must not call + # its finalizer! + self.assertEqual(finalizer_calls, []) + self.assertEqual(s.first, 1) + self.assertEqual(s.second, 2) + self.assertEqual(s.third, 3) + + # The finalizer must be called exactly once + s = None + support.gc_collect() + self.assertEqual(finalizer_calls, ["called"]) + + def test_pass_by_value_in_register(self): + class X(Structure): + _fields_ = [ + ('first', c_uint), + ('second', c_uint) + ] + + s = X() + s.first = 0xdeadbeef + s.second = 0xcafebabe + dll = CDLL(_ctypes_test.__file__) + func = dll._testfunc_reg_struct_update_value + func.argtypes = (X,) + func.restype = None + func(s) + self.assertEqual(s.first, 0xdeadbeef) + self.assertEqual(s.second, 0xcafebabe) + got = X.in_dll(dll, "last_tfrsuv_arg") + self.assertEqual(s.first, got.first) + self.assertEqual(s.second, got.second) + + def test_array_in_struct(self): + # See bpo-22273 + + # These should mirror the structures in Modules/_ctypes/_ctypes_test.c + class Test2(Structure): + _fields_ = [ + ('data', c_ubyte * 16), + ] + + class Test3(Structure): + _fields_ = [ + ('data', c_double * 2), + ] + + class Test3A(Structure): + _fields_ = [ + ('data', c_float * 2), + ] + + class Test3B(Test3A): + _fields_ = [ + ('more_data', c_float * 2), + ] + + s = Test2() + expected = 0 + for i in range(16): + s.data[i] = i + expected += i + dll = CDLL(_ctypes_test.__file__) + func = dll._testfunc_array_in_struct1 + func.restype = c_int + func.argtypes = (Test2,) + result = func(s) + self.assertEqual(result, expected) + # check the passed-in struct hasn't changed + for i in range(16): + self.assertEqual(s.data[i], i) + + s = Test3() + s.data[0] = 3.14159 + s.data[1] = 2.71828 + expected = 3.14159 + 2.71828 + func = dll._testfunc_array_in_struct2 + func.restype = c_double + func.argtypes = (Test3,) + result = func(s) + self.assertEqual(result, expected) + # check the passed-in struct hasn't changed + self.assertEqual(s.data[0], 3.14159) + self.assertEqual(s.data[1], 2.71828) + + s = Test3B() + s.data[0] = 3.14159 + s.data[1] = 2.71828 + s.more_data[0] = -3.0 + s.more_data[1] = -2.0 + + expected = 3.14159 + 2.71828 - 5.0 + func = dll._testfunc_array_in_struct2a + func.restype = c_double + func.argtypes = (Test3B,) + result = func(s) + self.assertAlmostEqual(result, expected, places=6) + # check the passed-in struct hasn't changed + self.assertAlmostEqual(s.data[0], 3.14159, places=6) + self.assertAlmostEqual(s.data[1], 2.71828, places=6) + self.assertAlmostEqual(s.more_data[0], -3.0, places=6) + self.assertAlmostEqual(s.more_data[1], -2.0, places=6) + + def test_38368(self): + class U(Union): + _fields_ = [ + ('f1', c_uint8 * 16), + ('f2', c_uint16 * 8), + ('f3', c_uint32 * 4), + ] + u = U() + u.f3[0] = 0x01234567 + u.f3[1] = 0x89ABCDEF + u.f3[2] = 0x76543210 + u.f3[3] = 0xFEDCBA98 + f1 = [u.f1[i] for i in range(16)] + f2 = [u.f2[i] for i in range(8)] + if sys.byteorder == 'little': + self.assertEqual(f1, [0x67, 0x45, 0x23, 0x01, + 0xef, 0xcd, 0xab, 0x89, + 0x10, 0x32, 0x54, 0x76, + 0x98, 0xba, 0xdc, 0xfe]) + self.assertEqual(f2, [0x4567, 0x0123, 0xcdef, 0x89ab, + 0x3210, 0x7654, 0xba98, 0xfedc]) + + @unittest.skipIf(True, 'Test disabled for now - see bpo-16575/bpo-16576') + def test_union_by_value(self): + # See bpo-16575 + + # These should mirror the structures in Modules/_ctypes/_ctypes_test.c + + class Nested1(Structure): + _fields_ = [ + ('an_int', c_int), + ('another_int', c_int), + ] + + class Test4(Union): + _fields_ = [ + ('a_long', c_long), + ('a_struct', Nested1), + ] + + class Nested2(Structure): + _fields_ = [ + ('an_int', c_int), + ('a_union', Test4), + ] + + class Test5(Structure): + _fields_ = [ + ('an_int', c_int), + ('nested', Nested2), + ('another_int', c_int), + ] + + test4 = Test4() + dll = CDLL(_ctypes_test.__file__) + with self.assertRaises(TypeError) as ctx: + func = dll._testfunc_union_by_value1 + func.restype = c_long + func.argtypes = (Test4,) + result = func(test4) + self.assertEqual(ctx.exception.args[0], 'item 1 in _argtypes_ passes ' + 'a union by value, which is unsupported.') + test5 = Test5() + with self.assertRaises(TypeError) as ctx: + func = dll._testfunc_union_by_value2 + func.restype = c_long + func.argtypes = (Test5,) + result = func(test5) + self.assertEqual(ctx.exception.args[0], 'item 1 in _argtypes_ passes ' + 'a union by value, which is unsupported.') + + # passing by reference should be OK + test4.a_long = 12345; + func = dll._testfunc_union_by_reference1 + func.restype = c_long + func.argtypes = (POINTER(Test4),) + result = func(byref(test4)) + self.assertEqual(result, 12345) + self.assertEqual(test4.a_long, 0) + self.assertEqual(test4.a_struct.an_int, 0) + self.assertEqual(test4.a_struct.another_int, 0) + test4.a_struct.an_int = 0x12340000 + test4.a_struct.another_int = 0x5678 + func = dll._testfunc_union_by_reference2 + func.restype = c_long + func.argtypes = (POINTER(Test4),) + result = func(byref(test4)) + self.assertEqual(result, 0x12345678) + self.assertEqual(test4.a_long, 0) + self.assertEqual(test4.a_struct.an_int, 0) + self.assertEqual(test4.a_struct.another_int, 0) + test5.an_int = 0x12000000 + test5.nested.an_int = 0x345600 + test5.another_int = 0x78 + func = dll._testfunc_union_by_reference3 + func.restype = c_long + func.argtypes = (POINTER(Test5),) + result = func(byref(test5)) + self.assertEqual(result, 0x12345678) + self.assertEqual(test5.an_int, 0) + self.assertEqual(test5.nested.an_int, 0) + self.assertEqual(test5.another_int, 0) + + @unittest.skipIf(True, 'Test disabled for now - see bpo-16575/bpo-16576') + def test_bitfield_by_value(self): + # See bpo-16576 + + # These should mirror the structures in Modules/_ctypes/_ctypes_test.c + + class Test6(Structure): + _fields_ = [ + ('A', c_int, 1), + ('B', c_int, 2), + ('C', c_int, 3), + ('D', c_int, 2), + ] + + test6 = Test6() + # As these are signed int fields, all are logically -1 due to sign + # extension. + test6.A = 1 + test6.B = 3 + test6.C = 7 + test6.D = 3 + dll = CDLL(_ctypes_test.__file__) + with self.assertRaises(TypeError) as ctx: + func = dll._testfunc_bitfield_by_value1 + func.restype = c_long + func.argtypes = (Test6,) + result = func(test6) + self.assertEqual(ctx.exception.args[0], 'item 1 in _argtypes_ passes ' + 'a struct/union with a bitfield by value, which is ' + 'unsupported.') + # passing by reference should be OK + func = dll._testfunc_bitfield_by_reference1 + func.restype = c_long + func.argtypes = (POINTER(Test6),) + result = func(byref(test6)) + self.assertEqual(result, -4) + self.assertEqual(test6.A, 0) + self.assertEqual(test6.B, 0) + self.assertEqual(test6.C, 0) + self.assertEqual(test6.D, 0) + + class Test7(Structure): + _fields_ = [ + ('A', c_uint, 1), + ('B', c_uint, 2), + ('C', c_uint, 3), + ('D', c_uint, 2), + ] + test7 = Test7() + test7.A = 1 + test7.B = 3 + test7.C = 7 + test7.D = 3 + func = dll._testfunc_bitfield_by_reference2 + func.restype = c_long + func.argtypes = (POINTER(Test7),) + result = func(byref(test7)) + self.assertEqual(result, 14) + self.assertEqual(test7.A, 0) + self.assertEqual(test7.B, 0) + self.assertEqual(test7.C, 0) + self.assertEqual(test7.D, 0) + + # for a union with bitfields, the union check happens first + class Test8(Union): + _fields_ = [ + ('A', c_int, 1), + ('B', c_int, 2), + ('C', c_int, 3), + ('D', c_int, 2), + ] + + test8 = Test8() + with self.assertRaises(TypeError) as ctx: + func = dll._testfunc_bitfield_by_value2 + func.restype = c_long + func.argtypes = (Test8,) + result = func(test8) + self.assertEqual(ctx.exception.args[0], 'item 1 in _argtypes_ passes ' + 'a union by value, which is unsupported.') + +class PointerMemberTestCase(unittest.TestCase): + + def test(self): + # a Structure with a POINTER field + class S(Structure): + _fields_ = [("array", POINTER(c_int))] + + s = S() + # We can assign arrays of the correct type + s.array = (c_int * 3)(1, 2, 3) + items = [s.array[i] for i in range(3)] + self.assertEqual(items, [1, 2, 3]) + + # The following are bugs, but are included here because the unittests + # also describe the current behaviour. + # + # This fails with SystemError: bad arg to internal function + # or with IndexError (with a patch I have) + + s.array[0] = 42 + + items = [s.array[i] for i in range(3)] + self.assertEqual(items, [42, 2, 3]) + + s.array[0] = 1 + +## s.array[1] = 42 + + items = [s.array[i] for i in range(3)] + self.assertEqual(items, [1, 2, 3]) + + def test_none_to_pointer_fields(self): + class S(Structure): + _fields_ = [("x", c_int), + ("p", POINTER(c_int))] + + s = S() + s.x = 12345678 + s.p = None + self.assertEqual(s.x, 12345678) + +class TestRecursiveStructure(unittest.TestCase): + def test_contains_itself(self): + class Recursive(Structure): + pass + + try: + Recursive._fields_ = [("next", Recursive)] + except AttributeError as details: + self.assertIn("Structure or union cannot contain itself", + str(details)) + else: + self.fail("Structure or union cannot contain itself") + + + def test_vice_versa(self): + class First(Structure): + pass + class Second(Structure): + pass + + First._fields_ = [("second", Second)] + + try: + Second._fields_ = [("first", First)] + except AttributeError as details: + self.assertIn("_fields_ is final", str(details)) + else: + self.fail("AttributeError not raised") + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/test_ctypes/test_unaligned_structures.py b/Lib/test/test_ctypes/test_unaligned_structures.py new file mode 100644 index 0000000..ee7fb45 --- /dev/null +++ b/Lib/test/test_ctypes/test_unaligned_structures.py @@ -0,0 +1,43 @@ +import sys, unittest +from ctypes import * + +structures = [] +byteswapped_structures = [] + + +if sys.byteorder == "little": + SwappedStructure = BigEndianStructure +else: + SwappedStructure = LittleEndianStructure + +for typ in [c_short, c_int, c_long, c_longlong, + c_float, c_double, + c_ushort, c_uint, c_ulong, c_ulonglong]: + class X(Structure): + _pack_ = 1 + _fields_ = [("pad", c_byte), + ("value", typ)] + class Y(SwappedStructure): + _pack_ = 1 + _fields_ = [("pad", c_byte), + ("value", typ)] + structures.append(X) + byteswapped_structures.append(Y) + +class TestStructures(unittest.TestCase): + def test_native(self): + for typ in structures: + self.assertEqual(typ.value.offset, 1) + o = typ() + o.value = 4 + self.assertEqual(o.value, 4) + + def test_swapped(self): + for typ in byteswapped_structures: + self.assertEqual(typ.value.offset, 1) + o = typ() + o.value = 4 + self.assertEqual(o.value, 4) + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/test_ctypes/test_unicode.py b/Lib/test/test_ctypes/test_unicode.py new file mode 100644 index 0000000..319cb3b --- /dev/null +++ b/Lib/test/test_ctypes/test_unicode.py @@ -0,0 +1,64 @@ +import unittest +import ctypes +from test.test_ctypes import need_symbol + +import _ctypes_test + +@need_symbol('c_wchar') +class UnicodeTestCase(unittest.TestCase): + def test_wcslen(self): + dll = ctypes.CDLL(_ctypes_test.__file__) + wcslen = dll.my_wcslen + wcslen.argtypes = [ctypes.c_wchar_p] + + self.assertEqual(wcslen("abc"), 3) + self.assertEqual(wcslen("ab\u2070"), 3) + self.assertRaises(ctypes.ArgumentError, wcslen, b"ab\xe4") + + def test_buffers(self): + buf = ctypes.create_unicode_buffer("abc") + self.assertEqual(len(buf), 3+1) + + buf = ctypes.create_unicode_buffer("ab\xe4\xf6\xfc") + self.assertEqual(buf[:], "ab\xe4\xf6\xfc\0") + self.assertEqual(buf[::], "ab\xe4\xf6\xfc\0") + self.assertEqual(buf[::-1], '\x00\xfc\xf6\xe4ba') + self.assertEqual(buf[::2], 'a\xe4\xfc') + self.assertEqual(buf[6:5:-1], "") + + def test_embedded_null(self): + class TestStruct(ctypes.Structure): + _fields_ = [("unicode", ctypes.c_wchar_p)] + t = TestStruct() + # This would raise a ValueError: + t.unicode = "foo\0bar\0\0" + + +func = ctypes.CDLL(_ctypes_test.__file__)._testfunc_p_p + +class StringTestCase(UnicodeTestCase): + def setUp(self): + func.argtypes = [ctypes.c_char_p] + func.restype = ctypes.c_char_p + + def tearDown(self): + func.argtypes = None + func.restype = ctypes.c_int + + def test_func(self): + self.assertEqual(func(b"abc\xe4"), b"abc\xe4") + + def test_buffers(self): + buf = ctypes.create_string_buffer(b"abc") + self.assertEqual(len(buf), 3+1) + + buf = ctypes.create_string_buffer(b"ab\xe4\xf6\xfc") + self.assertEqual(buf[:], b"ab\xe4\xf6\xfc\0") + self.assertEqual(buf[::], b"ab\xe4\xf6\xfc\0") + self.assertEqual(buf[::-1], b'\x00\xfc\xf6\xe4ba') + self.assertEqual(buf[::2], b'a\xe4\xfc') + self.assertEqual(buf[6:5:-1], b"") + + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/test_ctypes/test_values.py b/Lib/test/test_ctypes/test_values.py new file mode 100644 index 0000000..435fdd2 --- /dev/null +++ b/Lib/test/test_ctypes/test_values.py @@ -0,0 +1,103 @@ +""" +A testcase which accesses *values* in a dll. +""" + +import _imp +import importlib.util +import unittest +import sys +from ctypes import * +from test.support import import_helper + +import _ctypes_test + +class ValuesTestCase(unittest.TestCase): + + def test_an_integer(self): + # This test checks and changes an integer stored inside the + # _ctypes_test dll/shared lib. + ctdll = CDLL(_ctypes_test.__file__) + an_integer = c_int.in_dll(ctdll, "an_integer") + x = an_integer.value + self.assertEqual(x, ctdll.get_an_integer()) + an_integer.value *= 2 + self.assertEqual(x*2, ctdll.get_an_integer()) + # To avoid test failures when this test is repeated several + # times the original value must be restored + an_integer.value = x + self.assertEqual(x, ctdll.get_an_integer()) + + def test_undefined(self): + ctdll = CDLL(_ctypes_test.__file__) + self.assertRaises(ValueError, c_int.in_dll, ctdll, "Undefined_Symbol") + +class PythonValuesTestCase(unittest.TestCase): + """This test only works when python itself is a dll/shared library""" + + def test_optimizeflag(self): + # This test accesses the Py_OptimizeFlag integer, which is + # exported by the Python dll and should match the sys.flags value + + opt = c_int.in_dll(pythonapi, "Py_OptimizeFlag").value + self.assertEqual(opt, sys.flags.optimize) + + def test_frozentable(self): + # Python exports a PyImport_FrozenModules symbol. This is a + # pointer to an array of struct _frozen entries. The end of the + # array is marked by an entry containing a NULL name and zero + # size. + + # In standard Python, this table contains a __hello__ + # module, and a __phello__ package containing a spam + # module. + class struct_frozen(Structure): + _fields_ = [("name", c_char_p), + ("code", POINTER(c_ubyte)), + ("size", c_int), + ("is_package", c_int), + ("get_code", POINTER(c_ubyte)), # Function ptr + ] + FrozenTable = POINTER(struct_frozen) + + modules = [] + for group in ["Bootstrap", "Stdlib", "Test"]: + ft = FrozenTable.in_dll(pythonapi, f"_PyImport_Frozen{group}") + # ft is a pointer to the struct_frozen entries: + for entry in ft: + # This is dangerous. We *can* iterate over a pointer, but + # the loop will not terminate (maybe with an access + # violation;-) because the pointer instance has no size. + if entry.name is None: + break + modname = entry.name.decode("ascii") + modules.append(modname) + with self.subTest(modname): + if entry.size != 0: + # Do a sanity check on entry.size and entry.code. + self.assertGreater(abs(entry.size), 10) + self.assertTrue([entry.code[i] for i in range(abs(entry.size))]) + # Check the module's package-ness. + with import_helper.frozen_modules(): + spec = importlib.util.find_spec(modname) + if entry.is_package: + # It's a package. + self.assertIsNotNone(spec.submodule_search_locations) + else: + self.assertIsNone(spec.submodule_search_locations) + + with import_helper.frozen_modules(): + expected = _imp._frozen_module_names() + self.maxDiff = None + self.assertEqual(modules, expected, + "_PyImport_FrozenBootstrap example " + "in Doc/library/ctypes.rst may be out of date") + + from ctypes import _pointer_type_cache + del _pointer_type_cache[struct_frozen] + + def test_undefined(self): + self.assertRaises(ValueError, c_int.in_dll, pythonapi, + "Undefined_Symbol") + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/test_ctypes/test_varsize_struct.py b/Lib/test/test_ctypes/test_varsize_struct.py new file mode 100644 index 0000000..f409500 --- /dev/null +++ b/Lib/test/test_ctypes/test_varsize_struct.py @@ -0,0 +1,50 @@ +from ctypes import * +import unittest + +class VarSizeTest(unittest.TestCase): + def test_resize(self): + class X(Structure): + _fields_ = [("item", c_int), + ("array", c_int * 1)] + + self.assertEqual(sizeof(X), sizeof(c_int) * 2) + x = X() + x.item = 42 + x.array[0] = 100 + self.assertEqual(sizeof(x), sizeof(c_int) * 2) + + # make room for one additional item + new_size = sizeof(X) + sizeof(c_int) * 1 + resize(x, new_size) + self.assertEqual(sizeof(x), new_size) + self.assertEqual((x.item, x.array[0]), (42, 100)) + + # make room for 10 additional items + new_size = sizeof(X) + sizeof(c_int) * 9 + resize(x, new_size) + self.assertEqual(sizeof(x), new_size) + self.assertEqual((x.item, x.array[0]), (42, 100)) + + # make room for one additional item + new_size = sizeof(X) + sizeof(c_int) * 1 + resize(x, new_size) + self.assertEqual(sizeof(x), new_size) + self.assertEqual((x.item, x.array[0]), (42, 100)) + + def test_array_invalid_length(self): + # cannot create arrays with non-positive size + self.assertRaises(ValueError, lambda: c_int * -1) + self.assertRaises(ValueError, lambda: c_int * -3) + + def test_zerosized_array(self): + array = (c_int * 0)() + # accessing elements of zero-sized arrays raise IndexError + self.assertRaises(IndexError, array.__setitem__, 0, None) + self.assertRaises(IndexError, array.__getitem__, 0) + self.assertRaises(IndexError, array.__setitem__, 1, None) + self.assertRaises(IndexError, array.__getitem__, 1) + self.assertRaises(IndexError, array.__setitem__, -1, None) + self.assertRaises(IndexError, array.__getitem__, -1) + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_ctypes/test_win32.py b/Lib/test/test_ctypes/test_win32.py new file mode 100644 index 0000000..e51bdc8 --- /dev/null +++ b/Lib/test/test_ctypes/test_win32.py @@ -0,0 +1,136 @@ +# Windows specific tests + +from ctypes import * +import unittest, sys +from test import support + +import _ctypes_test + +@unittest.skipUnless(sys.platform == "win32", 'Windows-specific test') +class FunctionCallTestCase(unittest.TestCase): + @unittest.skipUnless('MSC' in sys.version, "SEH only supported by MSC") + @unittest.skipIf(sys.executable.lower().endswith('_d.exe'), + "SEH not enabled in debug builds") + def test_SEH(self): + # Disable faulthandler to prevent logging the warning: + # "Windows fatal exception: access violation" + with support.disable_faulthandler(): + # Call functions with invalid arguments, and make sure + # that access violations are trapped and raise an + # exception. + self.assertRaises(OSError, windll.kernel32.GetModuleHandleA, 32) + + def test_noargs(self): + # This is a special case on win32 x64 + windll.user32.GetDesktopWindow() + + +@unittest.skipUnless(sys.platform == "win32", 'Windows-specific test') +class ReturnStructSizesTestCase(unittest.TestCase): + def test_sizes(self): + dll = CDLL(_ctypes_test.__file__) + for i in range(1, 11): + fields = [ (f"f{f}", c_char) for f in range(1, i + 1)] + class S(Structure): + _fields_ = fields + f = getattr(dll, f"TestSize{i}") + f.restype = S + res = f() + for i, f in enumerate(fields): + value = getattr(res, f[0]) + expected = bytes([ord('a') + i]) + self.assertEqual(value, expected) + + + +@unittest.skipUnless(sys.platform == "win32", 'Windows-specific test') +class TestWintypes(unittest.TestCase): + def test_HWND(self): + from ctypes import wintypes + self.assertEqual(sizeof(wintypes.HWND), sizeof(c_void_p)) + + def test_PARAM(self): + from ctypes import wintypes + self.assertEqual(sizeof(wintypes.WPARAM), + sizeof(c_void_p)) + self.assertEqual(sizeof(wintypes.LPARAM), + sizeof(c_void_p)) + + def test_COMError(self): + from _ctypes import COMError + if support.HAVE_DOCSTRINGS: + self.assertEqual(COMError.__doc__, + "Raised when a COM method call failed.") + + ex = COMError(-1, "text", ("details",)) + self.assertEqual(ex.hresult, -1) + self.assertEqual(ex.text, "text") + self.assertEqual(ex.details, ("details",)) + +@unittest.skipUnless(sys.platform == "win32", 'Windows-specific test') +class TestWinError(unittest.TestCase): + def test_winerror(self): + # see Issue 16169 + import errno + ERROR_INVALID_PARAMETER = 87 + msg = FormatError(ERROR_INVALID_PARAMETER).strip() + args = (errno.EINVAL, msg, None, ERROR_INVALID_PARAMETER) + + e = WinError(ERROR_INVALID_PARAMETER) + self.assertEqual(e.args, args) + self.assertEqual(e.errno, errno.EINVAL) + self.assertEqual(e.winerror, ERROR_INVALID_PARAMETER) + + windll.kernel32.SetLastError(ERROR_INVALID_PARAMETER) + try: + raise WinError() + except OSError as exc: + e = exc + self.assertEqual(e.args, args) + self.assertEqual(e.errno, errno.EINVAL) + self.assertEqual(e.winerror, ERROR_INVALID_PARAMETER) + +class Structures(unittest.TestCase): + def test_struct_by_value(self): + class POINT(Structure): + _fields_ = [("x", c_long), + ("y", c_long)] + + class RECT(Structure): + _fields_ = [("left", c_long), + ("top", c_long), + ("right", c_long), + ("bottom", c_long)] + + dll = CDLL(_ctypes_test.__file__) + + pt = POINT(15, 25) + left = c_long.in_dll(dll, 'left') + top = c_long.in_dll(dll, 'top') + right = c_long.in_dll(dll, 'right') + bottom = c_long.in_dll(dll, 'bottom') + rect = RECT(left, top, right, bottom) + PointInRect = dll.PointInRect + PointInRect.argtypes = [POINTER(RECT), POINT] + self.assertEqual(1, PointInRect(byref(rect), pt)) + + ReturnRect = dll.ReturnRect + ReturnRect.argtypes = [c_int, RECT, POINTER(RECT), POINT, RECT, + POINTER(RECT), POINT, RECT] + ReturnRect.restype = RECT + for i in range(4): + ret = ReturnRect(i, rect, pointer(rect), pt, rect, + byref(rect), pt, rect) + # the c function will check and modify ret if something is + # passed in improperly + self.assertEqual(ret.left, left.value) + self.assertEqual(ret.right, right.value) + self.assertEqual(ret.top, top.value) + self.assertEqual(ret.bottom, bottom.value) + + # to not leak references, we must clean _pointer_type_cache + from ctypes import _pointer_type_cache + del _pointer_type_cache[RECT] + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/test_ctypes/test_wintypes.py b/Lib/test/test_ctypes/test_wintypes.py new file mode 100644 index 0000000..243d596 --- /dev/null +++ b/Lib/test/test_ctypes/test_wintypes.py @@ -0,0 +1,43 @@ +import unittest + +# also work on POSIX + +from ctypes import * +from ctypes import wintypes + + +class WinTypesTest(unittest.TestCase): + def test_variant_bool(self): + # reads 16-bits from memory, anything non-zero is True + for true_value in (1, 32767, 32768, 65535, 65537): + true = POINTER(c_int16)(c_int16(true_value)) + value = cast(true, POINTER(wintypes.VARIANT_BOOL)) + self.assertEqual(repr(value.contents), 'VARIANT_BOOL(True)') + + vb = wintypes.VARIANT_BOOL() + self.assertIs(vb.value, False) + vb.value = True + self.assertIs(vb.value, True) + vb.value = true_value + self.assertIs(vb.value, True) + + for false_value in (0, 65536, 262144, 2**33): + false = POINTER(c_int16)(c_int16(false_value)) + value = cast(false, POINTER(wintypes.VARIANT_BOOL)) + self.assertEqual(repr(value.contents), 'VARIANT_BOOL(False)') + + # allow any bool conversion on assignment to value + for set_value in (65536, 262144, 2**33): + vb = wintypes.VARIANT_BOOL() + vb.value = set_value + self.assertIs(vb.value, True) + + vb = wintypes.VARIANT_BOOL() + vb.value = [2, 3] + self.assertIs(vb.value, True) + vb.value = [] + self.assertIs(vb.value, False) + + +if __name__ == "__main__": + unittest.main() diff --git a/Makefile.pre.in b/Makefile.pre.in index eaaab5e..4b8a67f 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -1918,8 +1918,7 @@ LIBSUBDIRS= asyncio \ xmlrpc \ zoneinfo \ __phello__ -TESTSUBDIRS= ctypes/test \ - distutils/tests \ +TESTSUBDIRS= distutils/tests \ idlelib/idle_test \ lib2to3/tests \ lib2to3/tests/data \ @@ -1933,6 +1932,7 @@ TESTSUBDIRS= ctypes/test \ test/libregrtest test/sndhdrdata \ test/subprocessdata test/support \ test/test_asyncio \ + test/test_ctypes \ test/test_email test/test_email/data \ test/test_import \ test/test_import/data \ diff --git a/Misc/NEWS.d/next/Tests/2022-06-20-23-04-52.gh-issue-93839.OE3Ybk.rst b/Misc/NEWS.d/next/Tests/2022-06-20-23-04-52.gh-issue-93839.OE3Ybk.rst new file mode 100644 index 0000000..121b64b --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2022-06-20-23-04-52.gh-issue-93839.OE3Ybk.rst @@ -0,0 +1,2 @@ +Move ``Lib/ctypes/test/`` to ``Lib/test/test_ctypes/``. Patch by Victor +Stinner. diff --git a/PCbuild/lib.pyproj b/PCbuild/lib.pyproj index 43c570f..692b083 100644 --- a/PCbuild/lib.pyproj +++ b/PCbuild/lib.pyproj @@ -83,59 +83,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -944,7 +891,59 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1725,7 +1724,6 @@ - @@ -1769,6 +1767,7 @@ + diff --git a/Tools/wasm/wasm_assets.py b/Tools/wasm/wasm_assets.py index b7e8351..d0a0570 100755 --- a/Tools/wasm/wasm_assets.py +++ b/Tools/wasm/wasm_assets.py @@ -111,7 +111,6 @@ OMIT_MODULE_FILES = { # regression test sub directories OMIT_SUBDIRS = ( - "ctypes/test/", "tkinter/test/", "unittest/test/", ) -- cgit v0.12