/Lib/ctypes/test/test_parameters.py

http://unladen-swallow.googlecode.com/ · Python · 188 lines · 124 code · 42 blank · 22 comment · 16 complexity · 308159aac0b3af90ca8be5d32c20d8a1 MD5 · raw file

  1. import unittest, sys
  2. class SimpleTypesTestCase(unittest.TestCase):
  3. def setUp(self):
  4. import ctypes
  5. try:
  6. from _ctypes import set_conversion_mode
  7. except ImportError:
  8. pass
  9. else:
  10. self.prev_conv_mode = set_conversion_mode("ascii", "strict")
  11. def tearDown(self):
  12. try:
  13. from _ctypes import set_conversion_mode
  14. except ImportError:
  15. pass
  16. else:
  17. set_conversion_mode(*self.prev_conv_mode)
  18. def test_subclasses(self):
  19. from ctypes import c_void_p, c_char_p
  20. # ctypes 0.9.5 and before did overwrite from_param in SimpleType_new
  21. class CVOIDP(c_void_p):
  22. def from_param(cls, value):
  23. return value * 2
  24. from_param = classmethod(from_param)
  25. class CCHARP(c_char_p):
  26. def from_param(cls, value):
  27. return value * 4
  28. from_param = classmethod(from_param)
  29. self.failUnlessEqual(CVOIDP.from_param("abc"), "abcabc")
  30. self.failUnlessEqual(CCHARP.from_param("abc"), "abcabcabcabc")
  31. try:
  32. from ctypes import c_wchar_p
  33. except ImportError:
  34. return
  35. class CWCHARP(c_wchar_p):
  36. def from_param(cls, value):
  37. return value * 3
  38. from_param = classmethod(from_param)
  39. self.failUnlessEqual(CWCHARP.from_param("abc"), "abcabcabc")
  40. # XXX Replace by c_char_p tests
  41. def test_cstrings(self):
  42. from ctypes import c_char_p, byref
  43. # c_char_p.from_param on a Python String packs the string
  44. # into a cparam object
  45. s = "123"
  46. self.failUnless(c_char_p.from_param(s)._obj is s)
  47. # new in 0.9.1: convert (encode) unicode to ascii
  48. self.failUnlessEqual(c_char_p.from_param(u"123")._obj, "123")
  49. self.assertRaises(UnicodeEncodeError, c_char_p.from_param, u"123\377")
  50. self.assertRaises(TypeError, c_char_p.from_param, 42)
  51. # calling c_char_p.from_param with a c_char_p instance
  52. # returns the argument itself:
  53. a = c_char_p("123")
  54. self.failUnless(c_char_p.from_param(a) is a)
  55. def test_cw_strings(self):
  56. from ctypes import byref
  57. try:
  58. from ctypes import c_wchar_p
  59. except ImportError:
  60. ## print "(No c_wchar_p)"
  61. return
  62. s = u"123"
  63. if sys.platform == "win32":
  64. self.failUnless(c_wchar_p.from_param(s)._obj is s)
  65. self.assertRaises(TypeError, c_wchar_p.from_param, 42)
  66. # new in 0.9.1: convert (decode) ascii to unicode
  67. self.failUnlessEqual(c_wchar_p.from_param("123")._obj, u"123")
  68. self.assertRaises(UnicodeDecodeError, c_wchar_p.from_param, "123\377")
  69. pa = c_wchar_p.from_param(c_wchar_p(u"123"))
  70. self.failUnlessEqual(type(pa), c_wchar_p)
  71. def test_int_pointers(self):
  72. from ctypes import c_short, c_uint, c_int, c_long, POINTER, pointer
  73. LPINT = POINTER(c_int)
  74. ## p = pointer(c_int(42))
  75. ## x = LPINT.from_param(p)
  76. x = LPINT.from_param(pointer(c_int(42)))
  77. self.failUnlessEqual(x.contents.value, 42)
  78. self.failUnlessEqual(LPINT(c_int(42)).contents.value, 42)
  79. self.assertEqual(LPINT.from_param(None), None)
  80. if c_int != c_long:
  81. self.assertRaises(TypeError, LPINT.from_param, pointer(c_long(42)))
  82. self.assertRaises(TypeError, LPINT.from_param, pointer(c_uint(42)))
  83. self.assertRaises(TypeError, LPINT.from_param, pointer(c_short(42)))
  84. def test_byref_pointer(self):
  85. # The from_param class method of POINTER(typ) classes accepts what is
  86. # returned by byref(obj), it type(obj) == typ
  87. from ctypes import c_short, c_uint, c_int, c_long, pointer, POINTER, byref
  88. LPINT = POINTER(c_int)
  89. LPINT.from_param(byref(c_int(42)))
  90. self.assertRaises(TypeError, LPINT.from_param, byref(c_short(22)))
  91. if c_int != c_long:
  92. self.assertRaises(TypeError, LPINT.from_param, byref(c_long(22)))
  93. self.assertRaises(TypeError, LPINT.from_param, byref(c_uint(22)))
  94. def test_byref_pointerpointer(self):
  95. # See above
  96. from ctypes import c_short, c_uint, c_int, c_long, pointer, POINTER, byref
  97. LPLPINT = POINTER(POINTER(c_int))
  98. LPLPINT.from_param(byref(pointer(c_int(42))))
  99. self.assertRaises(TypeError, LPLPINT.from_param, byref(pointer(c_short(22))))
  100. if c_int != c_long:
  101. self.assertRaises(TypeError, LPLPINT.from_param, byref(pointer(c_long(22))))
  102. self.assertRaises(TypeError, LPLPINT.from_param, byref(pointer(c_uint(22))))
  103. def test_array_pointers(self):
  104. from ctypes import c_short, c_uint, c_int, c_long, POINTER
  105. INTARRAY = c_int * 3
  106. ia = INTARRAY()
  107. self.failUnlessEqual(len(ia), 3)
  108. self.failUnlessEqual([ia[i] for i in range(3)], [0, 0, 0])
  109. # Pointers are only compatible with arrays containing items of
  110. # the same type!
  111. LPINT = POINTER(c_int)
  112. LPINT.from_param((c_int*3)())
  113. self.assertRaises(TypeError, LPINT.from_param, c_short*3)
  114. self.assertRaises(TypeError, LPINT.from_param, c_long*3)
  115. self.assertRaises(TypeError, LPINT.from_param, c_uint*3)
  116. ## def test_performance(self):
  117. ## check_perf()
  118. def test_noctypes_argtype(self):
  119. import _ctypes_test
  120. from ctypes import CDLL, c_void_p, ArgumentError
  121. func = CDLL(_ctypes_test.__file__)._testfunc_p_p
  122. func.restype = c_void_p
  123. # TypeError: has no from_param method
  124. self.assertRaises(TypeError, setattr, func, "argtypes", (object,))
  125. class Adapter(object):
  126. def from_param(cls, obj):
  127. return None
  128. func.argtypes = (Adapter(),)
  129. self.failUnlessEqual(func(None), None)
  130. self.failUnlessEqual(func(object()), None)
  131. class Adapter(object):
  132. def from_param(cls, obj):
  133. return obj
  134. func.argtypes = (Adapter(),)
  135. # don't know how to convert parameter 1
  136. self.assertRaises(ArgumentError, func, object())
  137. self.failUnlessEqual(func(c_void_p(42)), 42)
  138. class Adapter(object):
  139. def from_param(cls, obj):
  140. raise ValueError(obj)
  141. func.argtypes = (Adapter(),)
  142. # ArgumentError: argument 1: ValueError: 99
  143. self.assertRaises(ArgumentError, func, 99)
  144. ################################################################
  145. if __name__ == '__main__':
  146. unittest.main()