1""" 2A testcase which accesses *values* in a dll. 3""" 4 5import _imp 6import importlib.util 7import unittest 8import sys 9from ctypes import * 10from test.support import import_helper 11 12import _ctypes_test 13 14class ValuesTestCase(unittest.TestCase): 15 16 def test_an_integer(self): 17 # This test checks and changes an integer stored inside the 18 # _ctypes_test dll/shared lib. 19 ctdll = CDLL(_ctypes_test.__file__) 20 an_integer = c_int.in_dll(ctdll, "an_integer") 21 x = an_integer.value 22 self.assertEqual(x, ctdll.get_an_integer()) 23 an_integer.value *= 2 24 self.assertEqual(x*2, ctdll.get_an_integer()) 25 # To avoid test failures when this test is repeated several 26 # times the original value must be restored 27 an_integer.value = x 28 self.assertEqual(x, ctdll.get_an_integer()) 29 30 def test_undefined(self): 31 ctdll = CDLL(_ctypes_test.__file__) 32 self.assertRaises(ValueError, c_int.in_dll, ctdll, "Undefined_Symbol") 33 34class PythonValuesTestCase(unittest.TestCase): 35 """This test only works when python itself is a dll/shared library""" 36 37 def test_optimizeflag(self): 38 # This test accesses the Py_OptimizeFlag integer, which is 39 # exported by the Python dll and should match the sys.flags value 40 41 opt = c_int.in_dll(pythonapi, "Py_OptimizeFlag").value 42 self.assertEqual(opt, sys.flags.optimize) 43 44 def test_frozentable(self): 45 # Python exports a PyImport_FrozenModules symbol. This is a 46 # pointer to an array of struct _frozen entries. The end of the 47 # array is marked by an entry containing a NULL name and zero 48 # size. 49 50 # In standard Python, this table contains a __hello__ 51 # module, and a __phello__ package containing a spam 52 # module. 53 class struct_frozen(Structure): 54 _fields_ = [("name", c_char_p), 55 ("code", POINTER(c_ubyte)), 56 ("size", c_int), 57 ("is_package", c_int), 58 ("get_code", POINTER(c_ubyte)), # Function ptr 59 ] 60 FrozenTable = POINTER(struct_frozen) 61 62 modules = [] 63 for group in ["Bootstrap", "Stdlib", "Test"]: 64 ft = FrozenTable.in_dll(pythonapi, f"_PyImport_Frozen{group}") 65 # ft is a pointer to the struct_frozen entries: 66 for entry in ft: 67 # This is dangerous. We *can* iterate over a pointer, but 68 # the loop will not terminate (maybe with an access 69 # violation;-) because the pointer instance has no size. 70 if entry.name is None: 71 break 72 modname = entry.name.decode("ascii") 73 modules.append(modname) 74 with self.subTest(modname): 75 if entry.size != 0: 76 # Do a sanity check on entry.size and entry.code. 77 self.assertGreater(abs(entry.size), 10) 78 self.assertTrue([entry.code[i] for i in range(abs(entry.size))]) 79 # Check the module's package-ness. 80 with import_helper.frozen_modules(): 81 spec = importlib.util.find_spec(modname) 82 if entry.is_package: 83 # It's a package. 84 self.assertIsNotNone(spec.submodule_search_locations) 85 else: 86 self.assertIsNone(spec.submodule_search_locations) 87 88 with import_helper.frozen_modules(): 89 expected = _imp._frozen_module_names() 90 self.maxDiff = None 91 self.assertEqual(modules, expected, 92 "_PyImport_FrozenBootstrap example " 93 "in Doc/library/ctypes.rst may be out of date") 94 95 from ctypes import _pointer_type_cache 96 del _pointer_type_cache[struct_frozen] 97 98 def test_undefined(self): 99 self.assertRaises(ValueError, c_int.in_dll, pythonapi, 100 "Undefined_Symbol") 101 102if __name__ == '__main__': 103 unittest.main() 104