blob: e83fd9a6fc4dc0314701d5a19d65e28f78ca0df0 [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 def test_subclasses(self):
23 from ctypes import c_void_p, c_char_p
24 # ctypes 0.9.5 and before did overwrite from_param in SimpleType_new
25 class CVOIDP(c_void_p):
26 def from_param(cls, value):
27 return value * 2
28 from_param = classmethod(from_param)
29
30 class CCHARP(c_char_p):
31 def from_param(cls, value):
32 return value * 4
33 from_param = classmethod(from_param)
34
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000035 self.assertEqual(CVOIDP.from_param("abc"), "abcabc")
36 self.assertEqual(CCHARP.from_param("abc"), "abcabcabcabc")
Thomas Hellerbabddfc2006-03-08 19:56:54 +000037
38 try:
39 from ctypes import c_wchar_p
40 except ImportError:
41 return
42
43 class CWCHARP(c_wchar_p):
44 def from_param(cls, value):
45 return value * 3
46 from_param = classmethod(from_param)
47
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000048 self.assertEqual(CWCHARP.from_param("abc"), "abcabcabc")
Thomas Hellerbabddfc2006-03-08 19:56:54 +000049
50 # XXX Replace by c_char_p tests
51 def test_cstrings(self):
52 from ctypes import c_char_p, byref
53
54 # c_char_p.from_param on a Python String packs the string
55 # into a cparam object
Thomas Heller3d79dd92007-07-12 19:33:24 +000056 s = b"123"
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000057 self.assertTrue(c_char_p.from_param(s)._obj is s)
Thomas Hellerbabddfc2006-03-08 19:56:54 +000058
59 # new in 0.9.1: convert (encode) unicode to ascii
Victor Stinnercf448832010-07-28 00:15:03 +000060 self.assertEqual(c_char_p.from_param(b"123")._obj, b"123")
61 self.assertRaises(TypeError, c_char_p.from_param, "123\377")
Thomas Hellerbabddfc2006-03-08 19:56:54 +000062 self.assertRaises(TypeError, c_char_p.from_param, 42)
63
64 # calling c_char_p.from_param with a c_char_p instance
65 # returns the argument itself:
Victor Stinner42746df2010-07-27 23:36:41 +000066 a = c_char_p(b"123")
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000067 self.assertTrue(c_char_p.from_param(a) is a)
Thomas Hellerbabddfc2006-03-08 19:56:54 +000068
69 def test_cw_strings(self):
70 from ctypes import byref
71 try:
72 from ctypes import c_wchar_p
73 except ImportError:
74## print "(No c_wchar_p)"
75 return
Guido van Rossumef87d6e2007-05-02 19:09:54 +000076 s = "123"
Thomas Hellerbabddfc2006-03-08 19:56:54 +000077 if sys.platform == "win32":
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000078 self.assertTrue(c_wchar_p.from_param(s)._obj is s)
Thomas Hellerbabddfc2006-03-08 19:56:54 +000079 self.assertRaises(TypeError, c_wchar_p.from_param, 42)
80
81 # new in 0.9.1: convert (decode) ascii to unicode
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000082 self.assertEqual(c_wchar_p.from_param("123")._obj, "123")
Victor Stinnercf448832010-07-28 00:15:03 +000083 self.assertRaises(TypeError, c_wchar_p.from_param, b"123\377")
Thomas Hellerbabddfc2006-03-08 19:56:54 +000084
Guido van Rossumef87d6e2007-05-02 19:09:54 +000085 pa = c_wchar_p.from_param(c_wchar_p("123"))
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000086 self.assertEqual(type(pa), c_wchar_p)
Thomas Hellerbabddfc2006-03-08 19:56:54 +000087
88 def test_int_pointers(self):
89 from ctypes import c_short, c_uint, c_int, c_long, POINTER, pointer
90 LPINT = POINTER(c_int)
91
92## p = pointer(c_int(42))
93## x = LPINT.from_param(p)
94 x = LPINT.from_param(pointer(c_int(42)))
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000095 self.assertEqual(x.contents.value, 42)
96 self.assertEqual(LPINT(c_int(42)).contents.value, 42)
Thomas Hellerbabddfc2006-03-08 19:56:54 +000097
Thomas Heller69b639f2009-09-18 20:08:39 +000098 self.assertEqual(LPINT.from_param(None), None)
Thomas Hellerbabddfc2006-03-08 19:56:54 +000099
100 if c_int != c_long:
101 self.assertRaises(TypeError, LPINT.from_param, pointer(c_long(42)))
102 self.assertRaises(TypeError, LPINT.from_param, pointer(c_uint(42)))
103 self.assertRaises(TypeError, LPINT.from_param, pointer(c_short(42)))
104
105 def test_byref_pointer(self):
106 # The from_param class method of POINTER(typ) classes accepts what is
107 # returned by byref(obj), it type(obj) == typ
108 from ctypes import c_short, c_uint, c_int, c_long, pointer, POINTER, byref
109 LPINT = POINTER(c_int)
110
111 LPINT.from_param(byref(c_int(42)))
112
113 self.assertRaises(TypeError, LPINT.from_param, byref(c_short(22)))
114 if c_int != c_long:
115 self.assertRaises(TypeError, LPINT.from_param, byref(c_long(22)))
116 self.assertRaises(TypeError, LPINT.from_param, byref(c_uint(22)))
117
118 def test_byref_pointerpointer(self):
119 # See above
120 from ctypes import c_short, c_uint, c_int, c_long, pointer, POINTER, byref
121
122 LPLPINT = POINTER(POINTER(c_int))
123 LPLPINT.from_param(byref(pointer(c_int(42))))
124
125 self.assertRaises(TypeError, LPLPINT.from_param, byref(pointer(c_short(22))))
126 if c_int != c_long:
127 self.assertRaises(TypeError, LPLPINT.from_param, byref(pointer(c_long(22))))
128 self.assertRaises(TypeError, LPLPINT.from_param, byref(pointer(c_uint(22))))
129
130 def test_array_pointers(self):
131 from ctypes import c_short, c_uint, c_int, c_long, POINTER
132 INTARRAY = c_int * 3
133 ia = INTARRAY()
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000134 self.assertEqual(len(ia), 3)
135 self.assertEqual([ia[i] for i in range(3)], [0, 0, 0])
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000136
137 # Pointers are only compatible with arrays containing items of
138 # the same type!
139 LPINT = POINTER(c_int)
140 LPINT.from_param((c_int*3)())
141 self.assertRaises(TypeError, LPINT.from_param, c_short*3)
142 self.assertRaises(TypeError, LPINT.from_param, c_long*3)
143 self.assertRaises(TypeError, LPINT.from_param, c_uint*3)
144
145## def test_performance(self):
146## check_perf()
147
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000148 def test_noctypes_argtype(self):
149 import _ctypes_test
150 from ctypes import CDLL, c_void_p, ArgumentError
151
152 func = CDLL(_ctypes_test.__file__)._testfunc_p_p
153 func.restype = c_void_p
154 # TypeError: has no from_param method
155 self.assertRaises(TypeError, setattr, func, "argtypes", (object,))
156
157 class Adapter(object):
158 def from_param(cls, obj):
159 return None
160
161 func.argtypes = (Adapter(),)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000162 self.assertEqual(func(None), None)
163 self.assertEqual(func(object()), None)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000164
165 class Adapter(object):
166 def from_param(cls, obj):
167 return obj
168
169 func.argtypes = (Adapter(),)
170 # don't know how to convert parameter 1
171 self.assertRaises(ArgumentError, func, object())
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000172 self.assertEqual(func(c_void_p(42)), 42)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000173
174 class Adapter(object):
175 def from_param(cls, obj):
176 raise ValueError(obj)
177
178 func.argtypes = (Adapter(),)
179 # ArgumentError: argument 1: ValueError: 99
180 self.assertRaises(ArgumentError, func, 99)
181
182
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000183################################################################
184
185if __name__ == '__main__':
186 unittest.main()