Home | History | Annotate | Download | only in test
      1 import unittest, sys
      2 
      3 from ctypes import *
      4 import _ctypes_test
      5 
      6 ctype_types = [c_byte, c_ubyte, c_short, c_ushort, c_int, c_uint,
      7                  c_long, c_ulong, c_longlong, c_ulonglong, c_double, c_float]
      8 python_types = [int, int, int, int, int, long,
      9                 int, long, long, long, float, float]
     10 
     11 class PointersTestCase(unittest.TestCase):
     12 
     13     def test_pointer_crash(self):
     14 
     15         class A(POINTER(c_ulong)):
     16             pass
     17 
     18         POINTER(c_ulong)(c_ulong(22))
     19         # Pointer can't set contents: has no _type_
     20         self.assertRaises(TypeError, A, c_ulong(33))
     21 
     22     def test_pass_pointers(self):
     23         dll = CDLL(_ctypes_test.__file__)
     24         func = dll._testfunc_p_p
     25         func.restype = c_long
     26 
     27         i = c_int(12345678)
     28 ##        func.argtypes = (POINTER(c_int),)
     29         address = func(byref(i))
     30         self.assertEqual(c_int.from_address(address).value, 12345678)
     31 
     32         func.restype = POINTER(c_int)
     33         res = func(pointer(i))
     34         self.assertEqual(res.contents.value, 12345678)
     35         self.assertEqual(res[0], 12345678)
     36 
     37     def test_change_pointers(self):
     38         dll = CDLL(_ctypes_test.__file__)
     39         func = dll._testfunc_p_p
     40 
     41         i = c_int(87654)
     42         func.restype = POINTER(c_int)
     43         func.argtypes = (POINTER(c_int),)
     44 
     45         res = func(pointer(i))
     46         self.assertEqual(res[0], 87654)
     47         self.assertEqual(res.contents.value, 87654)
     48 
     49         # C code: *res = 54345
     50         res[0] = 54345
     51         self.assertEqual(i.value, 54345)
     52 
     53         # C code:
     54         #   int x = 12321;
     55         #   res = &x
     56         x = c_int(12321)
     57         res.contents = x
     58         self.assertEqual(i.value, 54345)
     59 
     60         x.value = -99
     61         self.assertEqual(res.contents.value, -99)
     62 
     63     def test_callbacks_with_pointers(self):
     64         # a function type receiving a pointer
     65         PROTOTYPE = CFUNCTYPE(c_int, POINTER(c_int))
     66 
     67         self.result = []
     68 
     69         def func(arg):
     70             for i in range(10):
     71 ##                print arg[i],
     72                 self.result.append(arg[i])
     73 ##            print
     74             return 0
     75         callback = PROTOTYPE(func)
     76 
     77         dll = CDLL(_ctypes_test.__file__)
     78         # This function expects a function pointer,
     79         # and calls this with an integer pointer as parameter.
     80         # The int pointer points to a table containing the numbers 1..10
     81         doit = dll._testfunc_callback_with_pointer
     82 
     83 ##        i = c_int(42)
     84 ##        callback(byref(i))
     85 ##        self.assertEqual(i.value, 84)
     86 
     87         doit(callback)
     88 ##        print self.result
     89         doit(callback)
     90 ##        print self.result
     91 
     92     def test_basics(self):
     93         from operator import delitem
     94         for ct, pt in zip(ctype_types, python_types):
     95             i = ct(42)
     96             p = pointer(i)
     97 ##            print type(p.contents), ct
     98             self.assertIs(type(p.contents), ct)
     99             # p.contents is the same as p[0]
    100 ##            print p.contents
    101 ##            self.assertEqual(p.contents, 42)
    102 ##            self.assertEqual(p[0], 42)
    103 
    104             self.assertRaises(TypeError, delitem, p, 0)
    105 
    106     def test_from_address(self):
    107         from array import array
    108         a = array('i', [100, 200, 300, 400, 500])
    109         addr = a.buffer_info()[0]
    110 
    111         p = POINTER(POINTER(c_int))
    112 ##        print dir(p)
    113 ##        print p.from_address
    114 ##        print p.from_address(addr)[0][0]
    115 
    116     def test_other(self):
    117         class Table(Structure):
    118             _fields_ = [("a", c_int),
    119                         ("b", c_int),
    120                         ("c", c_int)]
    121 
    122         pt = pointer(Table(1, 2, 3))
    123 
    124         self.assertEqual(pt.contents.a, 1)
    125         self.assertEqual(pt.contents.b, 2)
    126         self.assertEqual(pt.contents.c, 3)
    127 
    128         pt.contents.c = 33
    129 
    130         from ctypes import _pointer_type_cache
    131         del _pointer_type_cache[Table]
    132 
    133     def test_basic(self):
    134         p = pointer(c_int(42))
    135         # Although a pointer can be indexed, it has no length
    136         self.assertRaises(TypeError, len, p)
    137         self.assertEqual(p[0], 42)
    138         self.assertEqual(p[0:1], [42])
    139         self.assertEqual(p.contents.value, 42)
    140 
    141     def test_charpp(self):
    142         """Test that a character pointer-to-pointer is correctly passed"""
    143         dll = CDLL(_ctypes_test.__file__)
    144         func = dll._testfunc_c_p_p
    145         func.restype = c_char_p
    146         argv = (c_char_p * 2)()
    147         argc = c_int( 2 )
    148         argv[0] = 'hello'
    149         argv[1] = 'world'
    150         result = func( byref(argc), argv )
    151         assert result == 'world', result
    152 
    153     def test_bug_1467852(self):
    154         # http://sourceforge.net/tracker/?func=detail&atid=532154&aid=1467852&group_id=71702
    155         x = c_int(5)
    156         dummy = []
    157         for i in range(32000):
    158             dummy.append(c_int(i))
    159         y = c_int(6)
    160         p = pointer(x)
    161         pp = pointer(p)
    162         q = pointer(y)
    163         pp[0] = q         # <==
    164         self.assertEqual(p[0], 6)
    165     def test_c_void_p(self):
    166         # http://sourceforge.net/tracker/?func=detail&aid=1518190&group_id=5470&atid=105470
    167         if sizeof(c_void_p) == 4:
    168             self.assertEqual(c_void_p(0xFFFFFFFFL).value,
    169                                  c_void_p(-1).value)
    170             self.assertEqual(c_void_p(0xFFFFFFFFFFFFFFFFL).value,
    171                                  c_void_p(-1).value)
    172         elif sizeof(c_void_p) == 8:
    173             self.assertEqual(c_void_p(0xFFFFFFFFL).value,
    174                                  0xFFFFFFFFL)
    175             self.assertEqual(c_void_p(0xFFFFFFFFFFFFFFFFL).value,
    176                                  c_void_p(-1).value)
    177             self.assertEqual(c_void_p(0xFFFFFFFFFFFFFFFFFFFFFFFFL).value,
    178                                  c_void_p(-1).value)
    179 
    180         self.assertRaises(TypeError, c_void_p, 3.14) # make sure floats are NOT accepted
    181         self.assertRaises(TypeError, c_void_p, object()) # nor other objects
    182 
    183     def test_pointers_bool(self):
    184         # NULL pointers have a boolean False value, non-NULL pointers True.
    185         self.assertEqual(bool(POINTER(c_int)()), False)
    186         self.assertEqual(bool(pointer(c_int())), True)
    187 
    188         self.assertEqual(bool(CFUNCTYPE(None)(0)), False)
    189         self.assertEqual(bool(CFUNCTYPE(None)(42)), True)
    190 
    191         # COM methods are boolean True:
    192         if sys.platform == "win32":
    193             mth = WINFUNCTYPE(None)(42, "name", (), None)
    194             self.assertEqual(bool(mth), True)
    195 
    196     def test_pointer_type_name(self):
    197         LargeNamedType = type('T' * 2 ** 25, (Structure,), {})
    198         self.assertTrue(POINTER(LargeNamedType))
    199 
    200         # to not leak references, we must clean _pointer_type_cache
    201         from ctypes import _pointer_type_cache
    202         del _pointer_type_cache[LargeNamedType]
    203 
    204     def test_pointer_type_str_name(self):
    205         large_string = 'T' * 2 ** 25
    206         P = POINTER(large_string)
    207         self.assertTrue(P)
    208 
    209         # to not leak references, we must clean _pointer_type_cache
    210         from ctypes import _pointer_type_cache
    211         del _pointer_type_cache[id(P)]
    212 
    213 
    214 if __name__ == '__main__':
    215     unittest.main()
    216