blob: 4c80bdfb73ec60938d9f379e96929b5d61672e04 [file] [log] [blame]
Thomas Hellerbabddfc2006-03-08 19:56:54 +00001import unittest, sys
2
3class 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)
Tim Peterse8d09e52006-03-09 01:15:05 +000021
Thomas Hellerbabddfc2006-03-08 19:56:54 +000022
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.failUnlessEqual(CVOIDP.from_param("abc"), "abcabc")
37 self.failUnlessEqual(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.failUnlessEqual(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
Thomas Heller3d79dd92007-07-12 19:33:24 +000057 s = b"123"
Thomas Hellerbabddfc2006-03-08 19:56:54 +000058 self.failUnless(c_char_p.from_param(s)._obj is s)
59
60 # new in 0.9.1: convert (encode) unicode to ascii
Thomas Heller3d79dd92007-07-12 19:33:24 +000061 self.failUnlessEqual(c_char_p.from_param("123")._obj, b"123")
Guido van Rossumef87d6e2007-05-02 19:09:54 +000062 self.assertRaises(UnicodeEncodeError, c_char_p.from_param, "123\377")
Thomas Hellerbabddfc2006-03-08 19:56:54 +000063
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.failUnless(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
Guido van Rossumef87d6e2007-05-02 19:09:54 +000078 s = "123"
Thomas Hellerbabddfc2006-03-08 19:56:54 +000079 if sys.platform == "win32":
80 self.failUnless(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
Guido van Rossumef87d6e2007-05-02 19:09:54 +000084 self.failUnlessEqual(c_wchar_p.from_param("123")._obj, "123")
Thomas Heller3d79dd92007-07-12 19:33:24 +000085 self.assertRaises(UnicodeDecodeError, c_wchar_p.from_param, b"123\377")
Thomas Hellerbabddfc2006-03-08 19:56:54 +000086
Guido van Rossumef87d6e2007-05-02 19:09:54 +000087 pa = c_wchar_p.from_param(c_wchar_p("123"))
Thomas Hellerbabddfc2006-03-08 19:56:54 +000088 self.failUnlessEqual(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.failUnlessEqual(x.contents.value, 42)
98 self.failUnlessEqual(LPINT(c_int(42)).contents.value, 42)
99
100 self.failUnlessEqual(LPINT.from_param(None), 0)
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.failUnlessEqual(len(ia), 3)
137 self.failUnlessEqual([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
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000150 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.failUnlessEqual(func(None), None)
165 self.failUnlessEqual(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.failUnlessEqual(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
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000185################################################################
186
187if __name__ == '__main__':
188 unittest.main()