You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
166 lines
6.0 KiB
166 lines
6.0 KiB
5 years ago
|
# Windows specific tests
|
||
|
|
||
|
from ctypes import *
|
||
|
import unittest, sys
|
||
|
from test import support
|
||
|
|
||
|
import _ctypes_test
|
||
|
|
||
|
# Only windows 32-bit has different calling conventions.
|
||
|
@unittest.skipUnless(sys.platform == "win32", 'Windows-specific test')
|
||
|
@unittest.skipUnless(sizeof(c_void_p) == sizeof(c_int),
|
||
|
"sizeof c_void_p and c_int differ")
|
||
|
class WindowsTestCase(unittest.TestCase):
|
||
|
def test_callconv_1(self):
|
||
|
# Testing stdcall function
|
||
|
|
||
|
IsWindow = windll.user32.IsWindow
|
||
|
# ValueError: Procedure probably called with not enough arguments
|
||
|
# (4 bytes missing)
|
||
|
self.assertRaises(ValueError, IsWindow)
|
||
|
|
||
|
# This one should succeed...
|
||
|
self.assertEqual(0, IsWindow(0))
|
||
|
|
||
|
# ValueError: Procedure probably called with too many arguments
|
||
|
# (8 bytes in excess)
|
||
|
self.assertRaises(ValueError, IsWindow, 0, 0, 0)
|
||
|
|
||
|
def test_callconv_2(self):
|
||
|
# Calling stdcall function as cdecl
|
||
|
|
||
|
IsWindow = cdll.user32.IsWindow
|
||
|
|
||
|
# ValueError: Procedure called with not enough arguments
|
||
|
# (4 bytes missing) or wrong calling convention
|
||
|
self.assertRaises(ValueError, IsWindow, None)
|
||
|
|
||
|
@unittest.skipUnless(sys.platform == "win32", 'Windows-specific test')
|
||
|
class FunctionCallTestCase(unittest.TestCase):
|
||
|
@unittest.skipUnless('MSC' in sys.version, "SEH only supported by MSC")
|
||
|
@unittest.skipIf(sys.executable.lower().endswith('_d.exe'),
|
||
|
"SEH not enabled in debug builds")
|
||
|
def test_SEH(self):
|
||
|
# Disable faulthandler to prevent logging the warning:
|
||
|
# "Windows fatal exception: access violation"
|
||
|
with support.disable_faulthandler():
|
||
|
# Call functions with invalid arguments, and make sure
|
||
|
# that access violations are trapped and raise an
|
||
|
# exception.
|
||
|
self.assertRaises(OSError, windll.kernel32.GetModuleHandleA, 32)
|
||
|
|
||
|
def test_noargs(self):
|
||
|
# This is a special case on win32 x64
|
||
|
windll.user32.GetDesktopWindow()
|
||
|
|
||
|
|
||
|
@unittest.skipUnless(sys.platform == "win32", 'Windows-specific test')
|
||
|
class ReturnStructSizesTestCase(unittest.TestCase):
|
||
|
def test_sizes(self):
|
||
|
dll = CDLL(_ctypes_test.__file__)
|
||
|
for i in range(1, 11):
|
||
|
fields = [ (f"f{f}", c_char) for f in range(1, i + 1)]
|
||
|
class S(Structure):
|
||
|
_fields_ = fields
|
||
|
f = getattr(dll, f"TestSize{i}")
|
||
|
f.restype = S
|
||
|
res = f()
|
||
|
for i, f in enumerate(fields):
|
||
|
value = getattr(res, f[0])
|
||
|
expected = bytes([ord('a') + i])
|
||
|
self.assertEqual(value, expected)
|
||
|
|
||
|
|
||
|
|
||
|
@unittest.skipUnless(sys.platform == "win32", 'Windows-specific test')
|
||
|
class TestWintypes(unittest.TestCase):
|
||
|
def test_HWND(self):
|
||
|
from ctypes import wintypes
|
||
|
self.assertEqual(sizeof(wintypes.HWND), sizeof(c_void_p))
|
||
|
|
||
|
def test_PARAM(self):
|
||
|
from ctypes import wintypes
|
||
|
self.assertEqual(sizeof(wintypes.WPARAM),
|
||
|
sizeof(c_void_p))
|
||
|
self.assertEqual(sizeof(wintypes.LPARAM),
|
||
|
sizeof(c_void_p))
|
||
|
|
||
|
def test_COMError(self):
|
||
|
from _ctypes import COMError
|
||
|
if support.HAVE_DOCSTRINGS:
|
||
|
self.assertEqual(COMError.__doc__,
|
||
|
"Raised when a COM method call failed.")
|
||
|
|
||
|
ex = COMError(-1, "text", ("details",))
|
||
|
self.assertEqual(ex.hresult, -1)
|
||
|
self.assertEqual(ex.text, "text")
|
||
|
self.assertEqual(ex.details, ("details",))
|
||
|
|
||
|
@unittest.skipUnless(sys.platform == "win32", 'Windows-specific test')
|
||
|
class TestWinError(unittest.TestCase):
|
||
|
def test_winerror(self):
|
||
|
# see Issue 16169
|
||
|
import errno
|
||
|
ERROR_INVALID_PARAMETER = 87
|
||
|
msg = FormatError(ERROR_INVALID_PARAMETER).strip()
|
||
|
args = (errno.EINVAL, msg, None, ERROR_INVALID_PARAMETER)
|
||
|
|
||
|
e = WinError(ERROR_INVALID_PARAMETER)
|
||
|
self.assertEqual(e.args, args)
|
||
|
self.assertEqual(e.errno, errno.EINVAL)
|
||
|
self.assertEqual(e.winerror, ERROR_INVALID_PARAMETER)
|
||
|
|
||
|
windll.kernel32.SetLastError(ERROR_INVALID_PARAMETER)
|
||
|
try:
|
||
|
raise WinError()
|
||
|
except OSError as exc:
|
||
|
e = exc
|
||
|
self.assertEqual(e.args, args)
|
||
|
self.assertEqual(e.errno, errno.EINVAL)
|
||
|
self.assertEqual(e.winerror, ERROR_INVALID_PARAMETER)
|
||
|
|
||
|
class Structures(unittest.TestCase):
|
||
|
def test_struct_by_value(self):
|
||
|
class POINT(Structure):
|
||
|
_fields_ = [("x", c_long),
|
||
|
("y", c_long)]
|
||
|
|
||
|
class RECT(Structure):
|
||
|
_fields_ = [("left", c_long),
|
||
|
("top", c_long),
|
||
|
("right", c_long),
|
||
|
("bottom", c_long)]
|
||
|
|
||
|
dll = CDLL(_ctypes_test.__file__)
|
||
|
|
||
|
pt = POINT(15, 25)
|
||
|
left = c_long.in_dll(dll, 'left')
|
||
|
top = c_long.in_dll(dll, 'top')
|
||
|
right = c_long.in_dll(dll, 'right')
|
||
|
bottom = c_long.in_dll(dll, 'bottom')
|
||
|
rect = RECT(left, top, right, bottom)
|
||
|
PointInRect = dll.PointInRect
|
||
|
PointInRect.argtypes = [POINTER(RECT), POINT]
|
||
|
self.assertEqual(1, PointInRect(byref(rect), pt))
|
||
|
|
||
|
ReturnRect = dll.ReturnRect
|
||
|
ReturnRect.argtypes = [c_int, RECT, POINTER(RECT), POINT, RECT,
|
||
|
POINTER(RECT), POINT, RECT]
|
||
|
ReturnRect.restype = RECT
|
||
|
for i in range(4):
|
||
|
ret = ReturnRect(i, rect, pointer(rect), pt, rect,
|
||
|
byref(rect), pt, rect)
|
||
|
# the c function will check and modify ret if something is
|
||
|
# passed in improperly
|
||
|
self.assertEqual(ret.left, left.value)
|
||
|
self.assertEqual(ret.right, right.value)
|
||
|
self.assertEqual(ret.top, top.value)
|
||
|
self.assertEqual(ret.bottom, bottom.value)
|
||
|
|
||
|
# to not leak references, we must clean _pointer_type_cache
|
||
|
from ctypes import _pointer_type_cache
|
||
|
del _pointer_type_cache[RECT]
|
||
|
|
||
|
if __name__ == '__main__':
|
||
|
unittest.main()
|