Dan Albert | 287553d | 2017-02-16 10:47:51 -0800 | [diff] [blame] | 1 | """ |
| 2 | A testcase which accesses *values* in a dll. |
| 3 | """ |
| 4 | |
| 5 | import unittest |
| 6 | from ctypes import * |
| 7 | |
| 8 | import _ctypes_test |
| 9 | |
| 10 | class ValuesTestCase(unittest.TestCase): |
| 11 | |
| 12 | def test_an_integer(self): |
| 13 | ctdll = CDLL(_ctypes_test.__file__) |
| 14 | an_integer = c_int.in_dll(ctdll, "an_integer") |
| 15 | x = an_integer.value |
| 16 | self.assertEqual(x, ctdll.get_an_integer()) |
| 17 | an_integer.value *= 2 |
| 18 | self.assertEqual(x*2, ctdll.get_an_integer()) |
| 19 | |
| 20 | def test_undefined(self): |
| 21 | ctdll = CDLL(_ctypes_test.__file__) |
| 22 | self.assertRaises(ValueError, c_int.in_dll, ctdll, "Undefined_Symbol") |
| 23 | |
| 24 | class Win_ValuesTestCase(unittest.TestCase): |
| 25 | """This test only works when python itself is a dll/shared library""" |
| 26 | |
| 27 | def test_optimizeflag(self): |
| 28 | # This test accesses the Py_OptimizeFlag intger, which is |
| 29 | # exported by the Python dll. |
| 30 | |
| 31 | # It's value is set depending on the -O and -OO flags: |
| 32 | # if not given, it is 0 and __debug__ is 1. |
| 33 | # If -O is given, the flag is 1, for -OO it is 2. |
| 34 | # docstrings are also removed in the latter case. |
| 35 | opt = c_int.in_dll(pydll, "Py_OptimizeFlag").value |
| 36 | if __debug__: |
| 37 | self.assertEqual(opt, 0) |
| 38 | elif ValuesTestCase.__doc__ is not None: |
| 39 | self.assertEqual(opt, 1) |
| 40 | else: |
| 41 | self.assertEqual(opt, 2) |
| 42 | |
| 43 | def test_frozentable(self): |
| 44 | # Python exports a PyImport_FrozenModules symbol. This is a |
| 45 | # pointer to an array of struct _frozen entries. The end of the |
| 46 | # array is marked by an entry containing a NULL name and zero |
| 47 | # size. |
| 48 | |
| 49 | # In standard Python, this table contains a __hello__ |
| 50 | # module, and a __phello__ package containing a spam |
| 51 | # module. |
| 52 | class struct_frozen(Structure): |
| 53 | _fields_ = [("name", c_char_p), |
| 54 | ("code", POINTER(c_ubyte)), |
| 55 | ("size", c_int)] |
| 56 | FrozenTable = POINTER(struct_frozen) |
| 57 | |
| 58 | ft = FrozenTable.in_dll(pydll, "PyImport_FrozenModules") |
| 59 | # ft is a pointer to the struct_frozen entries: |
| 60 | items = [] |
| 61 | for entry in ft: |
| 62 | # This is dangerous. We *can* iterate over a pointer, but |
| 63 | # the loop will not terminate (maybe with an access |
| 64 | # violation;-) because the pointer instance has no size. |
| 65 | if entry.name is None: |
| 66 | break |
| 67 | items.append((entry.name, entry.size)) |
| 68 | import sys |
| 69 | if sys.version_info[:2] >= (2, 3): |
| 70 | expected = [("__hello__", 104), ("__phello__", -104), ("__phello__.spam", 104)] |
| 71 | else: |
| 72 | expected = [("__hello__", 100), ("__phello__", -100), ("__phello__.spam", 100)] |
| 73 | self.assertEqual(items, expected) |
| 74 | |
| 75 | from ctypes import _pointer_type_cache |
| 76 | del _pointer_type_cache[struct_frozen] |
| 77 | |
| 78 | def test_undefined(self): |
| 79 | self.assertRaises(ValueError, c_int.in_dll, pydll, "Undefined_Symbol") |
| 80 | |
| 81 | if __name__ == '__main__': |
| 82 | unittest.main() |