blob: 1c217c3ed08ea4a8a652bede55ed82ddc917a80f [file] [log] [blame]
Dan Albert287553d2017-02-16 10:47:51 -08001from ctypes import *
2import unittest, sys
3
4def callback_func(arg):
5 42 // arg
6 raise ValueError(arg)
7
8if sys.platform == "win32":
9
10 class call_function_TestCase(unittest.TestCase):
11 # _ctypes.call_function is deprecated and private, but used by
12 # Gary Bishp's readline module. If we have it, we must test it as well.
13
14 def test(self):
15 from _ctypes import call_function
16 windll.kernel32.LoadLibraryA.restype = c_void_p
17 windll.kernel32.GetProcAddress.argtypes = c_void_p, c_char_p
18 windll.kernel32.GetProcAddress.restype = c_void_p
19
20 hdll = windll.kernel32.LoadLibraryA("kernel32")
21 funcaddr = windll.kernel32.GetProcAddress(hdll, "GetModuleHandleA")
22
23 self.assertEqual(call_function(funcaddr, (None,)),
24 windll.kernel32.GetModuleHandleA(None))
25
26class CallbackTracbackTestCase(unittest.TestCase):
27 # When an exception is raised in a ctypes callback function, the C
28 # code prints a traceback.
29 #
30 # This test makes sure the exception types *and* the exception
31 # value is printed correctly.
32 #
33 # Changed in 0.9.3: No longer is '(in callback)' prepended to the
34 # error message - instead a additional frame for the C code is
35 # created, then a full traceback printed. When SystemExit is
36 # raised in a callback function, the interpreter exits.
37
38 def capture_stderr(self, func, *args, **kw):
39 # helper - call function 'func', and return the captured stderr
40 import StringIO
41 old_stderr = sys.stderr
42 logger = sys.stderr = StringIO.StringIO()
43 try:
44 func(*args, **kw)
45 finally:
46 sys.stderr = old_stderr
47 return logger.getvalue()
48
49 def test_ValueError(self):
50 cb = CFUNCTYPE(c_int, c_int)(callback_func)
51 out = self.capture_stderr(cb, 42)
52 self.assertEqual(out.splitlines()[-1],
53 "ValueError: 42")
54
55 def test_IntegerDivisionError(self):
56 cb = CFUNCTYPE(c_int, c_int)(callback_func)
57 out = self.capture_stderr(cb, 0)
58 self.assertEqual(out.splitlines()[-1][:19],
59 "ZeroDivisionError: ")
60
61 def test_FloatDivisionError(self):
62 cb = CFUNCTYPE(c_int, c_double)(callback_func)
63 out = self.capture_stderr(cb, 0.0)
64 self.assertEqual(out.splitlines()[-1][:19],
65 "ZeroDivisionError: ")
66
67 def test_TypeErrorDivisionError(self):
68 cb = CFUNCTYPE(c_int, c_char_p)(callback_func)
69 out = self.capture_stderr(cb, "spam")
70 self.assertEqual(out.splitlines()[-1],
71 "TypeError: "
72 "unsupported operand type(s) for //: 'int' and 'str'")
73
74if __name__ == '__main__':
75 unittest.main()