5 def valid_ranges(*types):
6 # given a sequence of numeric types, collect their _type_
7 # attribute, which is a single format character compatible with
8 # the struct module, use the struct module to calculate the
9 # minimum and maximum value allowed for this format.
10 # Returns a list of (min, max) values.
14 size = struct.calcsize(fmt)
15 a = struct.unpack(fmt, ("\x00"*32)[:size])[0]
16 b = struct.unpack(fmt, ("\xFF"*32)[:size])[0]
17 c = struct.unpack(fmt, ("\x7F"+"\x00"*32)[:size])[0]
18 d = struct.unpack(fmt, ("\x80"+"\xFF"*32)[:size])[0]
19 result.append((min(a, b, c, d), max(a, b, c, d)))
22 ArgType = type(byref(c_int(0)))
24 unsigned_types = [c_ubyte, c_ushort, c_uint, c_ulong]
25 signed_types = [c_byte, c_short, c_int, c_long, c_longlong]
29 float_types = [c_double, c_float]
37 unsigned_types.append(c_ulonglong)
38 signed_types.append(c_longlong)
45 bool_types.append(c_bool)
47 unsigned_ranges = valid_ranges(*unsigned_types)
48 signed_ranges = valid_ranges(*signed_types)
49 bool_values = [True, False, 0, 1, -1, 5000, 'test', [], [1]]
51 ################################################################
53 class NumberTestCase(unittest.TestCase):
55 def test_default_init(self):
56 # default values are set to zero
57 for t in signed_types + unsigned_types + float_types:
58 self.failUnlessEqual(t().value, 0)
60 def test_unsigned_values(self):
61 # the value given to the constructor is available
62 # as the 'value' attribute
63 for t, (l, h) in zip(unsigned_types, unsigned_ranges):
64 self.failUnlessEqual(t(l).value, l)
65 self.failUnlessEqual(t(h).value, h)
67 def test_signed_values(self):
69 for t, (l, h) in zip(signed_types, signed_ranges):
70 self.failUnlessEqual(t(l).value, l)
71 self.failUnlessEqual(t(h).value, h)
73 def test_bool_values(self):
74 from operator import truth
75 for t, v in zip(bool_types, bool_values):
76 self.failUnlessEqual(t(v).value, truth(v))
78 def test_typeerror(self):
79 # Only numbers are allowed in the contructor,
80 # otherwise TypeError is raised
81 for t in signed_types + unsigned_types + float_types:
82 self.assertRaises(TypeError, t, "")
83 self.assertRaises(TypeError, t, None)
85 ## def test_valid_ranges(self):
86 ## # invalid values of the correct type
87 ## # raise ValueError (not OverflowError)
88 ## for t, (l, h) in zip(unsigned_types, unsigned_ranges):
89 ## self.assertRaises(ValueError, t, l-1)
90 ## self.assertRaises(ValueError, t, h+1)
92 def test_from_param(self):
93 # the from_param class method attribute always
94 # returns PyCArgObject instances
95 for t in signed_types + unsigned_types + float_types:
96 self.failUnlessEqual(ArgType, type(t.from_param(0)))
99 # calling byref returns also a PyCArgObject instance
100 for t in signed_types + unsigned_types + float_types + bool_types:
102 self.failUnlessEqual(ArgType, type(parm))
105 def test_floats(self):
106 # c_float and c_double can be created from
107 # Python int, long and float
108 class FloatLike(object):
112 for t in float_types:
113 self.failUnlessEqual(t(2.0).value, 2.0)
114 self.failUnlessEqual(t(2).value, 2.0)
115 self.failUnlessEqual(t(2L).value, 2.0)
116 self.failUnlessEqual(t(f).value, 2.0)
118 def test_integers(self):
119 class FloatLike(object):
123 class IntLike(object):
127 # integers cannot be constructed from floats,
128 # but from integer-like objects
129 for t in signed_types + unsigned_types:
130 self.assertRaises(TypeError, t, 3.14)
131 self.assertRaises(TypeError, t, f)
132 self.failUnlessEqual(t(i).value, 2)
134 def test_sizes(self):
135 for t in signed_types + unsigned_types + float_types + bool_types:
137 size = struct.calcsize(t._type_)
140 # sizeof of the type...
141 self.failUnlessEqual(sizeof(t), size)
142 # and sizeof of an instance
143 self.failUnlessEqual(sizeof(t()), size)
145 def test_alignments(self):
146 for t in signed_types + unsigned_types + float_types:
147 code = t._type_ # the typecode
148 align = struct.calcsize("c%c" % code) - struct.calcsize(code)
150 # alignment of the type...
151 self.failUnlessEqual((code, alignment(t)),
153 # and alignment of an instance
154 self.failUnlessEqual((code, alignment(t())),
157 def test_int_from_address(self):
158 from array import array
159 for t in signed_types + unsigned_types:
160 # the array module doesn't suppport all format codes
166 a = array(t._type_, [100])
168 # v now is an integer at an 'external' memory location
169 v = t.from_address(a.buffer_info()[0])
170 self.failUnlessEqual(v.value, a[0])
171 self.failUnlessEqual(type(v), t)
173 # changing the value at the memory location changes v's value also
175 self.failUnlessEqual(v.value, a[0])
178 def test_float_from_address(self):
179 from array import array
180 for t in float_types:
181 a = array(t._type_, [3.14])
182 v = t.from_address(a.buffer_info()[0])
183 self.failUnlessEqual(v.value, a[0])
184 self.failUnless(type(v) is t)
186 self.failUnlessEqual(v.value, a[0])
187 self.failUnless(type(v) is t)
189 def test_char_from_address(self):
190 from ctypes import c_char
191 from array import array
194 v = c_char.from_address(a.buffer_info()[0])
195 self.failUnlessEqual(v.value, a[0])
196 self.failUnless(type(v) is c_char)
199 self.failUnlessEqual(v.value, a[0])
201 # array does not support c_bool / 't'
202 # def test_bool_from_address(self):
203 # from ctypes import c_bool
204 # from array import array
205 # a = array(c_bool._type_, [True])
206 # v = t.from_address(a.buffer_info()[0])
207 # self.failUnlessEqual(v.value, a[0])
208 # self.failUnlessEqual(type(v) is t)
210 # self.failUnlessEqual(v.value, a[0])
211 # self.failUnlessEqual(type(v) is t)
214 # c_int() can be initialized from Python's int, and c_int.
215 # Not from c_long or so, which seems strange, abd should
216 # probably be changed:
217 self.assertRaises(TypeError, c_int, c_long(42))
219 ## def test_perf(self):
222 from ctypes import _SimpleCData
223 class c_int_S(_SimpleCData):
227 def run_test(rep, msg, func, arg=None):
228 ## items = [None] * rep
230 from time import clock
234 func(arg); func(arg); func(arg); func(arg); func(arg)
239 func(); func(); func(); func(); func()
241 print "%15s: %.2f us" % (msg, ((stop-start)*1e6/5/rep))
244 # Construct 5 objects
245 from ctypes import c_int
249 run_test(REP, "int()", int)
250 run_test(REP, "int(999)", int)
251 run_test(REP, "c_int()", c_int)
252 run_test(REP, "c_int(999)", c_int)
253 run_test(REP, "c_int_S()", c_int_S)
254 run_test(REP, "c_int_S(999)", c_int_S)
256 # Python 2.3 -OO, win2k, P4 700 MHz:
261 # c_int(999): 3.34 us
263 # c_int_S(999): 3.24 us
265 # Python 2.2 -OO, win2k, P4 700 MHz:
270 # c_int(999): 10.02 us
272 # c_int_S(999): 9.85 us
274 if __name__ == '__main__':