1 from ctypes import * 2 import unittest, sys 3 4 def callback_func(arg): 5 42 // arg 6 raise ValueError(arg) 7 8 if 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 26 class 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 74 if __name__ == '__main__': 75 unittest.main() 76