test_builtin_converters.py 8.7 KB

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