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