]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | # Copyright David Abrahams 2004. Distributed under the Boost |
2 | # Software License, Version 1.0. (See accompanying | |
3 | # file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
4 | import sys | |
5 | if (sys.version_info.major >= 3): | |
6 | long = int | |
7 | r""" | |
8 | >>> from builtin_converters_ext import * | |
9 | ||
10 | # Provide values for integer converter tests | |
11 | >>> def _signed_values(s): | |
12 | ... base = 2 ** (8 * s - 1) | |
13 | ... return [[-base, -1, 1, base - 1], [-base - 1, base]] | |
14 | >>> def _unsigned_values(s): | |
15 | ... base = 2 ** (8 * s) | |
16 | ... return [[1, base - 1], [long(-1), -1, base]] | |
17 | ||
18 | # Wrappers to simplify tests | |
19 | >>> def should_pass(method, values): | |
20 | ... result = map(method, values[0]) | |
21 | ... if result != values[0]: | |
22 | ... print("Got %s but expected %s" % (result, values[0])) | |
23 | >>> def test_overflow(method, values): | |
24 | ... for v in values[1]: | |
25 | ... try: method(v) | |
26 | ... except OverflowError: pass | |
27 | ... else: print("OverflowError expected") | |
28 | ||
29 | # Synthesize idendity functions in case long long not supported | |
30 | >>> if not 'rewrap_value_long_long' in dir(): | |
31 | ... def rewrap_value_long_long(x): return long(x) | |
32 | ... def rewrap_value_unsigned_long_long(x): return long(x) | |
33 | ... def rewrap_const_reference_long_long(x): return long(x) | |
34 | ... def rewrap_const_reference_unsigned_long_long(x): return long(x) | |
35 | >>> if not 'long_long_size' in dir(): | |
36 | ... def long_long_size(): return long_size() | |
37 | ||
38 | >>> try: bool_exists = bool | |
39 | ... except: pass | |
40 | ... else: | |
41 | ... rewrap_value_bool(True) | |
42 | ... rewrap_value_bool(False) | |
43 | True | |
44 | False | |
45 | ||
46 | >>> rewrap_value_bool(None) | |
47 | 0 | |
48 | >>> rewrap_value_bool(0) | |
49 | 0 | |
50 | >>> rewrap_value_bool(33) | |
51 | 1 | |
52 | >>> rewrap_value_char('x') | |
53 | 'x' | |
54 | ||
55 | Note that there's currently silent truncation of strings passed to | |
56 | char arguments. | |
57 | ||
58 | >>> rewrap_value_char('xy') | |
59 | 'x' | |
60 | >>> rewrap_value_signed_char(42) | |
61 | 42 | |
62 | >>> rewrap_value_unsigned_char(42) | |
63 | 42 | |
64 | >>> rewrap_value_int(42) | |
65 | 42 | |
66 | >>> rewrap_value_unsigned_int(42) | |
67 | 42 | |
68 | >>> rewrap_value_short(42) | |
69 | 42 | |
70 | >>> rewrap_value_unsigned_short(42) | |
71 | 42 | |
72 | >>> rewrap_value_long(42) | |
73 | 42 | |
74 | >>> rewrap_value_unsigned_long(42) | |
75 | 42 | |
76 | ||
77 | test unsigned long values which don't fit in a signed long. | |
78 | strip any 'L' characters in case the platform has > 32 bit longs | |
79 | ||
b32b8144 | 80 | >>> hex(rewrap_value_unsigned_long(long(0x80000001))).replace('L','') |
7c673cae FG |
81 | '0x80000001' |
82 | ||
83 | >>> rewrap_value_long_long(42) == 42 | |
84 | True | |
85 | >>> rewrap_value_unsigned_long_long(42) == 42 | |
86 | True | |
87 | ||
88 | show that we have range checking. | |
89 | ||
90 | >>> should_pass(rewrap_value_signed_char, _signed_values(char_size())) | |
91 | >>> should_pass(rewrap_value_short, _signed_values(short_size())) | |
92 | >>> should_pass(rewrap_value_int, _signed_values(int_size())) | |
93 | >>> should_pass(rewrap_value_long, _signed_values(long_size())) | |
94 | >>> should_pass(rewrap_value_long_long, _signed_values(long_long_size())) | |
95 | ||
96 | >>> should_pass(rewrap_value_unsigned_char, _unsigned_values(char_size())) | |
97 | >>> should_pass(rewrap_value_unsigned_short, _unsigned_values(short_size())) | |
98 | >>> should_pass(rewrap_value_unsigned_int, _unsigned_values(int_size())) | |
99 | >>> should_pass(rewrap_value_unsigned_long, _unsigned_values(long_size())) | |
100 | >>> should_pass(rewrap_value_unsigned_long_long, | |
101 | ... _unsigned_values(long_long_size())) | |
102 | ||
103 | >>> test_overflow(rewrap_value_signed_char, _signed_values(char_size())) | |
104 | >>> test_overflow(rewrap_value_short, _signed_values(short_size())) | |
105 | >>> test_overflow(rewrap_value_int, _signed_values(int_size())) | |
106 | >>> test_overflow(rewrap_value_long, _signed_values(long_size())) | |
107 | >>> test_overflow(rewrap_value_long_long, _signed_values(long_long_size())) | |
108 | ||
109 | >>> test_overflow(rewrap_value_unsigned_char, _unsigned_values(char_size())) | |
110 | >>> test_overflow(rewrap_value_unsigned_short, _unsigned_values(short_size())) | |
111 | >>> test_overflow(rewrap_value_unsigned_int, _unsigned_values(int_size())) | |
112 | >>> test_overflow(rewrap_value_unsigned_long, _unsigned_values(long_size())) | |
113 | ||
114 | # Exceptionally for PyLong_AsUnsignedLongLong(), a negative value raises | |
115 | # TypeError on Python versions prior to 2.7 | |
116 | >>> for v in _unsigned_values(long_long_size())[1]: | |
117 | ... try: rewrap_value_unsigned_long_long(v) | |
118 | ... except (OverflowError, TypeError): pass | |
119 | ... else: print("OverflowError or TypeError expected") | |
120 | ||
121 | >>> assert abs(rewrap_value_float(4.2) - 4.2) < .000001 | |
122 | >>> rewrap_value_double(4.2) - 4.2 | |
123 | 0.0 | |
124 | >>> rewrap_value_long_double(4.2) - 4.2 | |
125 | 0.0 | |
126 | ||
127 | >>> assert abs(rewrap_value_complex_float(4+.2j) - (4+.2j)) < .000001 | |
128 | >>> assert abs(rewrap_value_complex_double(4+.2j) - (4+.2j)) < .000001 | |
129 | >>> assert abs(rewrap_value_complex_long_double(4+.2j) - (4+.2j)) < .000001 | |
130 | ||
131 | >>> rewrap_value_cstring('hello, world') | |
132 | 'hello, world' | |
133 | >>> rewrap_value_string('yo, wassup?') | |
134 | 'yo, wassup?' | |
135 | ||
136 | >>> print(rewrap_value_wstring(u'yo, wassup?')) | |
137 | yo, wassup? | |
138 | ||
b32b8144 FG |
139 | >>> print(rewrap_value_wstring(u'\U0001f4a9')) |
140 | \U0001f4a9 | |
141 | ||
7c673cae FG |
142 | test that overloading on unicode works: |
143 | ||
144 | >>> print(rewrap_value_string(u'yo, wassup?')) | |
145 | yo, wassup? | |
146 | ||
147 | wrap strings with embedded nulls: | |
148 | ||
149 | >>> rewrap_value_string('yo,\0wassup?') | |
150 | 'yo,\x00wassup?' | |
151 | ||
152 | >>> rewrap_value_handle(1) | |
153 | 1 | |
154 | >>> x = 'hi' | |
155 | >>> assert rewrap_value_handle(x) is x | |
156 | >>> assert rewrap_value_object(x) is x | |
157 | ||
158 | Note that we can currently get a mutable pointer into an immutable | |
159 | Python string: | |
160 | ||
161 | >>> rewrap_value_mutable_cstring('hello, world') | |
162 | 'hello, world' | |
163 | ||
164 | >>> rewrap_const_reference_bool(None) | |
165 | 0 | |
166 | >>> rewrap_const_reference_bool(0) | |
167 | 0 | |
168 | ||
169 | >>> try: rewrap_const_reference_bool('yes') | |
170 | ... except TypeError: pass | |
171 | ... else: print('expected a TypeError exception') | |
172 | ||
173 | >>> rewrap_const_reference_char('x') | |
174 | 'x' | |
175 | ||
176 | Note that there's currently silent truncation of strings passed to | |
177 | char arguments. | |
178 | ||
179 | >>> rewrap_const_reference_char('xy') | |
180 | 'x' | |
181 | >>> rewrap_const_reference_signed_char(42) | |
182 | 42 | |
183 | >>> rewrap_const_reference_unsigned_char(42) | |
184 | 42 | |
185 | >>> rewrap_const_reference_int(42) | |
186 | 42 | |
187 | >>> rewrap_const_reference_unsigned_int(42) | |
188 | 42 | |
189 | >>> rewrap_const_reference_short(42) | |
190 | 42 | |
191 | >>> rewrap_const_reference_unsigned_short(42) | |
192 | 42 | |
193 | >>> rewrap_const_reference_long(42) | |
194 | 42 | |
195 | >>> rewrap_const_reference_unsigned_long(42) | |
196 | 42 | |
197 | >>> rewrap_const_reference_long_long(42) == 42 | |
198 | True | |
199 | >>> rewrap_const_reference_unsigned_long_long(42) == 42 | |
200 | True | |
201 | ||
202 | ||
203 | >>> assert abs(rewrap_const_reference_float(4.2) - 4.2) < .000001 | |
204 | >>> rewrap_const_reference_double(4.2) - 4.2 | |
205 | 0.0 | |
206 | >>> rewrap_const_reference_long_double(4.2) - 4.2 | |
207 | 0.0 | |
208 | ||
209 | >>> assert abs(rewrap_const_reference_complex_float(4+.2j) - (4+.2j)) < .000001 | |
210 | >>> assert abs(rewrap_const_reference_complex_double(4+.2j) - (4+.2j)) < .000001 | |
211 | >>> assert abs(rewrap_const_reference_complex_long_double(4+.2j) - (4+.2j)) < .000001 | |
212 | ||
213 | >>> rewrap_const_reference_cstring('hello, world') | |
214 | 'hello, world' | |
215 | >>> rewrap_const_reference_string('yo, wassup?') | |
216 | 'yo, wassup?' | |
217 | ||
218 | >>> rewrap_const_reference_handle(1) | |
219 | 1 | |
220 | >>> x = 'hi' | |
221 | >>> assert rewrap_const_reference_handle(x) is x | |
222 | >>> assert rewrap_const_reference_object(x) is x | |
223 | >>> assert rewrap_reference_object(x) is x | |
224 | ||
225 | ||
226 | Check that None <==> NULL | |
227 | ||
228 | >>> rewrap_const_reference_cstring(None) | |
229 | ||
230 | But None cannot be converted to a string object: | |
231 | ||
232 | >>> try: rewrap_const_reference_string(None) | |
233 | ... except TypeError: pass | |
234 | ... else: print('expected a TypeError exception') | |
235 | ||
236 | Now check implicit conversions between floating/integer types | |
237 | ||
238 | >>> rewrap_const_reference_float(42) | |
239 | 42.0 | |
240 | ||
241 | >>> rewrap_const_reference_float(long(42)) | |
242 | 42.0 | |
243 | ||
244 | >>> try: rewrap_const_reference_int(42.0) | |
245 | ... except TypeError: pass | |
246 | ... else: print('expected a TypeError exception') | |
247 | ||
248 | >>> rewrap_value_float(42) | |
249 | 42.0 | |
250 | ||
251 | >>> try: rewrap_value_int(42.0) | |
252 | ... except TypeError: pass | |
253 | ... else: print('expected a TypeError exception') | |
254 | ||
255 | Check that classic classes also work | |
256 | ||
257 | >>> class FortyTwo: | |
258 | ... def __int__(self): | |
259 | ... return 42 | |
260 | ... def __float__(self): | |
261 | ... return 42.0 | |
262 | ... def __complex__(self): | |
263 | ... return complex(4+.2j) | |
264 | ... def __str__(self): | |
265 | ... return '42' | |
266 | ||
267 | >>> try: rewrap_const_reference_float(FortyTwo()) | |
268 | ... except TypeError: pass | |
269 | ... else: print('expected a TypeError exception') | |
270 | ||
271 | >>> try: rewrap_value_int(FortyTwo()) | |
272 | ... except TypeError: pass | |
273 | ... else: print('expected a TypeError exception') | |
274 | ||
275 | >>> try: rewrap_const_reference_string(FortyTwo()) | |
276 | ... except TypeError: pass | |
277 | ... else: print('expected a TypeError exception') | |
278 | ||
279 | >>> try: rewrap_value_complex_double(FortyTwo()) | |
280 | ... except TypeError: pass | |
281 | ... else: print('expected a TypeError exception') | |
282 | ||
283 | # show that arbitrary handle<T> instantiations can be returned | |
284 | >>> assert get_type(1) is type(1) | |
285 | ||
286 | >>> assert return_null_handle() is None | |
287 | """ | |
288 | ||
b32b8144 FG |
289 | import sys |
290 | if (sys.version_info.major >= 3): | |
291 | long = int | |
292 | ||
7c673cae FG |
293 | def run(args = None): |
294 | import sys | |
295 | import doctest | |
296 | import builtin_converters_ext | |
297 | ||
298 | if 'rewrap_value_long_long' in dir(builtin_converters_ext): | |
299 | print('LONG_LONG supported, testing...') | |
300 | else: | |
301 | print('LONG_LONG not supported, skipping those tests...') | |
302 | ||
303 | if args is not None: | |
304 | sys.argv = args | |
305 | return doctest.testmod(sys.modules.get(__name__)) | |
306 | ||
307 | if __name__ == '__main__': | |
308 | print("running...") | |
309 | import sys | |
310 | status = run()[0] | |
311 | if (status == 0): print("Done.") | |
312 | sys.exit(status) |