• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Windows specific tests
2
3from ctypes import *
4import unittest, sys
5from test import support
6
7import _ctypes_test
8
9@unittest.skipUnless(sys.platform == "win32", 'Windows-specific test')
10class FunctionCallTestCase(unittest.TestCase):
11    @unittest.skipUnless('MSC' in sys.version, "SEH only supported by MSC")
12    @unittest.skipIf(sys.executable.lower().endswith('_d.exe'),
13                     "SEH not enabled in debug builds")
14    def test_SEH(self):
15        # Disable faulthandler to prevent logging the warning:
16        # "Windows fatal exception: access violation"
17        with support.disable_faulthandler():
18            # Call functions with invalid arguments, and make sure
19            # that access violations are trapped and raise an
20            # exception.
21            self.assertRaises(OSError, windll.kernel32.GetModuleHandleA, 32)
22
23    def test_noargs(self):
24        # This is a special case on win32 x64
25        windll.user32.GetDesktopWindow()
26
27
28@unittest.skipUnless(sys.platform == "win32", 'Windows-specific test')
29class ReturnStructSizesTestCase(unittest.TestCase):
30    def test_sizes(self):
31        dll = CDLL(_ctypes_test.__file__)
32        for i in range(1, 11):
33            fields = [ (f"f{f}", c_char) for f in range(1, i + 1)]
34            class S(Structure):
35                _fields_ = fields
36            f = getattr(dll, f"TestSize{i}")
37            f.restype = S
38            res = f()
39            for i, f in enumerate(fields):
40                value = getattr(res, f[0])
41                expected = bytes([ord('a') + i])
42                self.assertEqual(value, expected)
43
44
45
46@unittest.skipUnless(sys.platform == "win32", 'Windows-specific test')
47class TestWintypes(unittest.TestCase):
48    def test_HWND(self):
49        from ctypes import wintypes
50        self.assertEqual(sizeof(wintypes.HWND), sizeof(c_void_p))
51
52    def test_PARAM(self):
53        from ctypes import wintypes
54        self.assertEqual(sizeof(wintypes.WPARAM),
55                             sizeof(c_void_p))
56        self.assertEqual(sizeof(wintypes.LPARAM),
57                             sizeof(c_void_p))
58
59    def test_COMError(self):
60        from _ctypes import COMError
61        if support.HAVE_DOCSTRINGS:
62            self.assertEqual(COMError.__doc__,
63                             "Raised when a COM method call failed.")
64
65        ex = COMError(-1, "text", ("details",))
66        self.assertEqual(ex.hresult, -1)
67        self.assertEqual(ex.text, "text")
68        self.assertEqual(ex.details, ("details",))
69
70@unittest.skipUnless(sys.platform == "win32", 'Windows-specific test')
71class TestWinError(unittest.TestCase):
72    def test_winerror(self):
73        # see Issue 16169
74        import errno
75        ERROR_INVALID_PARAMETER = 87
76        msg = FormatError(ERROR_INVALID_PARAMETER).strip()
77        args = (errno.EINVAL, msg, None, ERROR_INVALID_PARAMETER)
78
79        e = WinError(ERROR_INVALID_PARAMETER)
80        self.assertEqual(e.args, args)
81        self.assertEqual(e.errno, errno.EINVAL)
82        self.assertEqual(e.winerror, ERROR_INVALID_PARAMETER)
83
84        windll.kernel32.SetLastError(ERROR_INVALID_PARAMETER)
85        try:
86            raise WinError()
87        except OSError as exc:
88            e = exc
89        self.assertEqual(e.args, args)
90        self.assertEqual(e.errno, errno.EINVAL)
91        self.assertEqual(e.winerror, ERROR_INVALID_PARAMETER)
92
93class Structures(unittest.TestCase):
94    def test_struct_by_value(self):
95        class POINT(Structure):
96            _fields_ = [("x", c_long),
97                        ("y", c_long)]
98
99        class RECT(Structure):
100            _fields_ = [("left", c_long),
101                        ("top", c_long),
102                        ("right", c_long),
103                        ("bottom", c_long)]
104
105        dll = CDLL(_ctypes_test.__file__)
106
107        pt = POINT(15, 25)
108        left = c_long.in_dll(dll, 'left')
109        top = c_long.in_dll(dll, 'top')
110        right = c_long.in_dll(dll, 'right')
111        bottom = c_long.in_dll(dll, 'bottom')
112        rect = RECT(left, top, right, bottom)
113        PointInRect = dll.PointInRect
114        PointInRect.argtypes = [POINTER(RECT), POINT]
115        self.assertEqual(1, PointInRect(byref(rect), pt))
116
117        ReturnRect = dll.ReturnRect
118        ReturnRect.argtypes = [c_int, RECT, POINTER(RECT), POINT, RECT,
119                               POINTER(RECT), POINT, RECT]
120        ReturnRect.restype = RECT
121        for i in range(4):
122            ret = ReturnRect(i, rect, pointer(rect), pt, rect,
123                         byref(rect), pt, rect)
124            # the c function will check and modify ret if something is
125            # passed in improperly
126            self.assertEqual(ret.left, left.value)
127            self.assertEqual(ret.right, right.value)
128            self.assertEqual(ret.top, top.value)
129            self.assertEqual(ret.bottom, bottom.value)
130
131        # to not leak references, we must clean _pointer_type_cache
132        from ctypes import _pointer_type_cache
133        del _pointer_type_cache[RECT]
134
135if __name__ == '__main__':
136    unittest.main()
137