PageRenderTime 166ms CodeModel.GetById 40ms app.highlight 87ms RepoModel.GetById 34ms app.codeStats 0ms

/Lib/ctypes/test/test_functions.py

http://unladen-swallow.googlecode.com/
Python | 407 lines | 290 code | 81 blank | 36 comment | 4 complexity | 36e42957ebb2b2c3e18897623b40b58d MD5 | raw file
  1"""
  2Here is probably the place to write the docs, since the test-cases
  3show how the type behave.
  4
  5Later...
  6"""
  7
  8from ctypes import *
  9import sys, unittest
 10
 11try:
 12    WINFUNCTYPE
 13except NameError:
 14    # fake to enable this test on Linux
 15    WINFUNCTYPE = CFUNCTYPE
 16
 17import _ctypes_test
 18dll = CDLL(_ctypes_test.__file__)
 19if sys.platform == "win32":
 20    windll = WinDLL(_ctypes_test.__file__)
 21
 22class POINT(Structure):
 23    _fields_ = [("x", c_int), ("y", c_int)]
 24class RECT(Structure):
 25    _fields_ = [("left", c_int), ("top", c_int),
 26                ("right", c_int), ("bottom", c_int)]
 27class FunctionTestCase(unittest.TestCase):
 28
 29    def test_mro(self):
 30        # in Python 2.3, this raises TypeError: MRO conflict among bases classes,
 31        # in Python 2.2 it works.
 32        #
 33        # But in early versions of _ctypes.c, the result of tp_new
 34        # wasn't checked, and it even crashed Python.
 35        # Found by Greg Chapman.
 36
 37        try:
 38            class X(object, Array):
 39                _length_ = 5
 40                _type_ = "i"
 41        except TypeError:
 42            pass
 43
 44
 45        from _ctypes import _Pointer
 46        try:
 47            class X(object, _Pointer):
 48                pass
 49        except TypeError:
 50            pass
 51
 52        from _ctypes import _SimpleCData
 53        try:
 54            class X(object, _SimpleCData):
 55                _type_ = "i"
 56        except TypeError:
 57            pass
 58
 59        try:
 60            class X(object, Structure):
 61                _fields_ = []
 62        except TypeError:
 63            pass
 64
 65
 66    def test_wchar_parm(self):
 67        try:
 68            c_wchar
 69        except NameError:
 70            return
 71        f = dll._testfunc_i_bhilfd
 72        f.argtypes = [c_byte, c_wchar, c_int, c_long, c_float, c_double]
 73        result = f(1, u"x", 3, 4, 5.0, 6.0)
 74        self.failUnlessEqual(result, 139)
 75        self.failUnlessEqual(type(result), int)
 76
 77    def test_wchar_result(self):
 78        try:
 79            c_wchar
 80        except NameError:
 81            return
 82        f = dll._testfunc_i_bhilfd
 83        f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double]
 84        f.restype = c_wchar
 85        result = f(0, 0, 0, 0, 0, 0)
 86        self.failUnlessEqual(result, u'\x00')
 87
 88    def test_voidresult(self):
 89        f = dll._testfunc_v
 90        f.restype = None
 91        f.argtypes = [c_int, c_int, POINTER(c_int)]
 92        result = c_int()
 93        self.failUnlessEqual(None, f(1, 2, byref(result)))
 94        self.failUnlessEqual(result.value, 3)
 95
 96    def test_intresult(self):
 97        f = dll._testfunc_i_bhilfd
 98        f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double]
 99        f.restype = c_int
