Funktionierender Prototyp des Serious Games zur Vermittlung von Wissen zu Software-Engineering-Arbeitsmodellen.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

handles.py 5.3KB

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