]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/python/contrib/Lib/ctypes/test/test_numbers.py
Inital import
[l4.git] / l4 / pkg / python / contrib / Lib / ctypes / test / test_numbers.py
1 from ctypes import *
2 import unittest
3 import struct
4
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.
11     result = []
12     for t in types:
13         fmt = t._type_
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)))
20     return result
21
22 ArgType = type(byref(c_int(0)))
23
24 unsigned_types = [c_ubyte, c_ushort, c_uint, c_ulong]
25 signed_types = [c_byte, c_short, c_int, c_long, c_longlong]
26
27 bool_types = []
28
29 float_types = [c_double, c_float]
30
31 try:
32     c_ulonglong
33     c_longlong
34 except NameError:
35     pass
36 else:
37     unsigned_types.append(c_ulonglong)
38     signed_types.append(c_longlong)
39
40 try:
41     c_bool
42 except NameError:
43     pass
44 else:
45     bool_types.append(c_bool)
46
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]]
50
51 ################################################################
52
53 class NumberTestCase(unittest.TestCase):
54
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)
59
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)
66
67     def test_signed_values(self):
68         # see above
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)
72
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))
77
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)
84
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)
91
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)))
97
98     def test_byref(self):
99         # calling byref returns also a PyCArgObject instance
100         for t in signed_types + unsigned_types + float_types + bool_types:
101             parm = byref(t())
102             self.failUnlessEqual(ArgType, type(parm))
103
104
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):
109             def __float__(self):
110                 return 2.0
111         f = FloatLike()
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)
117
118     def test_integers(self):
119         class FloatLike(object):
120             def __float__(self):
121                 return 2.0
122         f = FloatLike()
123         class IntLike(object):
124             def __int__(self):
125                 return 2
126         i = IntLike()
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)
133
134     def test_sizes(self):
135         for t in signed_types + unsigned_types + float_types + bool_types:
136             try:
137                 size = struct.calcsize(t._type_)
138             except struct.error:
139                 continue
140             # sizeof of the type...
141             self.failUnlessEqual(sizeof(t), size)
142             # and sizeof of an instance
143             self.failUnlessEqual(sizeof(t()), size)
144
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)
149
150             # alignment of the type...
151             self.failUnlessEqual((code, alignment(t)),
152                                  (code, align))
153             # and alignment of an instance
154             self.failUnlessEqual((code, alignment(t())),
155                                  (code, align))
156
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
161             # (no 'q' or 'Q')
162             try:
163                 array(t._type_)
164             except ValueError:
165                 continue
166             a = array(t._type_, [100])
167
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)
172
173             # changing the value at the memory location changes v's value also
174             a[0] = 42
175             self.failUnlessEqual(v.value, a[0])
176
177
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)
185             a[0] = 2.3456e17
186             self.failUnlessEqual(v.value, a[0])
187             self.failUnless(type(v) is t)
188
189     def test_char_from_address(self):
190         from ctypes import c_char
191         from array import array
192
193         a = array('c', 'x')
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)
197
198         a[0] = '?'
199         self.failUnlessEqual(v.value, a[0])
200
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)
209     #     a[0] = False
210     #     self.failUnlessEqual(v.value, a[0])
211     #     self.failUnlessEqual(type(v) is t)
212
213     def test_init(self):
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))
218
219 ##    def test_perf(self):
220 ##        check_perf()
221
222 from ctypes import _SimpleCData
223 class c_int_S(_SimpleCData):
224     _type_ = "i"
225     __slots__ = []
226
227 def run_test(rep, msg, func, arg=None):
228 ##    items = [None] * rep
229     items = range(rep)
230     from time import clock
231     if arg is not None:
232         start = clock()
233         for i in items:
234             func(arg); func(arg); func(arg); func(arg); func(arg)
235         stop = clock()
236     else:
237         start = clock()
238         for i in items:
239             func(); func(); func(); func(); func()
240         stop = clock()
241     print "%15s: %.2f us" % (msg, ((stop-start)*1e6/5/rep))
242
243 def check_perf():
244     # Construct 5 objects
245     from ctypes import c_int
246
247     REP = 200000
248
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)
255
256 # Python 2.3 -OO, win2k, P4 700 MHz:
257 #
258 #          int(): 0.87 us
259 #       int(999): 0.87 us
260 #        c_int(): 3.35 us
261 #     c_int(999): 3.34 us
262 #      c_int_S(): 3.23 us
263 #   c_int_S(999): 3.24 us
264
265 # Python 2.2 -OO, win2k, P4 700 MHz:
266 #
267 #          int(): 0.89 us
268 #       int(999): 0.89 us
269 #        c_int(): 9.99 us
270 #     c_int(999): 10.02 us
271 #      c_int_S(): 9.87 us
272 #   c_int_S(999): 9.85 us
273
274 if __name__ == '__main__':
275 ##    check_perf()
276     unittest.main()