/Lib/ctypes/test/test_refcounts.py

http://unladen-swallow.googlecode.com/ · Python · 98 lines · 61 code · 27 blank · 10 comment · 1 complexity · d412f5fef54ee53209c7f9103c0f46df MD5 · raw file

  1. import unittest
  2. import ctypes
  3. import gc
  4. MyCallback = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_int)
  5. OtherCallback = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_int, ctypes.c_ulonglong)
  6. import _ctypes_test
  7. dll = ctypes.CDLL(_ctypes_test.__file__)
  8. class RefcountTestCase(unittest.TestCase):
  9. def test_1(self):
  10. from sys import getrefcount as grc
  11. f = dll._testfunc_callback_i_if
  12. f.restype = ctypes.c_int
  13. f.argtypes = [ctypes.c_int, MyCallback]
  14. def callback(value):
  15. #print "called back with", value
  16. return value
  17. self.failUnlessEqual(grc(callback), 2)
  18. cb = MyCallback(callback)
  19. self.failUnless(grc(callback) > 2)
  20. result = f(-10, cb)
  21. self.failUnlessEqual(result, -18)
  22. cb = None
  23. gc.collect()
  24. self.failUnlessEqual(grc(callback), 2)
  25. def test_refcount(self):
  26. from sys import getrefcount as grc
  27. def func(*args):
  28. pass
  29. # this is the standard refcount for func
  30. self.failUnlessEqual(grc(func), 2)
  31. # the CFuncPtr instance holds atr least one refcount on func:
  32. f = OtherCallback(func)
  33. self.failUnless(grc(func) > 2)
  34. # and may release it again
  35. del f
  36. self.failUnless(grc(func) >= 2)
  37. # but now it must be gone
  38. gc.collect()
  39. self.failUnless(grc(func) == 2)
  40. class X(ctypes.Structure):
  41. _fields_ = [("a", OtherCallback)]
  42. x = X()
  43. x.a = OtherCallback(func)
  44. # the CFuncPtr instance holds atr least one refcount on func:
  45. self.failUnless(grc(func) > 2)
  46. # and may release it again
  47. del x
  48. self.failUnless(grc(func) >= 2)
  49. # and now it must be gone again
  50. gc.collect()
  51. self.failUnlessEqual(grc(func), 2)
  52. f = OtherCallback(func)
  53. # the CFuncPtr instance holds atr least one refcount on func:
  54. self.failUnless(grc(func) > 2)
  55. # create a cycle
  56. f.cycle = f
  57. del f
  58. gc.collect()
  59. self.failUnlessEqual(grc(func), 2)
  60. class AnotherLeak(unittest.TestCase):
  61. def test_callback(self):
  62. import sys
  63. proto = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_int, ctypes.c_int)
  64. def func(a, b):
  65. return a * b * 2
  66. f = proto(func)
  67. a = sys.getrefcount(ctypes.c_int)
  68. f(1, 2)
  69. self.failUnlessEqual(sys.getrefcount(ctypes.c_int), a)
  70. if __name__ == '__main__':
  71. unittest.main()