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