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        ctdll = CDLL(_ctypes_test.__file__)
15        an_integer = c_int.in_dll(ctdll, "an_integer")
16        x = an_integer.value
17        self.assertEqual(x, ctdll.get_an_integer())
18        an_integer.value *= 2
19        self.assertEqual(x*2, ctdll.get_an_integer())
20
21    def test_undefined(self):
22        ctdll = CDLL(_ctypes_test.__file__)
23        self.assertRaises(ValueError, c_int.in_dll, ctdll, "Undefined_Symbol")
24
25class PythonValuesTestCase(unittest.TestCase):
26    """This test only works when python itself is a dll/shared library"""
27
28    def test_optimizeflag(self):
29        # This test accesses the Py_OptimizeFlag intger, which is
30        # exported by the Python dll.
31
32        # It's value is set depending on the -O and -OO flags:
33        # if not given, it is 0 and __debug__ is 1.
34        # If -O is given, the flag is 1, for -OO it is 2.
35        # docstrings are also removed in the latter case.
36        opt = c_int.in_dll(pythonapi, "Py_OptimizeFlag").value
37        if __debug__:
38            self.assertEqual(opt, 0)
39        elif ValuesTestCase.__doc__ is not None:
40            self.assertEqual(opt, 1)
41        else:
42            self.assertEqual(opt, 2)
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        FrozenTable = POINTER(struct_frozen)
58
59        ft = FrozenTable.in_dll(pythonapi, "PyImport_FrozenModules")
60        # ft is a pointer to the struct_frozen entries:
61        items = []
62        for entry in ft:
63            # This is dangerous. We *can* iterate over a pointer, but
64            # the loop will not terminate (maybe with an access
65            # violation;-) because the pointer instance has no size.
66            if entry.name is None:
67                break
68            items.append((entry.name, entry.size))
69
70        expected = [("__hello__", 104),
71                    ("__phello__", -104),
72                    ("__phello__.spam", 104)]
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, pythonapi,
80                          "Undefined_Symbol")
81
82if __name__ == '__main__':
83    unittest.main()
84