Home | History | Annotate | Download | only in test
      1 import unittest
      2 import pickle
      3 from ctypes import *
      4 import _ctypes_test
      5 dll = CDLL(_ctypes_test.__file__)
      6 
      7 class X(Structure):
      8     _fields_ = [("a", c_int), ("b", c_double)]
      9     init_called = 0
     10     def __init__(self, *args, **kw):
     11         X.init_called += 1
     12         self.x = 42
     13 
     14 class Y(X):
     15     _fields_ = [("str", c_char_p)]
     16 
     17 class PickleTest:
     18     def dumps(self, item):
     19         return pickle.dumps(item, self.proto)
     20 
     21     def loads(self, item):
     22         return pickle.loads(item)
     23 
     24     def test_simple(self):
     25         for src in [
     26             c_int(42),
     27             c_double(3.14),
     28             ]:
     29             dst = self.loads(self.dumps(src))
     30             self.assertEqual(src.__dict__, dst.__dict__)
     31             self.assertEqual(memoryview(src).tobytes(),
     32                                  memoryview(dst).tobytes())
     33 
     34     def test_struct(self):
     35         X.init_called = 0
     36 
     37         x = X()
     38         x.a = 42
     39         self.assertEqual(X.init_called, 1)
     40 
     41         y = self.loads(self.dumps(x))
     42 
     43         # loads must NOT call __init__
     44         self.assertEqual(X.init_called, 1)
     45 
     46         # ctypes instances are identical when the instance __dict__
     47         # and the memory buffer are identical
     48         self.assertEqual(y.__dict__, x.__dict__)
     49         self.assertEqual(memoryview(y).tobytes(),
     50                              memoryview(x).tobytes())
     51 
     52     def test_unpickable(self):
     53         # ctypes objects that are pointers or contain pointers are
     54         # unpickable.
     55         self.assertRaises(ValueError, lambda: self.dumps(Y()))
     56 
     57         prototype = CFUNCTYPE(c_int)
     58 
     59         for item in [
     60             c_char_p(),
     61             c_wchar_p(),
     62             c_void_p(),
     63             pointer(c_int(42)),
     64             dll._testfunc_p_p,
     65             prototype(lambda: 42),
     66             ]:
     67             self.assertRaises(ValueError, lambda: self.dumps(item))
     68 
     69     def test_wchar(self):
     70         self.dumps(c_char(b"x"))
     71         # Issue 5049
     72         self.dumps(c_wchar(u"x"))
     73 
     74 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
     75     name = 'PickleTest_%s' % proto
     76     globals()[name] = type(name,
     77                            (PickleTest, unittest.TestCase),
     78                            {'proto': proto})
     79 
     80 if __name__ == "__main__":
     81     unittest.main()
     82