100        result = f(1, 2, 3, 4, 5.0, 6.0)
101        self.failUnlessEqual(result, 21)
102        self.failUnlessEqual(type(result), int)
103
104        result = f(-1, -2, -3, -4, -5.0, -6.0)
105        self.failUnlessEqual(result, -21)
106        self.failUnlessEqual(type(result), int)
107
108        # If we declare the function to return a short,
109        # is the high part split off?
110        f.restype = c_short
111        result = f(1, 2, 3, 4, 5.0, 6.0)
112        self.failUnlessEqual(result, 21)
113        self.failUnlessEqual(type(result), int)
114
115        result = f(1, 2, 3, 0x10004, 5.0, 6.0)
116        self.failUnlessEqual(result, 21)
117        self.failUnlessEqual(type(result), int)
118
119        # You cannot assing character format codes as restype any longer
120        self.assertRaises(TypeError, setattr, f, "restype", "i")
121
122    def test_floatresult(self):
123        f = dll._testfunc_f_bhilfd
124        f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double]
125        f.restype = c_float
126        result = f(1, 2, 3, 4, 5.0, 6.0)
127        self.failUnlessEqual(result, 21)
128        self.failUnlessEqual(type(result), float)
129
130        result = f(-1, -2, -3, -4, -5.0, -6.0)
131        self.failUnlessEqual(result, -21)
132        self.failUnlessEqual(type(result), float)
133
134    def test_doubleresult(self):
135        f = dll._testfunc_d_bhilfd
136        f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double]
137        f.restype = c_double
138        result = f(1, 2, 3, 4, 5.0, 6.0)
139        self.failUnlessEqual(result, 21)
140        self.failUnlessEqual(type(result), float)
141
142        result = f(-1, -2, -3, -4, -5.0, -6.0)
143        self.failUnlessEqual(result, -21)
144        self.failUnlessEqual(type(result), float)
145
146    def test_longdoubleresult(self):
147        f = dll._testfunc_D_bhilfD
148        f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_longdouble]
149        f.restype = c_longdouble
150        result = f(1, 2, 3, 4, 5.0, 6.0)
151        self.failUnlessEqual(result, 21)
152        self.failUnlessEqual(type(result), float)
153
154        result = f(-1, -2, -3, -4, -5.0, -6.0)
155        self.failUnlessEqual(result, -21)
156        self.failUnlessEqual(type(result), float)
157
158    def test_longlongresult(self):
159        try:
160            c_longlong
161        except NameError:
162            return
163        f = dll._testfunc_q_bhilfd
164        f.restype = c_longlong
165        f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double]
166        result = f(1, 2, 3, 4, 5.0, 6.0)
167        self.failUnlessEqual(result, 21)
168
169        f = dll._testfunc_q_bhilfdq
170        f.restype = c_longlong
171        f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double, c_longlong]
172        result = f(1, 2, 3, 4, 5.0, 6.0, 21)
173        self.failUnlessEqual(result, 42)
174
175    def test_stringresult(self):
176        f = dll._testfunc_p_p
177        f.argtypes = None
178        f.restype = c_char_p
179        result = f("123")
180        self.failUnlessEqual(result, "123")
181
182        result = f(None)
183        self.failUnlessEqual(result, None)
184
185    def test_pointers(self):
186        f = dll._testfunc_p_p
187        f.restype = POINTER(c_int)
188        f.argtypes = [POINTER(c_int)]
189
190        # This only works if the value c_int(42) passed to the
191        # function is still alive while the pointer (the result) is
192        # used.
193
194        v = c_int(42)
195
196        self.failUnlessEqual(pointer(v).contents.value, 42)
197        result = f(pointer(v))
198        self.failUnlessEqual(type(result), POINTER(c_int))
199        self.failUnlessEqual(result.contents.value, 42)
200
201        # This on works...
202        result = f(pointer(v))
203        self.failUnlessEqual(result.contents.value, v.value)
204
205        p = pointer(c_int(99))
206        result = f(p)
207        self.failUnlessEqual(result.contents.value, 99)
208
209        arg = byref(v)
210        result = f(arg)
211        self.failIfEqual(result.contents, v.value)
212
213        self.assertRaises(ArgumentError, f, byref(c_short(22)))
214
215        # It is dangerous, however, because you don't control the lifetime
216        # of the pointer:
217        result = f(byref(c_int(99)))
218        self.failIfEqual(result.contents, 99)
219
220    def test_errors(self):
221        f = dll._testfunc_p_p
222        f.restype = c_int
223
224        class X(Structure):
225            _fields_ = [("y", c_int)]
226
227        self.assertRaises(TypeError, f, X()) #cannot convert parameter
228
229    ################################################################
230    def test_shorts(self):
231        f = dll._testfunc_callback_i_if
232
233        args = []
234        expected = [262144, 131072, 65536, 32768, 16384, 8192, 4096, 2048,
235                    1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1]
236
237        def callback(v):
238            args.append(v)
239            return v
240
241        CallBack = CFUNCTYPE(c_int, c_int)
242
243        cb = CallBack(callback)
244        f(2**18, cb)
245        self.failUnlessEqual(args, expected)
246
247    ################################################################
248
249
250    def test_callbacks(self):
251        f = dll._testfunc_callback_i_if
252        f.restype = c_int
253
254        MyCallback = CFUNCTYPE(c_int, c_int)
255
256        def callback(value):
257            #print "called back with", value
258            return value
259
260        cb = MyCallback(callback)
261        result = f(-10, cb)
262        self.failUnlessEqual(result, -18)
263
264        # test with prototype
265        f.argtypes = [c_int, MyCallback]
266        cb = MyCallback(callback)
267        result = f(-10, cb)
268        self.failUnlessEqual(result, -18)
269
270        AnotherCallback = WINFUNCTYPE(c_int, c_int, c_int, c_int, c_int)
271
272        # check that the prototype works: we call f with wrong
273        # argument types
274        cb = AnotherCallback(callback)
275        self.assertRaises(ArgumentError, f, -10, cb)
276
277
278    def test_callbacks_2(self):
279        # Can also use simple datatypes as argument type specifiers
280        # for the callback function.
281        # In this case the call receives an instance of that type
282        f = dll._testfunc_callback_i_if
283        f.restype = c_int
284
285        MyCallback = CFUNCTYPE(c_int, c_int)
286
287        f.argtypes = [c_int, MyCallback]
288
289        def callback(value):
290            #print "called back with", value
291            self.failUnlessEqual(type(value), int)
292            return value
293
294        cb = MyCallback(callback)
295        result = f(-10, cb)
296        self.failUnlessEqual(result, -18)
297
298    def test_longlong_callbacks(self):
299
300        f = dll._testfunc_callback_q_qf
301        f.restype = c_longlong
302
303        MyCallback = CFUNCTYPE(c_longlong, c_longlong)
304
305        f.argtypes = [c_longlong, MyCallback]
306
307        def callback(value):
308            self.failUnless(isinstance(value, (int, long)))
309            return value & 0x7FFFFFFF
310
311        cb = MyCallback(callback)
312
313        self.failUnlessEqual(13577625587, f(1000000000000, cb))
314
315    def test_errors(self):
316        self.assertRaises(AttributeError, getattr, dll, "_xxx_yyy")
317        self.assertRaises(ValueError, c_int.in_dll, dll, "_xxx_yyy")
318
319    def test_byval(self):
320
321        # without prototype
322        ptin = POINT(1, 2)
323        ptout = POINT()
324        # EXPORT int _testfunc_byval(point in, point *pout)
325        result = dll._testfunc_byval(ptin, byref(ptout))
326        got = result, ptout.x, ptout.y
327        expected = 3, 1, 2
328        self.failUnlessEqual(got, expected)
329
330        # with prototype
331        ptin = POINT(101, 102)
332        ptout = POINT()
333        dll._testfunc_byval.argtypes = (POINT, POINTER(POINT))
334        dll._testfunc_byval.restype = c_int
335        result = dll._testfunc_byval(ptin, byref(ptout))
336        got = result, ptout.x, ptout.y
337        expected = 203, 101, 102
338        self.failUnlessEqual(got, expected)
339
340    def test_struct_return_2H(self):
341        class S2H(Structure):
342            _fields_ = [("x", c_short),
343                        ("y", c_short)]
344        dll.ret_2h_func.restype = S2H
345        dll.ret_2h_func.argtypes = [S2H]
346        inp = S2H(99, 88)
347        s2h = dll.ret_2h_func(inp)
348        self.failUnlessEqual((s2h.x, s2h.y), (99*2, 88*3))
349
350    if sys.platform == "win32":
351        def test_struct_return_2H_stdcall(self):
352            class S2H(Structure):
353                _fields_ = [("x", c_short),
354                            ("y", c_short)]
355
356            windll.s_ret_2h_func.restype = S2H
357            windll.s_ret_2h_func.argtypes = [S2H]
358            s2h = windll.s_ret_2h_func(S2H(99, 88))
359            self.failUnlessEqual((s2h.x, s2h.y), (99*2, 88*3))
360
361    def test_struct_return_8H(self):
362        class S8I(Structure):
363            _fields_ = [("a", c_int),
364                        ("b", c_int),
365                        ("c", c_int),
366                        ("d", c_int),
367                        ("e", c_int),
368                        ("f", c_int),
369                        ("g", c_int),
370                        ("h", c_int)]
371        dll.ret_8i_func.restype = S8I
372        dll.ret_8i_func.argtypes = [S8I]
373        inp = S8I(9, 8, 7, 6, 5, 4, 3, 2)
374        s8i = dll.ret_8i_func(inp)
375        self.failUnlessEqual((s8i.a, s8i.b, s8i.c, s8i.d, s8i.e, s8i.f, s8i.g, s8i.h),
376                             (9*2, 8*3, 7*4, 6*5, 5*6, 4*7, 3*8, 2*9))
377
378    if sys.platform == "win32":
379        def test_struct_return_8H_stdcall(self):
380            class S8I(Structure):
381                _fields_ = [("a", c_int),
382                            ("b", c_int),
383                            ("c", c_int),
384                            ("d", c_int),
385                            ("e", c_int),
386                            ("f", c_int),
387                            ("g", c_int),
388                            ("h", c_int)]
389            windll.s_ret_8i_func.restype = S8I
390            windll.s_ret_8i_func.argtypes = [S8I]
391            inp = S8I(9, 8, 7, 6, 5, 4, 3, 2)
392            s8i = windll.s_ret_8i_func(inp)
393            self.failUnlessEqual((s8i.a, s8i.b, s8i.c, s8i.d, s8i.e, s8i.f, s8i.g, s8i.h),
394                                 (9*2, 8*3, 7*4, 6*5, 5*6, 4*7, 3*8, 2*9))
395
396    def test_sf1651235(self):
397        # see http://www.python.org/sf/1651235
398
399        proto = CFUNCTYPE(c_int, RECT, POINT)
400        def callback(*args):
401            return 0
402
403        callback = proto(callback)
404        self.failUnlessRaises(ArgumentError, lambda: callback((1, 2, 3, 4), POINT()))
405
406if __name__ == '__main__':
407    unittest.main()