10a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoimport unittest, sys
20a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
30a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoclass SimpleTypesTestCase(unittest.TestCase):
40a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
50a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def setUp(self):
60a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        import ctypes
70a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        try:
80a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            from _ctypes import set_conversion_mode
90a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        except ImportError:
100a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            pass
110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        else:
120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.prev_conv_mode = set_conversion_mode("ascii", "strict")
130a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
140a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def tearDown(self):
150a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        try:
160a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            from _ctypes import set_conversion_mode
170a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        except ImportError:
180a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            pass
190a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        else:
200a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            set_conversion_mode(*self.prev_conv_mode)
210a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
220a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
230a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def test_subclasses(self):
240a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        from ctypes import c_void_p, c_char_p
250a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # ctypes 0.9.5 and before did overwrite from_param in SimpleType_new
260a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        class CVOIDP(c_void_p):
270a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            def from_param(cls, value):
280a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                return value * 2
290a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            from_param = classmethod(from_param)
300a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
310a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        class CCHARP(c_char_p):
320a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            def from_param(cls, value):
330a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                return value * 4
340a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            from_param = classmethod(from_param)
350a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
360a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual(CVOIDP.from_param("abc"), "abcabc")
370a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual(CCHARP.from_param("abc"), "abcabcabcabc")
380a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
390a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        try:
400a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            from ctypes import c_wchar_p
410a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        except ImportError:
420a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            return
430a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
440a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        class CWCHARP(c_wchar_p):
450a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            def from_param(cls, value):
460a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                return value * 3
470a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            from_param = classmethod(from_param)
480a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
490a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual(CWCHARP.from_param("abc"), "abcabcabc")
500a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
510a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    # XXX Replace by c_char_p tests
520a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def test_cstrings(self):
530a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        from ctypes import c_char_p, byref
540a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
550a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # c_char_p.from_param on a Python String packs the string
560a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # into a cparam object
570a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        s = "123"
580a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertTrue(c_char_p.from_param(s)._obj is s)
590a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
600a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # new in 0.9.1: convert (encode) unicode to ascii
610a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual(c_char_p.from_param(u"123")._obj, "123")
620a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertRaises(UnicodeEncodeError, c_char_p.from_param, u"123\377")
630a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
640a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertRaises(TypeError, c_char_p.from_param, 42)
650a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
660a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # calling c_char_p.from_param with a c_char_p instance
670a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # returns the argument itself:
680a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        a = c_char_p("123")
690a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertTrue(c_char_p.from_param(a) is a)
700a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
710a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def test_cw_strings(self):
720a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        from ctypes import byref
730a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        try:
740a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            from ctypes import c_wchar_p
750a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        except ImportError:
760a8c90248264a8b26970b4473770bcc3df8515fJosh Gao##            print "(No c_wchar_p)"
770a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            return
780a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        s = u"123"
790a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if sys.platform == "win32":
800a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.assertTrue(c_wchar_p.from_param(s)._obj is s)
810a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.assertRaises(TypeError, c_wchar_p.from_param, 42)
820a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
830a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            # new in 0.9.1: convert (decode) ascii to unicode
840a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.assertEqual(c_wchar_p.from_param("123")._obj, u"123")
850a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertRaises(UnicodeDecodeError, c_wchar_p.from_param, "123\377")
860a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
870a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        pa = c_wchar_p.from_param(c_wchar_p(u"123"))
880a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual(type(pa), c_wchar_p)
890a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
900a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def test_int_pointers(self):
910a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        from ctypes import c_short, c_uint, c_int, c_long, POINTER, pointer
920a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        LPINT = POINTER(c_int)
930a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
940a8c90248264a8b26970b4473770bcc3df8515fJosh Gao##        p = pointer(c_int(42))
950a8c90248264a8b26970b4473770bcc3df8515fJosh Gao##        x = LPINT.from_param(p)
960a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        x = LPINT.from_param(pointer(c_int(42)))
970a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual(x.contents.value, 42)
980a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual(LPINT(c_int(42)).contents.value, 42)
990a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1000a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual(LPINT.from_param(None), None)
1010a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1020a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if c_int != c_long:
1030a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.assertRaises(TypeError, LPINT.from_param, pointer(c_long(42)))
1040a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertRaises(TypeError, LPINT.from_param, pointer(c_uint(42)))
1050a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertRaises(TypeError, LPINT.from_param, pointer(c_short(42)))
1060a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1070a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def test_byref_pointer(self):
1080a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # The from_param class method of POINTER(typ) classes accepts what is
1090a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # returned by byref(obj), it type(obj) == typ
1100a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        from ctypes import c_short, c_uint, c_int, c_long, pointer, POINTER, byref
1110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        LPINT = POINTER(c_int)
1120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1130a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        LPINT.from_param(byref(c_int(42)))
1140a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1150a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertRaises(TypeError, LPINT.from_param, byref(c_short(22)))
1160a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if c_int != c_long:
1170a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.assertRaises(TypeError, LPINT.from_param, byref(c_long(22)))
1180a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertRaises(TypeError, LPINT.from_param, byref(c_uint(22)))
1190a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1200a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def test_byref_pointerpointer(self):
1210a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # See above
1220a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        from ctypes import c_short, c_uint, c_int, c_long, pointer, POINTER, byref
1230a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1240a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        LPLPINT = POINTER(POINTER(c_int))
1250a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        LPLPINT.from_param(byref(pointer(c_int(42))))
1260a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1270a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertRaises(TypeError, LPLPINT.from_param, byref(pointer(c_short(22))))
1280a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if c_int != c_long:
1290a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.assertRaises(TypeError, LPLPINT.from_param, byref(pointer(c_long(22))))
1300a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertRaises(TypeError, LPLPINT.from_param, byref(pointer(c_uint(22))))
1310a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1320a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def test_array_pointers(self):
1330a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        from ctypes import c_short, c_uint, c_int, c_long, POINTER
1340a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        INTARRAY = c_int * 3
1350a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        ia = INTARRAY()
1360a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual(len(ia), 3)
1370a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual([ia[i] for i in range(3)], [0, 0, 0])
1380a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1390a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # Pointers are only compatible with arrays containing items of
1400a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # the same type!
1410a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        LPINT = POINTER(c_int)
1420a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        LPINT.from_param((c_int*3)())
1430a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertRaises(TypeError, LPINT.from_param, c_short*3)
1440a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertRaises(TypeError, LPINT.from_param, c_long*3)
1450a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertRaises(TypeError, LPINT.from_param, c_uint*3)
1460a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1470a8c90248264a8b26970b4473770bcc3df8515fJosh Gao##    def test_performance(self):
1480a8c90248264a8b26970b4473770bcc3df8515fJosh Gao##        check_perf()
1490a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1500a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def test_noctypes_argtype(self):
1510a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        import _ctypes_test
1520a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        from ctypes import CDLL, c_void_p, ArgumentError
1530a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1540a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        func = CDLL(_ctypes_test.__file__)._testfunc_p_p
1550a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        func.restype = c_void_p
1560a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # TypeError: has no from_param method
1570a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertRaises(TypeError, setattr, func, "argtypes", (object,))
1580a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1590a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        class Adapter(object):
1600a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            def from_param(cls, obj):
1610a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                return None
1620a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1630a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        func.argtypes = (Adapter(),)
1640a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual(func(None), None)
1650a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual(func(object()), None)
1660a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1670a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        class Adapter(object):
1680a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            def from_param(cls, obj):
1690a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                return obj
1700a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1710a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        func.argtypes = (Adapter(),)
1720a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # don't know how to convert parameter 1
1730a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertRaises(ArgumentError, func, object())
1740a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual(func(c_void_p(42)), 42)
1750a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1760a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        class Adapter(object):
1770a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            def from_param(cls, obj):
1780a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                raise ValueError(obj)
1790a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1800a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        func.argtypes = (Adapter(),)
1810a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # ArgumentError: argument 1: ValueError: 99
1820a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertRaises(ArgumentError, func, 99)
1830a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1840a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1850a8c90248264a8b26970b4473770bcc3df8515fJosh Gao################################################################
1860a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1870a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoif __name__ == '__main__':
1880a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    unittest.main()
189