##// END OF EJS Templates
py3: byteify test-lock.py...
Matt Harbison -
r39984:5ee3146c default
parent child Browse files
Show More
@@ -1,296 +1,296 b''
1 from __future__ import absolute_import
1 from __future__ import absolute_import
2
2
3 import copy
3 import copy
4 import errno
4 import errno
5 import os
6 import silenttestrunner
5 import silenttestrunner
7 import tempfile
6 import tempfile
8 import types
7 import types
9 import unittest
8 import unittest
10
9
11 from mercurial import (
10 from mercurial import (
11 encoding,
12 error,
12 error,
13 lock,
13 lock,
14 vfs as vfsmod,
14 vfs as vfsmod,
15 )
15 )
16
16
17 testlockname = 'testlock'
17 testlockname = b'testlock'
18
18
19 # work around http://bugs.python.org/issue1515
19 # work around http://bugs.python.org/issue1515
20 if types.MethodType not in copy._deepcopy_dispatch:
20 if types.MethodType not in copy._deepcopy_dispatch:
21 def _deepcopy_method(x, memo):
21 def _deepcopy_method(x, memo):
22 return type(x)(x.__func__, copy.deepcopy(x.__self__, memo), x.im_class)
22 return type(x)(x.__func__, copy.deepcopy(x.__self__, memo), x.im_class)
23 copy._deepcopy_dispatch[types.MethodType] = _deepcopy_method
23 copy._deepcopy_dispatch[types.MethodType] = _deepcopy_method
24
24
25 class lockwrapper(lock.lock):
25 class lockwrapper(lock.lock):
26 def __init__(self, pidoffset, *args, **kwargs):
26 def __init__(self, pidoffset, *args, **kwargs):
27 # lock.lock.__init__() calls lock(), so the pidoffset assignment needs
27 # lock.lock.__init__() calls lock(), so the pidoffset assignment needs
28 # to be earlier
28 # to be earlier
29 self._pidoffset = pidoffset
29 self._pidoffset = pidoffset
30 super(lockwrapper, self).__init__(*args, **kwargs)
30 super(lockwrapper, self).__init__(*args, **kwargs)
31 def _getpid(self):
31 def _getpid(self):
32 return super(lockwrapper, self)._getpid() + self._pidoffset
32 return super(lockwrapper, self)._getpid() + self._pidoffset
33
33
34 class teststate(object):
34 class teststate(object):
35 def __init__(self, testcase, dir, pidoffset=0):
35 def __init__(self, testcase, dir, pidoffset=0):
36 self._testcase = testcase
36 self._testcase = testcase
37 self._acquirecalled = False
37 self._acquirecalled = False
38 self._releasecalled = False
38 self._releasecalled = False
39 self._postreleasecalled = False
39 self._postreleasecalled = False
40 self.vfs = vfsmod.vfs(dir, audit=False)
40 self.vfs = vfsmod.vfs(dir, audit=False)
41 self._pidoffset = pidoffset
41 self._pidoffset = pidoffset
42
42
43 def makelock(self, *args, **kwargs):
43 def makelock(self, *args, **kwargs):
44 l = lockwrapper(self._pidoffset, self.vfs, testlockname,
44 l = lockwrapper(self._pidoffset, self.vfs, testlockname,
45 releasefn=self.releasefn, acquirefn=self.acquirefn,
45 releasefn=self.releasefn, acquirefn=self.acquirefn,
46 *args, **kwargs)
46 *args, **kwargs)
47 l.postrelease.append(self.postreleasefn)
47 l.postrelease.append(self.postreleasefn)
48 return l
48 return l
49
49
50 def acquirefn(self):
50 def acquirefn(self):
51 self._acquirecalled = True
51 self._acquirecalled = True
52
52
53 def releasefn(self):
53 def releasefn(self):
54 self._releasecalled = True
54 self._releasecalled = True
55
55
56 def postreleasefn(self):
56 def postreleasefn(self):
57 self._postreleasecalled = True
57 self._postreleasecalled = True
58
58
59 def assertacquirecalled(self, called):
59 def assertacquirecalled(self, called):
60 self._testcase.assertEqual(
60 self._testcase.assertEqual(
61 self._acquirecalled, called,
61 self._acquirecalled, called,
62 'expected acquire to be %s but was actually %s' % (
62 'expected acquire to be %s but was actually %s' % (
63 self._tocalled(called),
63 self._tocalled(called),
64 self._tocalled(self._acquirecalled),
64 self._tocalled(self._acquirecalled),
65 ))
65 ))
66
66
67 def resetacquirefn(self):
67 def resetacquirefn(self):
68 self._acquirecalled = False
68 self._acquirecalled = False
69
69
70 def assertreleasecalled(self, called):
70 def assertreleasecalled(self, called):
71 self._testcase.assertEqual(
71 self._testcase.assertEqual(
72 self._releasecalled, called,
72 self._releasecalled, called,
73 'expected release to be %s but was actually %s' % (
73 'expected release to be %s but was actually %s' % (
74 self._tocalled(called),
74 self._tocalled(called),
75 self._tocalled(self._releasecalled),
75 self._tocalled(self._releasecalled),
76 ))
76 ))
77
77
78 def assertpostreleasecalled(self, called):
78 def assertpostreleasecalled(self, called):
79 self._testcase.assertEqual(
79 self._testcase.assertEqual(
80 self._postreleasecalled, called,
80 self._postreleasecalled, called,
81 'expected postrelease to be %s but was actually %s' % (
81 'expected postrelease to be %s but was actually %s' % (
82 self._tocalled(called),
82 self._tocalled(called),
83 self._tocalled(self._postreleasecalled),
83 self._tocalled(self._postreleasecalled),
84 ))
84 ))
85
85
86 def assertlockexists(self, exists):
86 def assertlockexists(self, exists):
87 actual = self.vfs.lexists(testlockname)
87 actual = self.vfs.lexists(testlockname)
88 self._testcase.assertEqual(
88 self._testcase.assertEqual(
89 actual, exists,
89 actual, exists,
90 'expected lock to %s but actually did %s' % (
90 'expected lock to %s but actually did %s' % (
91 self._toexists(exists),
91 self._toexists(exists),
92 self._toexists(actual),
92 self._toexists(actual),
93 ))
93 ))
94
94
95 def _tocalled(self, called):
95 def _tocalled(self, called):
96 if called:
96 if called:
97 return 'called'
97 return 'called'
98 else:
98 else:
99 return 'not called'
99 return 'not called'
100
100
101 def _toexists(self, exists):
101 def _toexists(self, exists):
102 if exists:
102 if exists:
103 return 'exist'
103 return 'exist'
104 else:
104 else:
105 return 'not exist'
105 return 'not exist'
106
106
107 class testlock(unittest.TestCase):
107 class testlock(unittest.TestCase):
108 def testlock(self):
108 def testlock(self):
109 state = teststate(self, tempfile.mkdtemp(dir=os.getcwd()))
109 state = teststate(self, tempfile.mkdtemp(dir=encoding.getcwd()))
110 lock = state.makelock()
110 lock = state.makelock()
111 state.assertacquirecalled(True)
111 state.assertacquirecalled(True)
112 lock.release()
112 lock.release()
113 state.assertreleasecalled(True)
113 state.assertreleasecalled(True)
114 state.assertpostreleasecalled(True)
114 state.assertpostreleasecalled(True)
115 state.assertlockexists(False)
115 state.assertlockexists(False)
116
116
117 def testrecursivelock(self):
117 def testrecursivelock(self):
118 state = teststate(self, tempfile.mkdtemp(dir=os.getcwd()))
118 state = teststate(self, tempfile.mkdtemp(dir=encoding.getcwd()))
119 lock = state.makelock()
119 lock = state.makelock()
120 state.assertacquirecalled(True)
120 state.assertacquirecalled(True)
121
121
122 state.resetacquirefn()
122 state.resetacquirefn()
123 lock.lock()
123 lock.lock()
124 # recursive lock should not call acquirefn again
124 # recursive lock should not call acquirefn again
125 state.assertacquirecalled(False)
125 state.assertacquirecalled(False)
126
126
127 lock.release() # brings lock refcount down from 2 to 1
127 lock.release() # brings lock refcount down from 2 to 1
128 state.assertreleasecalled(False)
128 state.assertreleasecalled(False)
129 state.assertpostreleasecalled(False)
129 state.assertpostreleasecalled(False)
130 state.assertlockexists(True)
130 state.assertlockexists(True)
131
131
132 lock.release() # releases the lock
132 lock.release() # releases the lock
133 state.assertreleasecalled(True)
133 state.assertreleasecalled(True)
134 state.assertpostreleasecalled(True)
134 state.assertpostreleasecalled(True)
135 state.assertlockexists(False)
135 state.assertlockexists(False)
136
136
137 def testlockfork(self):
137 def testlockfork(self):
138 state = teststate(self, tempfile.mkdtemp(dir=os.getcwd()))
138 state = teststate(self, tempfile.mkdtemp(dir=encoding.getcwd()))
139 lock = state.makelock()
139 lock = state.makelock()
140 state.assertacquirecalled(True)
140 state.assertacquirecalled(True)
141
141
142 # fake a fork
142 # fake a fork
143 forklock = copy.deepcopy(lock)
143 forklock = copy.deepcopy(lock)
144 forklock._pidoffset = 1
144 forklock._pidoffset = 1
145 forklock.release()
145 forklock.release()
146 state.assertreleasecalled(False)
146 state.assertreleasecalled(False)
147 state.assertpostreleasecalled(False)
147 state.assertpostreleasecalled(False)
148 state.assertlockexists(True)
148 state.assertlockexists(True)
149
149
150 # release the actual lock
150 # release the actual lock
151 lock.release()
151 lock.release()
152 state.assertreleasecalled(True)
152 state.assertreleasecalled(True)
153 state.assertpostreleasecalled(True)
153 state.assertpostreleasecalled(True)
154 state.assertlockexists(False)
154 state.assertlockexists(False)
155
155
156 def testinheritlock(self):
156 def testinheritlock(self):
157 d = tempfile.mkdtemp(dir=os.getcwd())
157 d = tempfile.mkdtemp(dir=encoding.getcwd())
158 parentstate = teststate(self, d)
158 parentstate = teststate(self, d)
159 parentlock = parentstate.makelock()
159 parentlock = parentstate.makelock()
160 parentstate.assertacquirecalled(True)
160 parentstate.assertacquirecalled(True)
161
161
162 # set up lock inheritance
162 # set up lock inheritance
163 with parentlock.inherit() as lockname:
163 with parentlock.inherit() as lockname:
164 parentstate.assertreleasecalled(True)
164 parentstate.assertreleasecalled(True)
165 parentstate.assertpostreleasecalled(False)
165 parentstate.assertpostreleasecalled(False)
166 parentstate.assertlockexists(True)
166 parentstate.assertlockexists(True)
167
167
168 childstate = teststate(self, d, pidoffset=1)
168 childstate = teststate(self, d, pidoffset=1)
169 childlock = childstate.makelock(parentlock=lockname)
169 childlock = childstate.makelock(parentlock=lockname)
170 childstate.assertacquirecalled(True)
170 childstate.assertacquirecalled(True)
171
171
172 childlock.release()
172 childlock.release()
173 childstate.assertreleasecalled(True)
173 childstate.assertreleasecalled(True)
174 childstate.assertpostreleasecalled(False)
174 childstate.assertpostreleasecalled(False)
175 childstate.assertlockexists(True)
175 childstate.assertlockexists(True)
176
176
177 parentstate.resetacquirefn()
177 parentstate.resetacquirefn()
178
178
179 parentstate.assertacquirecalled(True)
179 parentstate.assertacquirecalled(True)
180
180
181 parentlock.release()
181 parentlock.release()
182 parentstate.assertreleasecalled(True)
182 parentstate.assertreleasecalled(True)
183 parentstate.assertpostreleasecalled(True)
183 parentstate.assertpostreleasecalled(True)
184 parentstate.assertlockexists(False)
184 parentstate.assertlockexists(False)
185
185
186 def testmultilock(self):
186 def testmultilock(self):
187 d = tempfile.mkdtemp(dir=os.getcwd())
187 d = tempfile.mkdtemp(dir=encoding.getcwd())
188 state0 = teststate(self, d)
188 state0 = teststate(self, d)
189 lock0 = state0.makelock()
189 lock0 = state0.makelock()
190 state0.assertacquirecalled(True)
190 state0.assertacquirecalled(True)
191
191
192 with lock0.inherit() as lock0name:
192 with lock0.inherit() as lock0name:
193 state0.assertreleasecalled(True)
193 state0.assertreleasecalled(True)
194 state0.assertpostreleasecalled(False)
194 state0.assertpostreleasecalled(False)
195 state0.assertlockexists(True)
195 state0.assertlockexists(True)
196
196
197 state1 = teststate(self, d, pidoffset=1)
197 state1 = teststate(self, d, pidoffset=1)
198 lock1 = state1.makelock(parentlock=lock0name)
198 lock1 = state1.makelock(parentlock=lock0name)
199 state1.assertacquirecalled(True)
199 state1.assertacquirecalled(True)
200
200
201 # from within lock1, acquire another lock
201 # from within lock1, acquire another lock
202 with lock1.inherit() as lock1name:
202 with lock1.inherit() as lock1name:
203 # since the file on disk is lock0's this should have the same
203 # since the file on disk is lock0's this should have the same
204 # name
204 # name
205 self.assertEqual(lock0name, lock1name)
205 self.assertEqual(lock0name, lock1name)
206
206
207 state2 = teststate(self, d, pidoffset=2)
207 state2 = teststate(self, d, pidoffset=2)
208 lock2 = state2.makelock(parentlock=lock1name)
208 lock2 = state2.makelock(parentlock=lock1name)
209 state2.assertacquirecalled(True)
209 state2.assertacquirecalled(True)
210
210
211 lock2.release()
211 lock2.release()
212 state2.assertreleasecalled(True)
212 state2.assertreleasecalled(True)
213 state2.assertpostreleasecalled(False)
213 state2.assertpostreleasecalled(False)
214 state2.assertlockexists(True)
214 state2.assertlockexists(True)
215
215
216 state1.resetacquirefn()
216 state1.resetacquirefn()
217
217
218 state1.assertacquirecalled(True)
218 state1.assertacquirecalled(True)
219
219
220 lock1.release()
220 lock1.release()
221 state1.assertreleasecalled(True)
221 state1.assertreleasecalled(True)
222 state1.assertpostreleasecalled(False)
222 state1.assertpostreleasecalled(False)
223 state1.assertlockexists(True)
223 state1.assertlockexists(True)
224
224
225 lock0.release()
225 lock0.release()
226
226
227 def testinheritlockfork(self):
227 def testinheritlockfork(self):
228 d = tempfile.mkdtemp(dir=os.getcwd())
228 d = tempfile.mkdtemp(dir=encoding.getcwd())
229 parentstate = teststate(self, d)
229 parentstate = teststate(self, d)
230 parentlock = parentstate.makelock()
230 parentlock = parentstate.makelock()
231 parentstate.assertacquirecalled(True)
231 parentstate.assertacquirecalled(True)
232
232
233 # set up lock inheritance
233 # set up lock inheritance
234 with parentlock.inherit() as lockname:
234 with parentlock.inherit() as lockname:
235 childstate = teststate(self, d, pidoffset=1)
235 childstate = teststate(self, d, pidoffset=1)
236 childlock = childstate.makelock(parentlock=lockname)
236 childlock = childstate.makelock(parentlock=lockname)
237 childstate.assertacquirecalled(True)
237 childstate.assertacquirecalled(True)
238
238
239 # fork the child lock
239 # fork the child lock
240 forkchildlock = copy.deepcopy(childlock)
240 forkchildlock = copy.deepcopy(childlock)
241 forkchildlock._pidoffset += 1
241 forkchildlock._pidoffset += 1
242 forkchildlock.release()
242 forkchildlock.release()
243 childstate.assertreleasecalled(False)
243 childstate.assertreleasecalled(False)
244 childstate.assertpostreleasecalled(False)
244 childstate.assertpostreleasecalled(False)
245 childstate.assertlockexists(True)
245 childstate.assertlockexists(True)
246
246
247 # release the child lock
247 # release the child lock
248 childlock.release()
248 childlock.release()
249 childstate.assertreleasecalled(True)
249 childstate.assertreleasecalled(True)
250 childstate.assertpostreleasecalled(False)
250 childstate.assertpostreleasecalled(False)
251 childstate.assertlockexists(True)
251 childstate.assertlockexists(True)
252
252
253 parentlock.release()
253 parentlock.release()
254
254
255 def testinheritcheck(self):
255 def testinheritcheck(self):
256 d = tempfile.mkdtemp(dir=os.getcwd())
256 d = tempfile.mkdtemp(dir=encoding.getcwd())
257 state = teststate(self, d)
257 state = teststate(self, d)
258 def check():
258 def check():
259 raise error.LockInheritanceContractViolation('check failed')
259 raise error.LockInheritanceContractViolation('check failed')
260 lock = state.makelock(inheritchecker=check)
260 lock = state.makelock(inheritchecker=check)
261 state.assertacquirecalled(True)
261 state.assertacquirecalled(True)
262
262
263 with self.assertRaises(error.LockInheritanceContractViolation):
263 with self.assertRaises(error.LockInheritanceContractViolation):
264 with lock.inherit():
264 with lock.inherit():
265 pass
265 pass
266
266
267 lock.release()
267 lock.release()
268
268
269 def testfrequentlockunlock(self):
269 def testfrequentlockunlock(self):
270 """This tests whether lock acquisition fails as expected, even if
270 """This tests whether lock acquisition fails as expected, even if
271 (1) lock can't be acquired (makelock fails by EEXIST), and
271 (1) lock can't be acquired (makelock fails by EEXIST), and
272 (2) locker info can't be read in (readlock fails by ENOENT) while
272 (2) locker info can't be read in (readlock fails by ENOENT) while
273 retrying 5 times.
273 retrying 5 times.
274 """
274 """
275
275
276 d = tempfile.mkdtemp(dir=os.getcwd())
276 d = tempfile.mkdtemp(dir=encoding.getcwd())
277 state = teststate(self, d)
277 state = teststate(self, d)
278
278
279 def emulatefrequentlock(*args):
279 def emulatefrequentlock(*args):
280 raise OSError(errno.EEXIST, "File exists")
280 raise OSError(errno.EEXIST, "File exists")
281 def emulatefrequentunlock(*args):
281 def emulatefrequentunlock(*args):
282 raise OSError(errno.ENOENT, "No such file or directory")
282 raise OSError(errno.ENOENT, "No such file or directory")
283
283
284 state.vfs.makelock = emulatefrequentlock
284 state.vfs.makelock = emulatefrequentlock
285 state.vfs.readlock = emulatefrequentunlock
285 state.vfs.readlock = emulatefrequentunlock
286
286
287 try:
287 try:
288 state.makelock(timeout=0)
288 state.makelock(timeout=0)
289 self.fail("unexpected lock acquisition")
289 self.fail("unexpected lock acquisition")
290 except error.LockHeld as why:
290 except error.LockHeld as why:
291 self.assertTrue(why.errno == errno.ETIMEDOUT)
291 self.assertTrue(why.errno == errno.ETIMEDOUT)
292 self.assertTrue(why.locker == "")
292 self.assertTrue(why.locker == "")
293 state.assertlockexists(False)
293 state.assertlockexists(False)
294
294
295 if __name__ == '__main__':
295 if __name__ == '__main__':
296 silenttestrunner.main(__name__)
296 silenttestrunner.main(__name__)
General Comments 0
You need to be logged in to leave comments. Login now