Home | History | Annotate | Download | only in test
      1 import unittest, sys
      2 
      3 class SimpleTypesTestCase(unittest.TestCase):
      4 
      5     def setUp(self):
      6         import ctypes
      7         try:
      8             from _ctypes import set_conversion_mode
      9         except ImportError:
     10             pass
     11         else:
     12             self.prev_conv_mode = set_conversion_mode("ascii", "strict")
     13 
     14     def tearDown(self):
     15         try:
     16             from _ctypes import set_conversion_mode
     17         except ImportError:
     18             pass
     19         else:
     20             set_conversion_mode(*self.prev_conv_mode)
     21 
     22 
     23     def test_subclasses(self):
     24         from ctypes import c_void_p, c_char_p
     25         # ctypes 0.9.5 and before did overwrite from_param in SimpleType_new
     26         class CVOIDP(c_void_p):
     27             def from_param(cls, value):
     28                 return value * 2
     29             from_param = classmethod(from_param)
     30 
     31         class CCHARP(c_char_p):
     32             def from_param(cls, value):
     33                 return value * 4
     34             from_param = classmethod(from_param)
     35 
     36         self.assertEqual(CVOIDP.from_param("abc"), "abcabc")
     37         self.assertEqual(CCHARP.from_param("abc"), "abcabcabcabc")
     38 
     39         try:
     40             from ctypes import c_wchar_p
     41         except ImportError:
     42             return
     43 
     44         class CWCHARP(c_wchar_p):
     45             def from_param(cls, value):
     46                 return value * 3
     47             from_param = classmethod(from_param)
     48 
     49         self.assertEqual(CWCHARP.from_param("abc"), "abcabcabc")
     50 
     51     # XXX Replace by c_char_p tests
     52     def test_cstrings(self):
     53         from ctypes import c_char_p, byref
     54 
     55         # c_char_p.from_param on a Python String packs the string
     56         # into a cparam object
     57         s = "123"
     58         self.assertTrue(c_char_p.from_param(s)._obj is s)
     59 
     60         # new in 0.9.1: convert (encode) unicode to ascii
     61         self.assertEqual(c_char_p.from_param(u"123")._obj, "123")
     62         self.assertRaises(UnicodeEncodeError, c_char_p.from_param, u"123\377")
     63 
     64         self.assertRaises(TypeError, c_char_p.from_param, 42)
     65 
     66         # calling c_char_p.from_param with a c_char_p instance
     67         # returns the argument itself:
     68         a = c_char_p("123")
     69         self.assertTrue(c_char_p.from_param(a) is a)
     70 
     71     def test_cw_strings(self):
     72         from ctypes import byref
     73         try:
     74             from ctypes import c_wchar_p
     75         except ImportError:
     76 ##            print "(No c_wchar_p)"
     77             return
     78         s = u"123"
     79         if sys.platform == "win32":
     80             self.assertTrue(c_wchar_p.from_param(s)._obj is s)
     81             self.assertRaises(TypeError, c_wchar_p.from_param, 42)
     82 
     83             # new in 0.9.1: convert (decode) ascii to unicode
     84             self.assertEqual(c_wchar_p.from_param("123")._obj, u"123")
     85         self.assertRaises(UnicodeDecodeError, c_wchar_p.from_param, "123\377")
     86 
     87         pa = c_wchar_p.from_param(c_wchar_p(u"123"))
     88         self.assertEqual(type(pa), c_wchar_p)
     89 
     90     def test_int_pointers(self):
     91         from ctypes import c_short, c_uint, c_int, c_long, POINTER, pointer
     92         LPINT = POINTER(c_int)
     93 
     94 ##        p = pointer(c_int(42))
     95 ##        x = LPINT.from_param(p)
     96         x = LPINT.from_param(pointer(c_int(42)))
     97         self.assertEqual(x.contents.value, 42)
     98         self.assertEqual(LPINT(c_int(42)).contents.value, 42)
     99 
    100         self.assertEqual(LPINT.from_param(None), None)
    101 
    102         if c_int != c_long:
    103             self.assertRaises(TypeError, LPINT.from_param, pointer(c_long(42)))
    104         self.assertRaises(TypeError, LPINT.from_param, pointer(c_uint(42)))
    105         self.assertRaises(TypeError, LPINT.from_param, pointer(c_short(42)))
    106 
    107     def test_byref_pointer(self):
    108         # The from_param class method of POINTER(typ) classes accepts what is
    109         # returned by byref(obj), it type(obj) == typ
    110         from ctypes import c_short, c_uint, c_int, c_long, pointer, POINTER, byref
    111         LPINT = POINTER(c_int)
    112 
    113         LPINT.from_param(byref(c_int(42)))
    114 
    115         self.assertRaises(TypeError, LPINT.from_param, byref(c_short(22)))
    116         if c_int != c_long:
    117             self.assertRaises(TypeError, LPINT.from_param, byref(c_long(22)))
    118         self.assertRaises(TypeError, LPINT.from_param, byref(c_uint(22)))
    119 
    120     def test_byref_pointerpointer(self):
    121         # See above
    122         from ctypes import c_short, c_uint, c_int, c_long, pointer, POINTER, byref
    123 
    124         LPLPINT = POINTER(POINTER(c_int))
    125         LPLPINT.from_param(byref(pointer(c_int(42))))
    126 
    127         self.assertRaises(TypeError, LPLPINT.from_param, byref(pointer(c_short(22))))
    128         if c_int != c_long:
    129             self.assertRaises(TypeError, LPLPINT.from_param, byref(pointer(c_long(22))))
    130         self.assertRaises(TypeError, LPLPINT.from_param, byref(pointer(c_uint(22))))
    131 
    132     def test_array_pointers(self):
    133         from ctypes import c_short, c_uint, c_int, c_long, POINTER
    134         INTARRAY = c_int * 3
    135         ia = INTARRAY()
    136         self.assertEqual(len(ia), 3)
    137         self.assertEqual([ia[i] for i in range(3)], [0, 0, 0])
    138 
    139         # Pointers are only compatible with arrays containing items of
    140         # the same type!
    141         LPINT = POINTER(c_int)
    142         LPINT.from_param((c_int*3)())
    143         self.assertRaises(TypeError, LPINT.from_param, c_short*3)
    144         self.assertRaises(TypeError, LPINT.from_param, c_long*3)
    145         self.assertRaises(TypeError, LPINT.from_param, c_uint*3)
    146 
    147 ##    def test_performance(self):
    148 ##        check_perf()
    149 
    150     def test_noctypes_argtype(self):
    151         import _ctypes_test
    152         from ctypes import CDLL, c_void_p, ArgumentError
    153 
    154         func = CDLL(_ctypes_test.__file__)._testfunc_p_p
    155         func.restype = c_void_p
    156         # TypeError: has no from_param method
    157         self.assertRaises(TypeError, setattr, func, "argtypes", (object,))
    158 
    159         class Adapter(object):
    160             def from_param(cls, obj):
    161                 return None
    162 
    163         func.argtypes = (Adapter(),)
    164         self.assertEqual(func(None), None)
    165         self.assertEqual(func(object()), None)
    166 
    167         class Adapter(object):
    168             def from_param(cls, obj):
    169                 return obj
    170 
    171         func.argtypes = (Adapter(),)
    172         # don't know how to convert parameter 1
    173         self.assertRaises(ArgumentError, func, object())
    174         self.assertEqual(func(c_void_p(42)), 42)
    175 
    176         class Adapter(object):
    177             def from_param(cls, obj):
    178                 raise ValueError(obj)
    179 
    180         func.argtypes = (Adapter(),)
    181         # ArgumentError: argument 1: ValueError: 99
    182         self.assertRaises(ArgumentError, func, 99)
    183 
    184 
    185 ################################################################
    186 
    187 if __name__ == '__main__':
    188     unittest.main()
    189