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