handles.py 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. import sys
  2. import unittest
  3. import pywintypes
  4. import win32api
  5. from pywin32_testutil import int2long
  6. # A class that will never die vie refcounting, but will die via GC.
  7. class Cycle:
  8. def __init__(self, handle):
  9. self.cycle = self
  10. self.handle = handle
  11. class PyHandleTestCase(unittest.TestCase):
  12. def testCleanup1(self):
  13. # We used to clobber all outstanding exceptions.
  14. def f1(invalidate):
  15. import win32event
  16. h = win32event.CreateEvent(None, 0, 0, None)
  17. if invalidate:
  18. win32api.CloseHandle(int(h))
  19. 1/0
  20. # If we invalidated, then the object destruction code will attempt
  21. # to close an invalid handle. We don't wan't an exception in
  22. # this case
  23. def f2(invalidate):
  24. """ This function should throw an IOError. """
  25. try:
  26. f1(invalidate)
  27. except ZeroDivisionError as exc:
  28. raise IOError("raise 2")
  29. self.assertRaises(IOError, f2, False)
  30. # Now do it again, but so the auto object destruction
  31. # actually fails.
  32. self.assertRaises(IOError, f2, True)
  33. def testCleanup2(self):
  34. # Cause an exception during object destruction.
  35. # The worst this does is cause an ".XXX undetected error (why=3)"
  36. # So avoiding that is the goal
  37. import win32event
  38. h = win32event.CreateEvent(None, 0, 0, None)
  39. # Close the handle underneath the object.
  40. win32api.CloseHandle(int(h))
  41. # Object destructor runs with the implicit close failing
  42. h = None
  43. def testCleanup3(self):
  44. # And again with a class - no __del__
  45. import win32event
  46. class Test:
  47. def __init__(self):
  48. self.h = win32event.CreateEvent(None, 0, 0, None)
  49. win32api.CloseHandle(int(self.h))
  50. t=Test()
  51. t = None
  52. def testCleanupGood(self):
  53. # And check that normal error semantics *do* work.
  54. import win32event
  55. h = win32event.CreateEvent(None, 0, 0, None)
  56. win32api.CloseHandle(int(h))
  57. self.assertRaises(win32api.error, h.Close)
  58. # A following Close is documented as working
  59. h.Close()
  60. def testInvalid(self):
  61. h=pywintypes.HANDLE(-2)
  62. try:
  63. h.Close()
  64. # Ideally, we'd:
  65. # self.assertRaises(win32api.error, h.Close)
  66. # and everywhere markh has tried, that would pass - but not on
  67. # github automation, where the .Close apparently works fine.
  68. # (same for -1. Using 0 appears to work fine everywhere)
  69. # There still seems value in testing it though, so we just accept
  70. # either working or failing.
  71. except win32api.error:
  72. pass
  73. def testOtherHandle(self):
  74. h=pywintypes.HANDLE(1)
  75. h2=pywintypes.HANDLE(h)
  76. self.failUnlessEqual(h, h2)
  77. # but the above doesn't really test everything - we want a way to
  78. # pass the handle directly into PyWinLong_AsVoidPtr. One way to
  79. # to that is to abuse win32api.GetProcAddress() - the 2nd param
  80. # is passed to PyWinLong_AsVoidPtr() if its not a string.
  81. # passing a handle value of '1' should work - there is something
  82. # at that ordinal
  83. win32api.GetProcAddress(sys.dllhandle, h)
  84. def testHandleInDict(self):
  85. h=pywintypes.HANDLE(1)
  86. d = dict(foo=h)
  87. self.failUnlessEqual(d['foo'], h)
  88. def testHandleInDictThenInt(self):
  89. h=pywintypes.HANDLE(1)
  90. d = dict(foo=h)
  91. self.failUnlessEqual(d['foo'], 1)
  92. def testHandleCompareNone(self):
  93. h=pywintypes.HANDLE(1)
  94. self.failIfEqual(h, None)
  95. self.failIfEqual(None, h)
  96. # ensure we use both __eq__ and __ne__ ops
  97. self.failIf(h==None)
  98. self.failUnless(h!=None)
  99. def testHandleCompareInt(self):
  100. h=pywintypes.HANDLE(1)
  101. self.failIfEqual(h, 0)
  102. self.failUnlessEqual(h, 1)
  103. # ensure we use both __eq__ and __ne__ ops
  104. self.failUnless(h==1)
  105. self.failUnless(1==h)
  106. self.failIf(h!=1)
  107. self.failIf(1!=h)
  108. self.failIf(h==0)
  109. self.failIf(0==h)
  110. self.failUnless(h!=0)
  111. self.failUnless(0!=h)
  112. def testHandleNonZero(self):
  113. h=pywintypes.HANDLE(0)
  114. self.failIf(h)
  115. h=pywintypes.HANDLE(1)
  116. self.failUnless(h)
  117. def testLong(self):
  118. # sys.maxint+1 should always be a 'valid' handle, treated as an
  119. # unsigned int, even though it is a long. Although pywin32 should not
  120. # directly create such longs, using struct.unpack() with a P format
  121. # may well return them. eg:
  122. # >>> struct.unpack("P", struct.pack("P", -1))
  123. # (4294967295L,)
  124. try:
  125. big = sys.maxsize
  126. except AttributeError:
  127. big = sys.maxint
  128. pywintypes.HANDLE(big+1)
  129. def testGC(self):
  130. # This used to provoke:
  131. # Fatal Python error: unexpected exception during garbage collection
  132. def make():
  133. h=pywintypes.HANDLE(-2)
  134. c = Cycle(h)
  135. import gc
  136. make()
  137. gc.collect()
  138. def testTypes(self):
  139. self.assertRaises(TypeError, pywintypes.HANDLE, "foo")
  140. self.assertRaises(TypeError, pywintypes.HANDLE, ())
  141. # should be able to get a long!
  142. pywintypes.HANDLE(int2long(0))
  143. if __name__ == '__main__':
  144. unittest.main()