1""" 2A testcase which accesses *values* in a dll. 3""" 4 5import unittest 6import sys 7from ctypes import * 8 9import _ctypes_test 10 11class ValuesTestCase(unittest.TestCase): 12 13 def test_an_integer(self): 14 # This test checks and changes an integer stored inside the 15 # _ctypes_test dll/shared lib. 16 ctdll = CDLL(_ctypes_test.__file__) 17 an_integer = c_int.in_dll(ctdll, "an_integer") 18 x = an_integer.value 19 self.assertEqual(x, ctdll.get_an_integer()) 20 an_integer.value *= 2 21 self.assertEqual(x*2, ctdll.get_an_integer()) 22 # To avoid test failures when this test is repeated several 23 # times the original value must be restored 24 an_integer.value = x 25 self.assertEqual(x, ctdll.get_an_integer()) 26 27 def test_undefined(self): 28 ctdll = CDLL(_ctypes_test.__file__) 29 self.assertRaises(ValueError, c_int.in_dll, ctdll, "Undefined_Symbol") 30 31class PythonValuesTestCase(unittest.TestCase): 32 """This test only works when python itself is a dll/shared library""" 33 34 def test_optimizeflag(self): 35 # This test accesses the Py_OptimizeFlag integer, which is 36 # exported by the Python dll and should match the sys.flags value 37 38 opt = c_int.in_dll(pythonapi, "Py_OptimizeFlag").value 39 self.assertEqual(opt, sys.flags.optimize) 40 41 def test_frozentable(self): 42 # Python exports a PyImport_FrozenModules symbol. This is a 43 # pointer to an array of struct _frozen entries. The end of the 44 # array is marked by an entry containing a NULL name and zero 45 # size. 46 47 # In standard Python, this table contains a __hello__ 48 # module, and a __phello__ package containing a spam 49 # module. 50 class struct_frozen(Structure): 51 _fields_ = [("name", c_char_p), 52 ("code", POINTER(c_ubyte)), 53 ("size", c_int)] 54 FrozenTable = POINTER(struct_frozen) 55 56 ft = FrozenTable.in_dll(pythonapi, "PyImport_FrozenModules") 57 # ft is a pointer to the struct_frozen entries: 58 items = [] 59 # _frozen_importlib changes size whenever importlib._bootstrap 60 # changes, so it gets a special case. We should make sure it's 61 # found, but don't worry about its size too much. The same 62 # applies to _frozen_importlib_external. 63 bootstrap_seen = [] 64 bootstrap_expected = [ 65 b'_frozen_importlib', 66 b'_frozen_importlib_external', 67 ] 68 for entry in ft: 69 # This is dangerous. We *can* iterate over a pointer, but 70 # the loop will not terminate (maybe with an access 71 # violation;-) because the pointer instance has no size. 72 if entry.name is None: 73 break 74 75 if entry.name in bootstrap_expected: 76 bootstrap_seen.append(entry.name) 77 self.assertTrue(entry.size, 78 "{!r} was reported as having no size".format(entry.name)) 79 continue 80 items.append((entry.name.decode("ascii"), entry.size)) 81 82 expected = [("__hello__", 139), 83 ("__phello__", -139), 84 ("__phello__.spam", 139), 85 ] 86 self.assertEqual(items, expected, "PyImport_FrozenModules example " 87 "in Doc/library/ctypes.rst may be out of date") 88 89 self.assertEqual(sorted(bootstrap_seen), bootstrap_expected, 90 "frozen bootstrap modules did not match PyImport_FrozenModules") 91 92 from ctypes import _pointer_type_cache 93 del _pointer_type_cache[struct_frozen] 94 95 def test_undefined(self): 96 self.assertRaises(ValueError, c_int.in_dll, pythonapi, 97 "Undefined_Symbol") 98 99if __name__ == '__main__': 100 unittest.main() 101