##// END OF EJS Templates
test-lock.py: fix testing for forks...
Siddharth Agarwal -
r26386:146cccdb default
parent child Browse files
Show More
@@ -1,147 +1,155 b''
1 from __future__ import absolute_import
1 from __future__ import absolute_import
2
2
3 import copy
3 import os
4 import os
4 import silenttestrunner
5 import silenttestrunner
5 import tempfile
6 import tempfile
7 import types
6 import unittest
8 import unittest
7
9
8 from mercurial import (
10 from mercurial import (
9 lock,
11 lock,
10 scmutil,
12 scmutil,
11 )
13 )
12
14
13 testlockname = 'testlock'
15 testlockname = 'testlock'
14
16
17 # work around http://bugs.python.org/issue1515
18 if types.MethodType not in copy._deepcopy_dispatch:
19 def _deepcopy_method(x, memo):
20 return type(x)(x.im_func, copy.deepcopy(x.im_self, memo), x.im_class)
21 copy._deepcopy_dispatch[types.MethodType] = _deepcopy_method
22
15 class lockwrapper(lock.lock):
23 class lockwrapper(lock.lock):
16 def __init__(self, pidoffset, *args, **kwargs):
24 def __init__(self, pidoffset, *args, **kwargs):
17 # lock.lock.__init__() calls lock(), so the pidoffset assignment needs
25 # lock.lock.__init__() calls lock(), so the pidoffset assignment needs
18 # to be earlier
26 # to be earlier
19 self._pidoffset = pidoffset
27 self._pidoffset = pidoffset
20 super(lockwrapper, self).__init__(*args, **kwargs)
28 super(lockwrapper, self).__init__(*args, **kwargs)
21 def _getpid(self):
29 def _getpid(self):
22 return os.getpid() + self._pidoffset
30 return os.getpid() + self._pidoffset
23
31
24 class teststate(object):
32 class teststate(object):
25 def __init__(self, testcase, dir, pidoffset=0):
33 def __init__(self, testcase, dir, pidoffset=0):
26 self._testcase = testcase
34 self._testcase = testcase
27 self._acquirecalled = False
35 self._acquirecalled = False
28 self._releasecalled = False
36 self._releasecalled = False
29 self._postreleasecalled = False
37 self._postreleasecalled = False
30 self.vfs = scmutil.vfs(dir, audit=False)
38 self.vfs = scmutil.vfs(dir, audit=False)
31 self._pidoffset = pidoffset
39 self._pidoffset = pidoffset
32
40
33 def makelock(self, *args, **kwargs):
41 def makelock(self, *args, **kwargs):
34 l = lockwrapper(self._pidoffset, self.vfs, testlockname,
42 l = lockwrapper(self._pidoffset, self.vfs, testlockname,
35 releasefn=self.releasefn, acquirefn=self.acquirefn,
43 releasefn=self.releasefn, acquirefn=self.acquirefn,
36 *args, **kwargs)
44 *args, **kwargs)
37 l.postrelease.append(self.postreleasefn)
45 l.postrelease.append(self.postreleasefn)
38 return l
46 return l
39
47
40 def acquirefn(self):
48 def acquirefn(self):
41 self._acquirecalled = True
49 self._acquirecalled = True
42
50
43 def releasefn(self):
51 def releasefn(self):
44 self._releasecalled = True
52 self._releasecalled = True
45
53
46 def postreleasefn(self):
54 def postreleasefn(self):
47 self._postreleasecalled = True
55 self._postreleasecalled = True
48
56
49 def assertacquirecalled(self, called):
57 def assertacquirecalled(self, called):
50 self._testcase.assertEqual(
58 self._testcase.assertEqual(
51 self._acquirecalled, called,
59 self._acquirecalled, called,
52 'expected acquire to be %s but was actually %s' % (
60 'expected acquire to be %s but was actually %s' % (
53 self._tocalled(called),
61 self._tocalled(called),
54 self._tocalled(self._acquirecalled),
62 self._tocalled(self._acquirecalled),
55 ))
63 ))
56
64
57 def resetacquirefn(self):
65 def resetacquirefn(self):
58 self._acquirecalled = False
66 self._acquirecalled = False
59
67
60 def assertreleasecalled(self, called):
68 def assertreleasecalled(self, called):
61 self._testcase.assertEqual(
69 self._testcase.assertEqual(
62 self._releasecalled, called,
70 self._releasecalled, called,
63 'expected release to be %s but was actually %s' % (
71 'expected release to be %s but was actually %s' % (
64 self._tocalled(called),
72 self._tocalled(called),
65 self._tocalled(self._releasecalled),
73 self._tocalled(self._releasecalled),
66 ))
74 ))
67
75
68 def assertpostreleasecalled(self, called):
76 def assertpostreleasecalled(self, called):
69 self._testcase.assertEqual(
77 self._testcase.assertEqual(
70 self._postreleasecalled, called,
78 self._postreleasecalled, called,
71 'expected postrelease to be %s but was actually %s' % (
79 'expected postrelease to be %s but was actually %s' % (
72 self._tocalled(called),
80 self._tocalled(called),
73 self._tocalled(self._postreleasecalled),
81 self._tocalled(self._postreleasecalled),
74 ))
82 ))
75
83
76 def assertlockexists(self, exists):
84 def assertlockexists(self, exists):
77 actual = self.vfs.lexists(testlockname)
85 actual = self.vfs.lexists(testlockname)
78 self._testcase.assertEqual(
86 self._testcase.assertEqual(
79 actual, exists,
87 actual, exists,
80 'expected lock to %s but actually did %s' % (
88 'expected lock to %s but actually did %s' % (
81 self._toexists(exists),
89 self._toexists(exists),
82 self._toexists(actual),
90 self._toexists(actual),
83 ))
91 ))
84
92
85 def _tocalled(self, called):
93 def _tocalled(self, called):
86 if called:
94 if called:
87 return 'called'
95 return 'called'
88 else:
96 else:
89 return 'not called'
97 return 'not called'
90
98
91 def _toexists(self, exists):
99 def _toexists(self, exists):
92 if exists:
100 if exists:
93 return 'exist'
101 return 'exist'
94 else:
102 else:
95 return 'not exist'
103 return 'not exist'
96
104
97 class testlock(unittest.TestCase):
105 class testlock(unittest.TestCase):
98 def testlock(self):
106 def testlock(self):
99 state = teststate(self, tempfile.mkdtemp(dir=os.getcwd()))
107 state = teststate(self, tempfile.mkdtemp(dir=os.getcwd()))
100 lock = state.makelock()
108 lock = state.makelock()
101 state.assertacquirecalled(True)
109 state.assertacquirecalled(True)
102 lock.release()
110 lock.release()
103 state.assertreleasecalled(True)
111 state.assertreleasecalled(True)
104 state.assertpostreleasecalled(True)
112 state.assertpostreleasecalled(True)
105 state.assertlockexists(False)
113 state.assertlockexists(False)
106
114
107 def testrecursivelock(self):
115 def testrecursivelock(self):
108 state = teststate(self, tempfile.mkdtemp(dir=os.getcwd()))
116 state = teststate(self, tempfile.mkdtemp(dir=os.getcwd()))
109 lock = state.makelock()
117 lock = state.makelock()
110 state.assertacquirecalled(True)
118 state.assertacquirecalled(True)
111
119
112 state.resetacquirefn()
120 state.resetacquirefn()
113 lock.lock()
121 lock.lock()
114 # recursive lock should not call acquirefn again
122 # recursive lock should not call acquirefn again
115 state.assertacquirecalled(False)
123 state.assertacquirecalled(False)
116
124
117 lock.release() # brings lock refcount down from 2 to 1
125 lock.release() # brings lock refcount down from 2 to 1
118 state.assertreleasecalled(False)
126 state.assertreleasecalled(False)
119 state.assertpostreleasecalled(False)
127 state.assertpostreleasecalled(False)
120 state.assertlockexists(True)
128 state.assertlockexists(True)
121
129
122 lock.release() # releases the lock
130 lock.release() # releases the lock
123 state.assertreleasecalled(True)
131 state.assertreleasecalled(True)
124 state.assertpostreleasecalled(True)
132 state.assertpostreleasecalled(True)
125 state.assertlockexists(False)
133 state.assertlockexists(False)
126
134
127 def testlockfork(self):
135 def testlockfork(self):
128 state = teststate(self, tempfile.mkdtemp(dir=os.getcwd()))
136 state = teststate(self, tempfile.mkdtemp(dir=os.getcwd()))
129 lock = state.makelock()
137 lock = state.makelock()
130 state.assertacquirecalled(True)
138 state.assertacquirecalled(True)
131 lock.lock()
139
132 # fake a fork
140 # fake a fork
133 lock.pid += 1
141 forklock = copy.deepcopy(lock)
134 lock.release()
142 forklock._pidoffset = 1
143 forklock.release()
135 state.assertreleasecalled(False)
144 state.assertreleasecalled(False)
136 state.assertpostreleasecalled(False)
145 state.assertpostreleasecalled(False)
137 state.assertlockexists(True)
146 state.assertlockexists(True)
138
147
139 # release the actual lock
148 # release the actual lock
140 lock.pid -= 1
141 lock.release()
149 lock.release()
142 state.assertreleasecalled(True)
150 state.assertreleasecalled(True)
143 state.assertpostreleasecalled(True)
151 state.assertpostreleasecalled(True)
144 state.assertlockexists(False)
152 state.assertlockexists(False)
145
153
146 if __name__ == '__main__':
154 if __name__ == '__main__':
147 silenttestrunner.main(__name__)
155 silenttestrunner.main(__name__)
General Comments 0
You need to be logged in to leave comments. Login now