Statistics
| Branch: | Tag: | Revision:

root / test / ganeti.locking_unittest.py @ 5e0a6daf

History | View | Annotate | Download (43.7 kB)

1 162c1c1f Guido Trotter
#!/usr/bin/python
2 162c1c1f Guido Trotter
#
3 162c1c1f Guido Trotter
4 162c1c1f Guido Trotter
# Copyright (C) 2006, 2007 Google Inc.
5 162c1c1f Guido Trotter
#
6 162c1c1f Guido Trotter
# This program is free software; you can redistribute it and/or modify
7 162c1c1f Guido Trotter
# it under the terms of the GNU General Public License as published by
8 162c1c1f Guido Trotter
# the Free Software Foundation; either version 2 of the License, or
9 162c1c1f Guido Trotter
# (at your option) any later version.
10 162c1c1f Guido Trotter
#
11 162c1c1f Guido Trotter
# This program is distributed in the hope that it will be useful, but
12 162c1c1f Guido Trotter
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 162c1c1f Guido Trotter
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 162c1c1f Guido Trotter
# General Public License for more details.
15 162c1c1f Guido Trotter
#
16 162c1c1f Guido Trotter
# You should have received a copy of the GNU General Public License
17 162c1c1f Guido Trotter
# along with this program; if not, write to the Free Software
18 162c1c1f Guido Trotter
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 162c1c1f Guido Trotter
# 0.0510-1301, USA.
20 162c1c1f Guido Trotter
21 162c1c1f Guido Trotter
22 162c1c1f Guido Trotter
"""Script for unittesting the locking module"""
23 162c1c1f Guido Trotter
24 162c1c1f Guido Trotter
25 162c1c1f Guido Trotter
import os
26 162c1c1f Guido Trotter
import unittest
27 162c1c1f Guido Trotter
import time
28 162c1c1f Guido Trotter
import Queue
29 84e344d4 Michael Hanselmann
import threading
30 162c1c1f Guido Trotter
31 162c1c1f Guido Trotter
from ganeti import locking
32 a95fd5d7 Guido Trotter
from ganeti import errors
33 162c1c1f Guido Trotter
34 162c1c1f Guido Trotter
35 42a999d1 Guido Trotter
# This is used to test the ssynchronize decorator.
36 42a999d1 Guido Trotter
# Since it's passed as input to a decorator it must be declared as a global.
37 42a999d1 Guido Trotter
_decoratorlock = locking.SharedLock()
38 42a999d1 Guido Trotter
39 4607c978 Iustin Pop
#: List for looping tests
40 4607c978 Iustin Pop
ITERATIONS = range(8)
41 4607c978 Iustin Pop
42 84e344d4 Michael Hanselmann
43 4607c978 Iustin Pop
def _Repeat(fn):
44 4607c978 Iustin Pop
  """Decorator for executing a function many times"""
45 4607c978 Iustin Pop
  def wrapper(*args, **kwargs):
46 4607c978 Iustin Pop
    for i in ITERATIONS:
47 4607c978 Iustin Pop
      fn(*args, **kwargs)
48 4607c978 Iustin Pop
  return wrapper
49 4607c978 Iustin Pop
50 84e344d4 Michael Hanselmann
51 4607c978 Iustin Pop
class _ThreadedTestCase(unittest.TestCase):
52 4607c978 Iustin Pop
  """Test class that supports adding/waiting on threads"""
53 4607c978 Iustin Pop
  def setUp(self):
54 4607c978 Iustin Pop
    unittest.TestCase.setUp(self)
55 4607c978 Iustin Pop
    self.threads = []
56 4607c978 Iustin Pop
57 4607c978 Iustin Pop
  def _addThread(self, *args, **kwargs):
58 4607c978 Iustin Pop
    """Create and remember a new thread"""
59 84e344d4 Michael Hanselmann
    t = threading.Thread(*args, **kwargs)
60 4607c978 Iustin Pop
    self.threads.append(t)
61 4607c978 Iustin Pop
    t.start()
62 4607c978 Iustin Pop
    return t
63 4607c978 Iustin Pop
64 4607c978 Iustin Pop
  def _waitThreads(self):
65 4607c978 Iustin Pop
    """Wait for all our threads to finish"""
66 4607c978 Iustin Pop
    for t in self.threads:
67 4607c978 Iustin Pop
      t.join(60)
68 4607c978 Iustin Pop
      self.failIf(t.isAlive())
69 4607c978 Iustin Pop
    self.threads = []
70 42a999d1 Guido Trotter
71 4607c978 Iustin Pop
72 48dabc6a Michael Hanselmann
class TestPipeCondition(_ThreadedTestCase):
73 48dabc6a Michael Hanselmann
  """_PipeCondition tests"""
74 48dabc6a Michael Hanselmann
75 48dabc6a Michael Hanselmann
  def setUp(self):
76 48dabc6a Michael Hanselmann
    _ThreadedTestCase.setUp(self)
77 48dabc6a Michael Hanselmann
    self.lock = threading.Lock()
78 48dabc6a Michael Hanselmann
    self.cond = locking._PipeCondition(self.lock)
79 48dabc6a Michael Hanselmann
    self.done = Queue.Queue(0)
80 48dabc6a Michael Hanselmann
81 48dabc6a Michael Hanselmann
  def testAcquireRelease(self):
82 48dabc6a Michael Hanselmann
    self.assert_(not self.cond._is_owned())
83 48dabc6a Michael Hanselmann
    self.assertRaises(RuntimeError, self.cond.wait)
84 48dabc6a Michael Hanselmann
    self.assertRaises(RuntimeError, self.cond.notifyAll)
85 48dabc6a Michael Hanselmann
86 48dabc6a Michael Hanselmann
    self.cond.acquire()
87 48dabc6a Michael Hanselmann
    self.assert_(self.cond._is_owned())
88 48dabc6a Michael Hanselmann
    self.cond.notifyAll()
89 48dabc6a Michael Hanselmann
    self.assert_(self.cond._is_owned())
90 48dabc6a Michael Hanselmann
    self.cond.release()
91 48dabc6a Michael Hanselmann
92 48dabc6a Michael Hanselmann
    self.assert_(not self.cond._is_owned())
93 48dabc6a Michael Hanselmann
    self.assertRaises(RuntimeError, self.cond.wait)
94 48dabc6a Michael Hanselmann
    self.assertRaises(RuntimeError, self.cond.notifyAll)
95 48dabc6a Michael Hanselmann
96 48dabc6a Michael Hanselmann
  def testNotification(self):
97 48dabc6a Michael Hanselmann
    def _NotifyAll():
98 48dabc6a Michael Hanselmann
      self.cond.acquire()
99 48dabc6a Michael Hanselmann
      self.cond.notifyAll()
100 48dabc6a Michael Hanselmann
      self.cond.release()
101 48dabc6a Michael Hanselmann
102 48dabc6a Michael Hanselmann
    self.cond.acquire()
103 48dabc6a Michael Hanselmann
    self._addThread(target=_NotifyAll)
104 48dabc6a Michael Hanselmann
    self.cond.wait()
105 48dabc6a Michael Hanselmann
    self.assert_(self.cond._is_owned())
106 48dabc6a Michael Hanselmann
    self.cond.release()
107 48dabc6a Michael Hanselmann
    self.assert_(not self.cond._is_owned())
108 48dabc6a Michael Hanselmann
109 48dabc6a Michael Hanselmann
  def _TestWait(self, fn):
110 48dabc6a Michael Hanselmann
    self._addThread(target=fn)
111 48dabc6a Michael Hanselmann
    self._addThread(target=fn)
112 48dabc6a Michael Hanselmann
    self._addThread(target=fn)
113 48dabc6a Michael Hanselmann
114 48dabc6a Michael Hanselmann
    # Wait for threads to be waiting
115 48dabc6a Michael Hanselmann
    self.assertEqual(self.done.get(True, 1), "A")
116 48dabc6a Michael Hanselmann
    self.assertEqual(self.done.get(True, 1), "A")
117 48dabc6a Michael Hanselmann
    self.assertEqual(self.done.get(True, 1), "A")
118 48dabc6a Michael Hanselmann
119 48dabc6a Michael Hanselmann
    self.assertRaises(Queue.Empty, self.done.get_nowait)
120 48dabc6a Michael Hanselmann
121 48dabc6a Michael Hanselmann
    self.cond.acquire()
122 48dabc6a Michael Hanselmann
    self.assertEqual(self.cond._nwaiters, 3)
123 48dabc6a Michael Hanselmann
    # This new thread can"t acquire the lock, and thus call wait, before we
124 48dabc6a Michael Hanselmann
    # release it
125 48dabc6a Michael Hanselmann
    self._addThread(target=fn)
126 48dabc6a Michael Hanselmann
    self.cond.notifyAll()
127 48dabc6a Michael Hanselmann
    self.assertRaises(Queue.Empty, self.done.get_nowait)
128 48dabc6a Michael Hanselmann
    self.cond.release()
129 48dabc6a Michael Hanselmann
130 48dabc6a Michael Hanselmann
    # We should now get 3 W and 1 A (for the new thread) in whatever order
131 48dabc6a Michael Hanselmann
    w = 0
132 48dabc6a Michael Hanselmann
    a = 0
133 48dabc6a Michael Hanselmann
    for i in range(4):
134 48dabc6a Michael Hanselmann
      got = self.done.get(True, 1)
135 48dabc6a Michael Hanselmann
      if got == "W":
136 48dabc6a Michael Hanselmann
        w += 1
137 48dabc6a Michael Hanselmann
      elif got == "A":
138 48dabc6a Michael Hanselmann
        a += 1
139 48dabc6a Michael Hanselmann
      else:
140 48dabc6a Michael Hanselmann
        self.fail("Got %s on the done queue" % got)
141 48dabc6a Michael Hanselmann
142 48dabc6a Michael Hanselmann
    self.assertEqual(w, 3)
143 48dabc6a Michael Hanselmann
    self.assertEqual(a, 1)
144 48dabc6a Michael Hanselmann
145 48dabc6a Michael Hanselmann
    self.cond.acquire()
146 48dabc6a Michael Hanselmann
    self.cond.notifyAll()
147 48dabc6a Michael Hanselmann
    self.cond.release()
148 48dabc6a Michael Hanselmann
    self._waitThreads()
149 48dabc6a Michael Hanselmann
    self.assertEqual(self.done.get_nowait(), "W")
150 48dabc6a Michael Hanselmann
    self.assertRaises(Queue.Empty, self.done.get_nowait)
151 48dabc6a Michael Hanselmann
152 48dabc6a Michael Hanselmann
  def testBlockingWait(self):
153 48dabc6a Michael Hanselmann
    def _BlockingWait():
154 48dabc6a Michael Hanselmann
      self.cond.acquire()
155 48dabc6a Michael Hanselmann
      self.done.put("A")
156 48dabc6a Michael Hanselmann
      self.cond.wait()
157 48dabc6a Michael Hanselmann
      self.cond.release()
158 48dabc6a Michael Hanselmann
      self.done.put("W")
159 48dabc6a Michael Hanselmann
160 48dabc6a Michael Hanselmann
    self._TestWait(_BlockingWait)
161 48dabc6a Michael Hanselmann
162 48dabc6a Michael Hanselmann
  def testLongTimeoutWait(self):
163 48dabc6a Michael Hanselmann
    def _Helper():
164 48dabc6a Michael Hanselmann
      self.cond.acquire()
165 48dabc6a Michael Hanselmann
      self.done.put("A")
166 48dabc6a Michael Hanselmann
      self.cond.wait(15.0)
167 48dabc6a Michael Hanselmann
      self.cond.release()
168 48dabc6a Michael Hanselmann
      self.done.put("W")
169 48dabc6a Michael Hanselmann
170 48dabc6a Michael Hanselmann
    self._TestWait(_Helper)
171 48dabc6a Michael Hanselmann
172 48dabc6a Michael Hanselmann
  def _TimeoutWait(self, timeout, check):
173 48dabc6a Michael Hanselmann
    self.cond.acquire()
174 48dabc6a Michael Hanselmann
    self.cond.wait(timeout)
175 48dabc6a Michael Hanselmann
    self.cond.release()
176 48dabc6a Michael Hanselmann
    self.done.put(check)
177 48dabc6a Michael Hanselmann
178 48dabc6a Michael Hanselmann
  def testShortTimeoutWait(self):
179 48dabc6a Michael Hanselmann
    self._addThread(target=self._TimeoutWait, args=(0.1, "T1"))
180 48dabc6a Michael Hanselmann
    self._addThread(target=self._TimeoutWait, args=(0.1, "T1"))
181 48dabc6a Michael Hanselmann
    self._waitThreads()
182 48dabc6a Michael Hanselmann
    self.assertEqual(self.done.get_nowait(), "T1")
183 48dabc6a Michael Hanselmann
    self.assertEqual(self.done.get_nowait(), "T1")
184 48dabc6a Michael Hanselmann
    self.assertRaises(Queue.Empty, self.done.get_nowait)
185 48dabc6a Michael Hanselmann
186 48dabc6a Michael Hanselmann
  def testZeroTimeoutWait(self):
187 48dabc6a Michael Hanselmann
    self._addThread(target=self._TimeoutWait, args=(0, "T0"))
188 48dabc6a Michael Hanselmann
    self._addThread(target=self._TimeoutWait, args=(0, "T0"))
189 48dabc6a Michael Hanselmann
    self._addThread(target=self._TimeoutWait, args=(0, "T0"))
190 48dabc6a Michael Hanselmann
    self._waitThreads()
191 48dabc6a Michael Hanselmann
    self.assertEqual(self.done.get_nowait(), "T0")
192 48dabc6a Michael Hanselmann
    self.assertEqual(self.done.get_nowait(), "T0")
193 48dabc6a Michael Hanselmann
    self.assertEqual(self.done.get_nowait(), "T0")
194 48dabc6a Michael Hanselmann
    self.assertRaises(Queue.Empty, self.done.get_nowait)
195 48dabc6a Michael Hanselmann
196 48dabc6a Michael Hanselmann
197 d76167a5 Michael Hanselmann
class TestSingleActionPipeCondition(unittest.TestCase):
198 d76167a5 Michael Hanselmann
  """_SingleActionPipeCondition tests"""
199 d76167a5 Michael Hanselmann
200 d76167a5 Michael Hanselmann
  def setUp(self):
201 d76167a5 Michael Hanselmann
    self.cond = locking._SingleActionPipeCondition()
202 d76167a5 Michael Hanselmann
203 d76167a5 Michael Hanselmann
  def testInitialization(self):
204 d76167a5 Michael Hanselmann
    self.assert_(self.cond._read_fd is not None)
205 d76167a5 Michael Hanselmann
    self.assert_(self.cond._write_fd is not None)
206 d76167a5 Michael Hanselmann
    self.assert_(self.cond._poller is not None)
207 d76167a5 Michael Hanselmann
    self.assertEqual(self.cond._nwaiters, 0)
208 d76167a5 Michael Hanselmann
209 d76167a5 Michael Hanselmann
  def testUsageCount(self):
210 d76167a5 Michael Hanselmann
    self.cond.StartWaiting()
211 d76167a5 Michael Hanselmann
    self.assert_(self.cond._read_fd is not None)
212 d76167a5 Michael Hanselmann
    self.assert_(self.cond._write_fd is not None)
213 d76167a5 Michael Hanselmann
    self.assert_(self.cond._poller is not None)
214 d76167a5 Michael Hanselmann
    self.assertEqual(self.cond._nwaiters, 1)
215 d76167a5 Michael Hanselmann
216 d76167a5 Michael Hanselmann
    # use again
217 d76167a5 Michael Hanselmann
    self.cond.StartWaiting()
218 d76167a5 Michael Hanselmann
    self.assertEqual(self.cond._nwaiters, 2)
219 d76167a5 Michael Hanselmann
220 d76167a5 Michael Hanselmann
    # there is more than one user
221 d76167a5 Michael Hanselmann
    self.assert_(not self.cond.DoneWaiting())
222 d76167a5 Michael Hanselmann
    self.assert_(self.cond._read_fd is not None)
223 d76167a5 Michael Hanselmann
    self.assert_(self.cond._write_fd is not None)
224 d76167a5 Michael Hanselmann
    self.assert_(self.cond._poller is not None)
225 d76167a5 Michael Hanselmann
    self.assertEqual(self.cond._nwaiters, 1)
226 d76167a5 Michael Hanselmann
227 d76167a5 Michael Hanselmann
    self.assert_(self.cond.DoneWaiting())
228 d76167a5 Michael Hanselmann
    self.assertEqual(self.cond._nwaiters, 0)
229 d76167a5 Michael Hanselmann
    self.assert_(self.cond._read_fd is None)
230 d76167a5 Michael Hanselmann
    self.assert_(self.cond._write_fd is None)
231 d76167a5 Michael Hanselmann
    self.assert_(self.cond._poller is None)
232 d76167a5 Michael Hanselmann
233 d76167a5 Michael Hanselmann
  def testNotify(self):
234 d76167a5 Michael Hanselmann
    wait1 = self.cond.StartWaiting()
235 d76167a5 Michael Hanselmann
    wait2 = self.cond.StartWaiting()
236 d76167a5 Michael Hanselmann
237 d76167a5 Michael Hanselmann
    self.assert_(self.cond._read_fd is not None)
238 d76167a5 Michael Hanselmann
    self.assert_(self.cond._write_fd is not None)
239 d76167a5 Michael Hanselmann
    self.assert_(self.cond._poller is not None)
240 d76167a5 Michael Hanselmann
241 d76167a5 Michael Hanselmann
    self.cond.notifyAll()
242 d76167a5 Michael Hanselmann
243 d76167a5 Michael Hanselmann
    self.assert_(self.cond._read_fd is not None)
244 d76167a5 Michael Hanselmann
    self.assert_(self.cond._write_fd is None)
245 d76167a5 Michael Hanselmann
    self.assert_(self.cond._poller is not None)
246 d76167a5 Michael Hanselmann
247 d76167a5 Michael Hanselmann
    self.assert_(not self.cond.DoneWaiting())
248 d76167a5 Michael Hanselmann
249 d76167a5 Michael Hanselmann
    self.assert_(self.cond._read_fd is not None)
250 d76167a5 Michael Hanselmann
    self.assert_(self.cond._write_fd is None)
251 d76167a5 Michael Hanselmann
    self.assert_(self.cond._poller is not None)
252 d76167a5 Michael Hanselmann
253 d76167a5 Michael Hanselmann
    self.assert_(self.cond.DoneWaiting())
254 d76167a5 Michael Hanselmann
255 d76167a5 Michael Hanselmann
    self.assert_(self.cond._read_fd is None)
256 d76167a5 Michael Hanselmann
    self.assert_(self.cond._write_fd is None)
257 d76167a5 Michael Hanselmann
    self.assert_(self.cond._poller is None)
258 d76167a5 Michael Hanselmann
259 d76167a5 Michael Hanselmann
  def testReusage(self):
260 d76167a5 Michael Hanselmann
    self.cond.StartWaiting()
261 d76167a5 Michael Hanselmann
    self.assert_(self.cond._read_fd is not None)
262 d76167a5 Michael Hanselmann
    self.assert_(self.cond._write_fd is not None)
263 d76167a5 Michael Hanselmann
    self.assert_(self.cond._poller is not None)
264 d76167a5 Michael Hanselmann
265 d76167a5 Michael Hanselmann
    self.assert_(self.cond.DoneWaiting())
266 d76167a5 Michael Hanselmann
267 d76167a5 Michael Hanselmann
    self.assertRaises(RuntimeError, self.cond.StartWaiting)
268 d76167a5 Michael Hanselmann
    self.assert_(self.cond._read_fd is None)
269 d76167a5 Michael Hanselmann
    self.assert_(self.cond._write_fd is None)
270 d76167a5 Michael Hanselmann
    self.assert_(self.cond._poller is None)
271 d76167a5 Michael Hanselmann
272 d76167a5 Michael Hanselmann
  def testNotifyTwice(self):
273 d76167a5 Michael Hanselmann
    self.cond.notifyAll()
274 d76167a5 Michael Hanselmann
    self.assertRaises(RuntimeError, self.cond.notifyAll)
275 d76167a5 Michael Hanselmann
276 d76167a5 Michael Hanselmann
277 4607c978 Iustin Pop
class TestSharedLock(_ThreadedTestCase):
278 d6646186 Guido Trotter
  """SharedLock tests"""
279 162c1c1f Guido Trotter
280 162c1c1f Guido Trotter
  def setUp(self):
281 4607c978 Iustin Pop
    _ThreadedTestCase.setUp(self)
282 162c1c1f Guido Trotter
    self.sl = locking.SharedLock()
283 162c1c1f Guido Trotter
    # helper threads use the 'done' queue to tell the master they finished.
284 162c1c1f Guido Trotter
    self.done = Queue.Queue(0)
285 162c1c1f Guido Trotter
286 162c1c1f Guido Trotter
  def testSequenceAndOwnership(self):
287 162c1c1f Guido Trotter
    self.assert_(not self.sl._is_owned())
288 162c1c1f Guido Trotter
    self.sl.acquire(shared=1)
289 162c1c1f Guido Trotter
    self.assert_(self.sl._is_owned())
290 162c1c1f Guido Trotter
    self.assert_(self.sl._is_owned(shared=1))
291 162c1c1f Guido Trotter
    self.assert_(not self.sl._is_owned(shared=0))
292 162c1c1f Guido Trotter
    self.sl.release()
293 162c1c1f Guido Trotter
    self.assert_(not self.sl._is_owned())
294 162c1c1f Guido Trotter
    self.sl.acquire()
295 162c1c1f Guido Trotter
    self.assert_(self.sl._is_owned())
296 162c1c1f Guido Trotter
    self.assert_(not self.sl._is_owned(shared=1))
297 162c1c1f Guido Trotter
    self.assert_(self.sl._is_owned(shared=0))
298 162c1c1f Guido Trotter
    self.sl.release()
299 162c1c1f Guido Trotter
    self.assert_(not self.sl._is_owned())
300 162c1c1f Guido Trotter
    self.sl.acquire(shared=1)
301 162c1c1f Guido Trotter
    self.assert_(self.sl._is_owned())
302 162c1c1f Guido Trotter
    self.assert_(self.sl._is_owned(shared=1))
303 162c1c1f Guido Trotter
    self.assert_(not self.sl._is_owned(shared=0))
304 162c1c1f Guido Trotter
    self.sl.release()
305 162c1c1f Guido Trotter
    self.assert_(not self.sl._is_owned())
306 162c1c1f Guido Trotter
307 162c1c1f Guido Trotter
  def testBooleanValue(self):
308 162c1c1f Guido Trotter
    # semaphores are supposed to return a true value on a successful acquire
309 162c1c1f Guido Trotter
    self.assert_(self.sl.acquire(shared=1))
310 162c1c1f Guido Trotter
    self.sl.release()
311 162c1c1f Guido Trotter
    self.assert_(self.sl.acquire())
312 162c1c1f Guido Trotter
    self.sl.release()
313 162c1c1f Guido Trotter
314 162c1c1f Guido Trotter
  def testDoubleLockingStoE(self):
315 162c1c1f Guido Trotter
    self.sl.acquire(shared=1)
316 162c1c1f Guido Trotter
    self.assertRaises(AssertionError, self.sl.acquire)
317 162c1c1f Guido Trotter
318 162c1c1f Guido Trotter
  def testDoubleLockingEtoS(self):
319 162c1c1f Guido Trotter
    self.sl.acquire()
320 162c1c1f Guido Trotter
    self.assertRaises(AssertionError, self.sl.acquire, shared=1)
321 162c1c1f Guido Trotter
322 162c1c1f Guido Trotter
  def testDoubleLockingStoS(self):
323 162c1c1f Guido Trotter
    self.sl.acquire(shared=1)
324 162c1c1f Guido Trotter
    self.assertRaises(AssertionError, self.sl.acquire, shared=1)
325 162c1c1f Guido Trotter
326 162c1c1f Guido Trotter
  def testDoubleLockingEtoE(self):
327 162c1c1f Guido Trotter
    self.sl.acquire()
328 162c1c1f Guido Trotter
    self.assertRaises(AssertionError, self.sl.acquire)
329 162c1c1f Guido Trotter
330 162c1c1f Guido Trotter
  # helper functions: called in a separate thread they acquire the lock, send
331 162c1c1f Guido Trotter
  # their identifier on the done queue, then release it.
332 162c1c1f Guido Trotter
  def _doItSharer(self):
333 a95fd5d7 Guido Trotter
    try:
334 a95fd5d7 Guido Trotter
      self.sl.acquire(shared=1)
335 a95fd5d7 Guido Trotter
      self.done.put('SHR')
336 a95fd5d7 Guido Trotter
      self.sl.release()
337 a95fd5d7 Guido Trotter
    except errors.LockError:
338 a95fd5d7 Guido Trotter
      self.done.put('ERR')
339 162c1c1f Guido Trotter
340 162c1c1f Guido Trotter
  def _doItExclusive(self):
341 a95fd5d7 Guido Trotter
    try:
342 a95fd5d7 Guido Trotter
      self.sl.acquire()
343 a95fd5d7 Guido Trotter
      self.done.put('EXC')
344 a95fd5d7 Guido Trotter
      self.sl.release()
345 a95fd5d7 Guido Trotter
    except errors.LockError:
346 a95fd5d7 Guido Trotter
      self.done.put('ERR')
347 a95fd5d7 Guido Trotter
348 a95fd5d7 Guido Trotter
  def _doItDelete(self):
349 a95fd5d7 Guido Trotter
    try:
350 4354ab03 Guido Trotter
      self.sl.delete()
351 a95fd5d7 Guido Trotter
      self.done.put('DEL')
352 a95fd5d7 Guido Trotter
    except errors.LockError:
353 a95fd5d7 Guido Trotter
      self.done.put('ERR')
354 162c1c1f Guido Trotter
355 162c1c1f Guido Trotter
  def testSharersCanCoexist(self):
356 162c1c1f Guido Trotter
    self.sl.acquire(shared=1)
357 84e344d4 Michael Hanselmann
    threading.Thread(target=self._doItSharer).start()
358 162c1c1f Guido Trotter
    self.assert_(self.done.get(True, 1))
359 162c1c1f Guido Trotter
    self.sl.release()
360 162c1c1f Guido Trotter
361 4607c978 Iustin Pop
  @_Repeat
362 162c1c1f Guido Trotter
  def testExclusiveBlocksExclusive(self):
363 162c1c1f Guido Trotter
    self.sl.acquire()
364 4607c978 Iustin Pop
    self._addThread(target=self._doItExclusive)
365 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
366 162c1c1f Guido Trotter
    self.sl.release()
367 4607c978 Iustin Pop
    self._waitThreads()
368 4607c978 Iustin Pop
    self.failUnlessEqual(self.done.get_nowait(), 'EXC')
369 162c1c1f Guido Trotter
370 4607c978 Iustin Pop
  @_Repeat
371 a95fd5d7 Guido Trotter
  def testExclusiveBlocksDelete(self):
372 a95fd5d7 Guido Trotter
    self.sl.acquire()
373 4607c978 Iustin Pop
    self._addThread(target=self._doItDelete)
374 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
375 a95fd5d7 Guido Trotter
    self.sl.release()
376 4607c978 Iustin Pop
    self._waitThreads()
377 4607c978 Iustin Pop
    self.failUnlessEqual(self.done.get_nowait(), 'DEL')
378 4607c978 Iustin Pop
    self.sl = locking.SharedLock()
379 a95fd5d7 Guido Trotter
380 4607c978 Iustin Pop
  @_Repeat
381 162c1c1f Guido Trotter
  def testExclusiveBlocksSharer(self):
382 162c1c1f Guido Trotter
    self.sl.acquire()
383 4607c978 Iustin Pop
    self._addThread(target=self._doItSharer)
384 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
385 162c1c1f Guido Trotter
    self.sl.release()
386 4607c978 Iustin Pop
    self._waitThreads()
387 4607c978 Iustin Pop
    self.failUnlessEqual(self.done.get_nowait(), 'SHR')
388 162c1c1f Guido Trotter
389 4607c978 Iustin Pop
  @_Repeat
390 162c1c1f Guido Trotter
  def testSharerBlocksExclusive(self):
391 162c1c1f Guido Trotter
    self.sl.acquire(shared=1)
392 4607c978 Iustin Pop
    self._addThread(target=self._doItExclusive)
393 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
394 162c1c1f Guido Trotter
    self.sl.release()
395 4607c978 Iustin Pop
    self._waitThreads()
396 4607c978 Iustin Pop
    self.failUnlessEqual(self.done.get_nowait(), 'EXC')
397 162c1c1f Guido Trotter
398 4607c978 Iustin Pop
  @_Repeat
399 a95fd5d7 Guido Trotter
  def testSharerBlocksDelete(self):
400 a95fd5d7 Guido Trotter
    self.sl.acquire(shared=1)
401 4607c978 Iustin Pop
    self._addThread(target=self._doItDelete)
402 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
403 a95fd5d7 Guido Trotter
    self.sl.release()
404 4607c978 Iustin Pop
    self._waitThreads()
405 4607c978 Iustin Pop
    self.failUnlessEqual(self.done.get_nowait(), 'DEL')
406 4607c978 Iustin Pop
    self.sl = locking.SharedLock()
407 a95fd5d7 Guido Trotter
408 4607c978 Iustin Pop
  @_Repeat
409 162c1c1f Guido Trotter
  def testWaitingExclusiveBlocksSharer(self):
410 e6416152 Iustin Pop
    """SKIPPED testWaitingExclusiveBlockSharer"""
411 e6416152 Iustin Pop
    return
412 e6416152 Iustin Pop
413 162c1c1f Guido Trotter
    self.sl.acquire(shared=1)
414 162c1c1f Guido Trotter
    # the lock is acquired in shared mode...
415 4607c978 Iustin Pop
    self._addThread(target=self._doItExclusive)
416 162c1c1f Guido Trotter
    # ...but now an exclusive is waiting...
417 4607c978 Iustin Pop
    self._addThread(target=self._doItSharer)
418 162c1c1f Guido Trotter
    # ...so the sharer should be blocked as well
419 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
420 162c1c1f Guido Trotter
    self.sl.release()
421 4607c978 Iustin Pop
    self._waitThreads()
422 162c1c1f Guido Trotter
    # The exclusive passed before
423 4607c978 Iustin Pop
    self.failUnlessEqual(self.done.get_nowait(), 'EXC')
424 4607c978 Iustin Pop
    self.failUnlessEqual(self.done.get_nowait(), 'SHR')
425 162c1c1f Guido Trotter
426 4607c978 Iustin Pop
  @_Repeat
427 162c1c1f Guido Trotter
  def testWaitingSharerBlocksExclusive(self):
428 a143be68 Iustin Pop
    """SKIPPED testWaitingSharerBlocksExclusive"""
429 a143be68 Iustin Pop
    return
430 a143be68 Iustin Pop
431 162c1c1f Guido Trotter
    self.sl.acquire()
432 162c1c1f Guido Trotter
    # the lock is acquired in exclusive mode...
433 4607c978 Iustin Pop
    self._addThread(target=self._doItSharer)
434 162c1c1f Guido Trotter
    # ...but now a sharer is waiting...
435 4607c978 Iustin Pop
    self._addThread(target=self._doItExclusive)
436 162c1c1f Guido Trotter
    # ...the exclusive is waiting too...
437 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
438 162c1c1f Guido Trotter
    self.sl.release()
439 4607c978 Iustin Pop
    self._waitThreads()
440 162c1c1f Guido Trotter
    # The sharer passed before
441 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'SHR')
442 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'EXC')
443 162c1c1f Guido Trotter
444 a95fd5d7 Guido Trotter
  def testDelete(self):
445 a95fd5d7 Guido Trotter
    self.sl.delete()
446 a95fd5d7 Guido Trotter
    self.assertRaises(errors.LockError, self.sl.acquire)
447 84152b96 Guido Trotter
    self.assertRaises(errors.LockError, self.sl.acquire, shared=1)
448 a95fd5d7 Guido Trotter
    self.assertRaises(errors.LockError, self.sl.delete)
449 a95fd5d7 Guido Trotter
450 84152b96 Guido Trotter
  def testNoDeleteIfSharer(self):
451 84152b96 Guido Trotter
    self.sl.acquire(shared=1)
452 84152b96 Guido Trotter
    self.assertRaises(AssertionError, self.sl.delete)
453 84152b96 Guido Trotter
454 4607c978 Iustin Pop
  @_Repeat
455 a95fd5d7 Guido Trotter
  def testDeletePendingSharersExclusiveDelete(self):
456 a95fd5d7 Guido Trotter
    self.sl.acquire()
457 4607c978 Iustin Pop
    self._addThread(target=self._doItSharer)
458 4607c978 Iustin Pop
    self._addThread(target=self._doItSharer)
459 4607c978 Iustin Pop
    self._addThread(target=self._doItExclusive)
460 4607c978 Iustin Pop
    self._addThread(target=self._doItDelete)
461 a95fd5d7 Guido Trotter
    self.sl.delete()
462 4607c978 Iustin Pop
    self._waitThreads()
463 4607c978 Iustin Pop
    # The threads who were pending return ERR
464 4607c978 Iustin Pop
    for _ in range(4):
465 4607c978 Iustin Pop
      self.assertEqual(self.done.get_nowait(), 'ERR')
466 4607c978 Iustin Pop
    self.sl = locking.SharedLock()
467 a95fd5d7 Guido Trotter
468 4607c978 Iustin Pop
  @_Repeat
469 a95fd5d7 Guido Trotter
  def testDeletePendingDeleteExclusiveSharers(self):
470 a95fd5d7 Guido Trotter
    self.sl.acquire()
471 4607c978 Iustin Pop
    self._addThread(target=self._doItDelete)
472 4607c978 Iustin Pop
    self._addThread(target=self._doItExclusive)
473 4607c978 Iustin Pop
    self._addThread(target=self._doItSharer)
474 4607c978 Iustin Pop
    self._addThread(target=self._doItSharer)
475 a95fd5d7 Guido Trotter
    self.sl.delete()
476 4607c978 Iustin Pop
    self._waitThreads()
477 a95fd5d7 Guido Trotter
    # The two threads who were pending return both ERR
478 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'ERR')
479 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'ERR')
480 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'ERR')
481 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'ERR')
482 4607c978 Iustin Pop
    self.sl = locking.SharedLock()
483 a95fd5d7 Guido Trotter
484 84e344d4 Michael Hanselmann
  @_Repeat
485 84e344d4 Michael Hanselmann
  def testExclusiveAcquireTimeout(self):
486 84e344d4 Michael Hanselmann
    def _LockExclusive(wait):
487 84e344d4 Michael Hanselmann
      self.sl.acquire(shared=0)
488 84e344d4 Michael Hanselmann
      self.done.put("A: start sleep")
489 84e344d4 Michael Hanselmann
      time.sleep(wait)
490 84e344d4 Michael Hanselmann
      self.done.put("A: end sleep")
491 84e344d4 Michael Hanselmann
      self.sl.release()
492 84e344d4 Michael Hanselmann
493 84e344d4 Michael Hanselmann
    for shared in [0, 1]:
494 84e344d4 Michael Hanselmann
      # Start thread to hold lock for 20 ms
495 84e344d4 Michael Hanselmann
      self._addThread(target=_LockExclusive, args=(20.0 / 1000.0, ))
496 84e344d4 Michael Hanselmann
497 2042aa94 Michael Hanselmann
      # Wait for sleep to begin
498 2042aa94 Michael Hanselmann
      self.assertEqual(self.done.get(), "A: start sleep")
499 2042aa94 Michael Hanselmann
500 84e344d4 Michael Hanselmann
      # Wait up to 100 ms to get lock
501 84e344d4 Michael Hanselmann
      self.failUnless(self.sl.acquire(shared=shared, timeout=0.1))
502 84e344d4 Michael Hanselmann
      self.done.put("got 2nd")
503 84e344d4 Michael Hanselmann
      self.sl.release()
504 84e344d4 Michael Hanselmann
505 84e344d4 Michael Hanselmann
      self._waitThreads()
506 84e344d4 Michael Hanselmann
507 84e344d4 Michael Hanselmann
      self.assertEqual(self.done.get_nowait(), "A: end sleep")
508 84e344d4 Michael Hanselmann
      self.assertEqual(self.done.get_nowait(), "got 2nd")
509 84e344d4 Michael Hanselmann
      self.assertRaises(Queue.Empty, self.done.get_nowait)
510 84e344d4 Michael Hanselmann
511 84e344d4 Michael Hanselmann
  @_Repeat
512 84e344d4 Michael Hanselmann
  def testAcquireExpiringTimeout(self):
513 84e344d4 Michael Hanselmann
    def _AcquireWithTimeout(shared, timeout):
514 84e344d4 Michael Hanselmann
      if not self.sl.acquire(shared=shared, timeout=timeout):
515 84e344d4 Michael Hanselmann
        self.done.put("timeout")
516 84e344d4 Michael Hanselmann
517 84e344d4 Michael Hanselmann
    for shared in [0, 1]:
518 84e344d4 Michael Hanselmann
      # Lock exclusively
519 84e344d4 Michael Hanselmann
      self.sl.acquire()
520 84e344d4 Michael Hanselmann
521 84e344d4 Michael Hanselmann
      # Start shared acquires with timeout between 0 and 20 ms
522 84e344d4 Michael Hanselmann
      for i in xrange(11):
523 84e344d4 Michael Hanselmann
        self._addThread(target=_AcquireWithTimeout,
524 84e344d4 Michael Hanselmann
                        args=(shared, i * 2.0 / 1000.0))
525 84e344d4 Michael Hanselmann
526 84e344d4 Michael Hanselmann
      # Wait for threads to finish (makes sure the acquire timeout expires
527 84e344d4 Michael Hanselmann
      # before releasing the lock)
528 84e344d4 Michael Hanselmann
      self._waitThreads()
529 84e344d4 Michael Hanselmann
530 84e344d4 Michael Hanselmann
      # Release lock
531 84e344d4 Michael Hanselmann
      self.sl.release()
532 84e344d4 Michael Hanselmann
533 84e344d4 Michael Hanselmann
      for _ in xrange(11):
534 84e344d4 Michael Hanselmann
        self.assertEqual(self.done.get_nowait(), "timeout")
535 84e344d4 Michael Hanselmann
536 84e344d4 Michael Hanselmann
      self.assertRaises(Queue.Empty, self.done.get_nowait)
537 84e344d4 Michael Hanselmann
538 84e344d4 Michael Hanselmann
  @_Repeat
539 84e344d4 Michael Hanselmann
  def testSharedSkipExclusiveAcquires(self):
540 84e344d4 Michael Hanselmann
    # Tests whether shared acquires jump in front of exclusive acquires in the
541 84e344d4 Michael Hanselmann
    # queue.
542 84e344d4 Michael Hanselmann
543 84e344d4 Michael Hanselmann
    # Get exclusive lock while we fill the queue
544 84e344d4 Michael Hanselmann
    self.sl.acquire()
545 84e344d4 Michael Hanselmann
546 84e344d4 Michael Hanselmann
    def _Acquire(shared, name):
547 84e344d4 Michael Hanselmann
      if not self.sl.acquire(shared=shared):
548 84e344d4 Michael Hanselmann
        return
549 84e344d4 Michael Hanselmann
550 84e344d4 Michael Hanselmann
      self.done.put(name)
551 84e344d4 Michael Hanselmann
      self.sl.release()
552 84e344d4 Michael Hanselmann
553 84e344d4 Michael Hanselmann
    # Start shared acquires
554 84e344d4 Michael Hanselmann
    for _ in xrange(5):
555 84e344d4 Michael Hanselmann
      self._addThread(target=_Acquire, args=(1, "shared A"))
556 84e344d4 Michael Hanselmann
557 84e344d4 Michael Hanselmann
    # Start exclusive acquires
558 84e344d4 Michael Hanselmann
    for _ in xrange(3):
559 84e344d4 Michael Hanselmann
      self._addThread(target=_Acquire, args=(0, "exclusive B"))
560 84e344d4 Michael Hanselmann
561 84e344d4 Michael Hanselmann
    # More shared acquires
562 84e344d4 Michael Hanselmann
    for _ in xrange(5):
563 84e344d4 Michael Hanselmann
      self._addThread(target=_Acquire, args=(1, "shared C"))
564 84e344d4 Michael Hanselmann
565 84e344d4 Michael Hanselmann
    # More exclusive acquires
566 84e344d4 Michael Hanselmann
    for _ in xrange(3):
567 84e344d4 Michael Hanselmann
      self._addThread(target=_Acquire, args=(0, "exclusive D"))
568 84e344d4 Michael Hanselmann
569 84e344d4 Michael Hanselmann
    # Expect 6 pending exclusive acquires and 1 for all shared acquires
570 2042aa94 Michael Hanselmann
    # together. There's no way to wait for SharedLock.acquire to start
571 2042aa94 Michael Hanselmann
    # its work. Hence the timeout of 2 seconds.
572 2042aa94 Michael Hanselmann
    pending = 0
573 2042aa94 Michael Hanselmann
    end_time = time.time() + 2.0
574 2042aa94 Michael Hanselmann
    while time.time() < end_time:
575 2042aa94 Michael Hanselmann
      pending = self.sl._count_pending()
576 2042aa94 Michael Hanselmann
      self.assert_(pending >= 0 and pending <= 7)
577 2042aa94 Michael Hanselmann
      if pending == 7:
578 2042aa94 Michael Hanselmann
        break
579 2042aa94 Michael Hanselmann
      time.sleep(0.05)
580 2042aa94 Michael Hanselmann
    self.assertEqual(pending, 7)
581 84e344d4 Michael Hanselmann
582 84e344d4 Michael Hanselmann
    # Release exclusive lock and wait
583 84e344d4 Michael Hanselmann
    self.sl.release()
584 84e344d4 Michael Hanselmann
585 84e344d4 Michael Hanselmann
    self._waitThreads()
586 84e344d4 Michael Hanselmann
587 84e344d4 Michael Hanselmann
    # Check sequence
588 2042aa94 Michael Hanselmann
    shr_a = 0
589 2042aa94 Michael Hanselmann
    shr_c = 0
590 84e344d4 Michael Hanselmann
    for _ in xrange(10):
591 84e344d4 Michael Hanselmann
      # Shared locks aren't guaranteed to be notified in order, but they'll be
592 84e344d4 Michael Hanselmann
      # first
593 2042aa94 Michael Hanselmann
      tmp = self.done.get_nowait()
594 2042aa94 Michael Hanselmann
      if tmp == "shared A":
595 2042aa94 Michael Hanselmann
        shr_a += 1
596 2042aa94 Michael Hanselmann
      elif tmp == "shared C":
597 2042aa94 Michael Hanselmann
        shr_c += 1
598 2042aa94 Michael Hanselmann
    self.assertEqual(shr_a, 5)
599 2042aa94 Michael Hanselmann
    self.assertEqual(shr_c, 5)
600 84e344d4 Michael Hanselmann
601 84e344d4 Michael Hanselmann
    for _ in xrange(3):
602 84e344d4 Michael Hanselmann
      self.assertEqual(self.done.get_nowait(), "exclusive B")
603 84e344d4 Michael Hanselmann
604 84e344d4 Michael Hanselmann
    for _ in xrange(3):
605 84e344d4 Michael Hanselmann
      self.assertEqual(self.done.get_nowait(), "exclusive D")
606 84e344d4 Michael Hanselmann
607 84e344d4 Michael Hanselmann
    self.assertRaises(Queue.Empty, self.done.get_nowait)
608 84e344d4 Michael Hanselmann
609 84e344d4 Michael Hanselmann
  @_Repeat
610 84e344d4 Michael Hanselmann
  def testMixedAcquireTimeout(self):
611 84e344d4 Michael Hanselmann
    sync = threading.Condition()
612 84e344d4 Michael Hanselmann
613 84e344d4 Michael Hanselmann
    def _AcquireShared(ev):
614 84e344d4 Michael Hanselmann
      if not self.sl.acquire(shared=1, timeout=None):
615 84e344d4 Michael Hanselmann
        return
616 84e344d4 Michael Hanselmann
617 84e344d4 Michael Hanselmann
      self.done.put("shared")
618 84e344d4 Michael Hanselmann
619 84e344d4 Michael Hanselmann
      # Notify main thread
620 84e344d4 Michael Hanselmann
      ev.set()
621 84e344d4 Michael Hanselmann
622 84e344d4 Michael Hanselmann
      # Wait for notification
623 84e344d4 Michael Hanselmann
      sync.acquire()
624 84e344d4 Michael Hanselmann
      try:
625 84e344d4 Michael Hanselmann
        sync.wait()
626 84e344d4 Michael Hanselmann
      finally:
627 84e344d4 Michael Hanselmann
        sync.release()
628 84e344d4 Michael Hanselmann
629 84e344d4 Michael Hanselmann
      # Release lock
630 84e344d4 Michael Hanselmann
      self.sl.release()
631 84e344d4 Michael Hanselmann
632 84e344d4 Michael Hanselmann
    acquires = []
633 84e344d4 Michael Hanselmann
    for _ in xrange(3):
634 84e344d4 Michael Hanselmann
      ev = threading.Event()
635 84e344d4 Michael Hanselmann
      self._addThread(target=_AcquireShared, args=(ev, ))
636 84e344d4 Michael Hanselmann
      acquires.append(ev)
637 84e344d4 Michael Hanselmann
638 84e344d4 Michael Hanselmann
    # Wait for all acquires to finish
639 84e344d4 Michael Hanselmann
    for i in acquires:
640 84e344d4 Michael Hanselmann
      i.wait()
641 84e344d4 Michael Hanselmann
642 84e344d4 Michael Hanselmann
    self.assertEqual(self.sl._count_pending(), 0)
643 84e344d4 Michael Hanselmann
644 84e344d4 Michael Hanselmann
    # Try to get exclusive lock
645 84e344d4 Michael Hanselmann
    self.failIf(self.sl.acquire(shared=0, timeout=0.02))
646 84e344d4 Michael Hanselmann
647 84e344d4 Michael Hanselmann
    # Acquire exclusive without timeout
648 84e344d4 Michael Hanselmann
    exclsync = threading.Condition()
649 84e344d4 Michael Hanselmann
    exclev = threading.Event()
650 84e344d4 Michael Hanselmann
651 84e344d4 Michael Hanselmann
    def _AcquireExclusive():
652 84e344d4 Michael Hanselmann
      if not self.sl.acquire(shared=0):
653 84e344d4 Michael Hanselmann
        return
654 84e344d4 Michael Hanselmann
655 84e344d4 Michael Hanselmann
      self.done.put("exclusive")
656 84e344d4 Michael Hanselmann
657 84e344d4 Michael Hanselmann
      # Notify main thread
658 84e344d4 Michael Hanselmann
      exclev.set()
659 84e344d4 Michael Hanselmann
660 84e344d4 Michael Hanselmann
      exclsync.acquire()
661 84e344d4 Michael Hanselmann
      try:
662 84e344d4 Michael Hanselmann
        exclsync.wait()
663 84e344d4 Michael Hanselmann
      finally:
664 84e344d4 Michael Hanselmann
        exclsync.release()
665 84e344d4 Michael Hanselmann
666 84e344d4 Michael Hanselmann
      self.sl.release()
667 84e344d4 Michael Hanselmann
668 84e344d4 Michael Hanselmann
    self._addThread(target=_AcquireExclusive)
669 84e344d4 Michael Hanselmann
670 84e344d4 Michael Hanselmann
    # Try to get exclusive lock
671 84e344d4 Michael Hanselmann
    self.failIf(self.sl.acquire(shared=0, timeout=0.02))
672 84e344d4 Michael Hanselmann
673 84e344d4 Michael Hanselmann
    # Make all shared holders release their locks
674 84e344d4 Michael Hanselmann
    sync.acquire()
675 84e344d4 Michael Hanselmann
    try:
676 84e344d4 Michael Hanselmann
      sync.notifyAll()
677 84e344d4 Michael Hanselmann
    finally:
678 84e344d4 Michael Hanselmann
      sync.release()
679 84e344d4 Michael Hanselmann
680 84e344d4 Michael Hanselmann
    # Wait for exclusive acquire to succeed
681 84e344d4 Michael Hanselmann
    exclev.wait()
682 84e344d4 Michael Hanselmann
683 84e344d4 Michael Hanselmann
    self.assertEqual(self.sl._count_pending(), 0)
684 84e344d4 Michael Hanselmann
685 84e344d4 Michael Hanselmann
    # Try to get exclusive lock
686 84e344d4 Michael Hanselmann
    self.failIf(self.sl.acquire(shared=0, timeout=0.02))
687 84e344d4 Michael Hanselmann
688 84e344d4 Michael Hanselmann
    def _AcquireSharedSimple():
689 84e344d4 Michael Hanselmann
      if self.sl.acquire(shared=1, timeout=None):
690 84e344d4 Michael Hanselmann
        self.done.put("shared2")
691 84e344d4 Michael Hanselmann
        self.sl.release()
692 84e344d4 Michael Hanselmann
693 84e344d4 Michael Hanselmann
    for _ in xrange(10):
694 84e344d4 Michael Hanselmann
      self._addThread(target=_AcquireSharedSimple)
695 84e344d4 Michael Hanselmann
696 84e344d4 Michael Hanselmann
    # Tell exclusive lock to release
697 84e344d4 Michael Hanselmann
    exclsync.acquire()
698 84e344d4 Michael Hanselmann
    try:
699 84e344d4 Michael Hanselmann
      exclsync.notifyAll()
700 84e344d4 Michael Hanselmann
    finally:
701 84e344d4 Michael Hanselmann
      exclsync.release()
702 84e344d4 Michael Hanselmann
703 84e344d4 Michael Hanselmann
    # Wait for everything to finish
704 84e344d4 Michael Hanselmann
    self._waitThreads()
705 84e344d4 Michael Hanselmann
706 84e344d4 Michael Hanselmann
    self.assertEqual(self.sl._count_pending(), 0)
707 84e344d4 Michael Hanselmann
708 84e344d4 Michael Hanselmann
    # Check sequence
709 84e344d4 Michael Hanselmann
    for _ in xrange(3):
710 84e344d4 Michael Hanselmann
      self.assertEqual(self.done.get_nowait(), "shared")
711 84e344d4 Michael Hanselmann
712 84e344d4 Michael Hanselmann
    self.assertEqual(self.done.get_nowait(), "exclusive")
713 84e344d4 Michael Hanselmann
714 84e344d4 Michael Hanselmann
    for _ in xrange(10):
715 84e344d4 Michael Hanselmann
      self.assertEqual(self.done.get_nowait(), "shared2")
716 84e344d4 Michael Hanselmann
717 84e344d4 Michael Hanselmann
    self.assertRaises(Queue.Empty, self.done.get_nowait)
718 84e344d4 Michael Hanselmann
719 162c1c1f Guido Trotter
720 4607c978 Iustin Pop
class TestSSynchronizedDecorator(_ThreadedTestCase):
721 42a999d1 Guido Trotter
  """Shared Lock Synchronized decorator test"""
722 42a999d1 Guido Trotter
723 42a999d1 Guido Trotter
  def setUp(self):
724 4607c978 Iustin Pop
    _ThreadedTestCase.setUp(self)
725 42a999d1 Guido Trotter
    # helper threads use the 'done' queue to tell the master they finished.
726 42a999d1 Guido Trotter
    self.done = Queue.Queue(0)
727 42a999d1 Guido Trotter
728 42a999d1 Guido Trotter
  @locking.ssynchronized(_decoratorlock)
729 42a999d1 Guido Trotter
  def _doItExclusive(self):
730 42a999d1 Guido Trotter
    self.assert_(_decoratorlock._is_owned())
731 42a999d1 Guido Trotter
    self.done.put('EXC')
732 42a999d1 Guido Trotter
733 42a999d1 Guido Trotter
  @locking.ssynchronized(_decoratorlock, shared=1)
734 42a999d1 Guido Trotter
  def _doItSharer(self):
735 42a999d1 Guido Trotter
    self.assert_(_decoratorlock._is_owned(shared=1))
736 42a999d1 Guido Trotter
    self.done.put('SHR')
737 42a999d1 Guido Trotter
738 42a999d1 Guido Trotter
  def testDecoratedFunctions(self):
739 42a999d1 Guido Trotter
    self._doItExclusive()
740 42a999d1 Guido Trotter
    self.assert_(not _decoratorlock._is_owned())
741 42a999d1 Guido Trotter
    self._doItSharer()
742 42a999d1 Guido Trotter
    self.assert_(not _decoratorlock._is_owned())
743 42a999d1 Guido Trotter
744 42a999d1 Guido Trotter
  def testSharersCanCoexist(self):
745 42a999d1 Guido Trotter
    _decoratorlock.acquire(shared=1)
746 84e344d4 Michael Hanselmann
    threading.Thread(target=self._doItSharer).start()
747 42a999d1 Guido Trotter
    self.assert_(self.done.get(True, 1))
748 42a999d1 Guido Trotter
    _decoratorlock.release()
749 42a999d1 Guido Trotter
750 4607c978 Iustin Pop
  @_Repeat
751 42a999d1 Guido Trotter
  def testExclusiveBlocksExclusive(self):
752 42a999d1 Guido Trotter
    _decoratorlock.acquire()
753 4607c978 Iustin Pop
    self._addThread(target=self._doItExclusive)
754 42a999d1 Guido Trotter
    # give it a bit of time to check that it's not actually doing anything
755 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
756 42a999d1 Guido Trotter
    _decoratorlock.release()
757 4607c978 Iustin Pop
    self._waitThreads()
758 4607c978 Iustin Pop
    self.failUnlessEqual(self.done.get_nowait(), 'EXC')
759 42a999d1 Guido Trotter
760 4607c978 Iustin Pop
  @_Repeat
761 42a999d1 Guido Trotter
  def testExclusiveBlocksSharer(self):
762 42a999d1 Guido Trotter
    _decoratorlock.acquire()
763 4607c978 Iustin Pop
    self._addThread(target=self._doItSharer)
764 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
765 42a999d1 Guido Trotter
    _decoratorlock.release()
766 4607c978 Iustin Pop
    self._waitThreads()
767 4607c978 Iustin Pop
    self.failUnlessEqual(self.done.get_nowait(), 'SHR')
768 42a999d1 Guido Trotter
769 4607c978 Iustin Pop
  @_Repeat
770 42a999d1 Guido Trotter
  def testSharerBlocksExclusive(self):
771 42a999d1 Guido Trotter
    _decoratorlock.acquire(shared=1)
772 4607c978 Iustin Pop
    self._addThread(target=self._doItExclusive)
773 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
774 42a999d1 Guido Trotter
    _decoratorlock.release()
775 4607c978 Iustin Pop
    self._waitThreads()
776 4607c978 Iustin Pop
    self.failUnlessEqual(self.done.get_nowait(), 'EXC')
777 42a999d1 Guido Trotter
778 42a999d1 Guido Trotter
779 4607c978 Iustin Pop
class TestLockSet(_ThreadedTestCase):
780 aaae9bc0 Guido Trotter
  """LockSet tests"""
781 aaae9bc0 Guido Trotter
782 aaae9bc0 Guido Trotter
  def setUp(self):
783 4607c978 Iustin Pop
    _ThreadedTestCase.setUp(self)
784 4607c978 Iustin Pop
    self._setUpLS()
785 aaae9bc0 Guido Trotter
    # helper threads use the 'done' queue to tell the master they finished.
786 aaae9bc0 Guido Trotter
    self.done = Queue.Queue(0)
787 aaae9bc0 Guido Trotter
788 4607c978 Iustin Pop
  def _setUpLS(self):
789 4607c978 Iustin Pop
    """Helper to (re)initialize the lock set"""
790 4607c978 Iustin Pop
    self.resources = ['one', 'two', 'three']
791 4607c978 Iustin Pop
    self.ls = locking.LockSet(members=self.resources)
792 4607c978 Iustin Pop
793 aaae9bc0 Guido Trotter
  def testResources(self):
794 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._names(), set(self.resources))
795 aaae9bc0 Guido Trotter
    newls = locking.LockSet()
796 aaae9bc0 Guido Trotter
    self.assertEquals(newls._names(), set())
797 aaae9bc0 Guido Trotter
798 aaae9bc0 Guido Trotter
  def testAcquireRelease(self):
799 0cc00929 Guido Trotter
    self.assert_(self.ls.acquire('one'))
800 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['one']))
801 aaae9bc0 Guido Trotter
    self.ls.release()
802 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set())
803 0cc00929 Guido Trotter
    self.assertEquals(self.ls.acquire(['one']), set(['one']))
804 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['one']))
805 aaae9bc0 Guido Trotter
    self.ls.release()
806 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set())
807 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'two', 'three'])
808 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['one', 'two', 'three']))
809 aaae9bc0 Guido Trotter
    self.ls.release('one')
810 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['two', 'three']))
811 aaae9bc0 Guido Trotter
    self.ls.release(['three'])
812 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['two']))
813 aaae9bc0 Guido Trotter
    self.ls.release()
814 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set())
815 0cc00929 Guido Trotter
    self.assertEquals(self.ls.acquire(['one', 'three']), set(['one', 'three']))
816 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['one', 'three']))
817 aaae9bc0 Guido Trotter
    self.ls.release()
818 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set())
819 aaae9bc0 Guido Trotter
820 aaae9bc0 Guido Trotter
  def testNoDoubleAcquire(self):
821 aaae9bc0 Guido Trotter
    self.ls.acquire('one')
822 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.acquire, 'one')
823 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.acquire, ['two'])
824 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.acquire, ['two', 'three'])
825 aaae9bc0 Guido Trotter
    self.ls.release()
826 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'three'])
827 aaae9bc0 Guido Trotter
    self.ls.release('one')
828 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.acquire, ['two'])
829 aaae9bc0 Guido Trotter
    self.ls.release('three')
830 aaae9bc0 Guido Trotter
831 aaae9bc0 Guido Trotter
  def testNoWrongRelease(self):
832 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.release)
833 aaae9bc0 Guido Trotter
    self.ls.acquire('one')
834 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.release, 'two')
835 aaae9bc0 Guido Trotter
836 aaae9bc0 Guido Trotter
  def testAddRemove(self):
837 aaae9bc0 Guido Trotter
    self.ls.add('four')
838 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set())
839 aaae9bc0 Guido Trotter
    self.assert_('four' in self.ls._names())
840 aaae9bc0 Guido Trotter
    self.ls.add(['five', 'six', 'seven'], acquired=1)
841 aaae9bc0 Guido Trotter
    self.assert_('five' in self.ls._names())
842 aaae9bc0 Guido Trotter
    self.assert_('six' in self.ls._names())
843 aaae9bc0 Guido Trotter
    self.assert_('seven' in self.ls._names())
844 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['five', 'six', 'seven']))
845 3f404fc5 Guido Trotter
    self.assertEquals(self.ls.remove(['five', 'six']), ['five', 'six'])
846 aaae9bc0 Guido Trotter
    self.assert_('five' not in self.ls._names())
847 aaae9bc0 Guido Trotter
    self.assert_('six' not in self.ls._names())
848 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['seven']))
849 d2aff862 Guido Trotter
    self.assertRaises(AssertionError, self.ls.add, 'eight', acquired=1)
850 aaae9bc0 Guido Trotter
    self.ls.remove('seven')
851 aaae9bc0 Guido Trotter
    self.assert_('seven' not in self.ls._names())
852 d2aff862 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set([]))
853 d2aff862 Guido Trotter
    self.ls.acquire(None, shared=1)
854 d2aff862 Guido Trotter
    self.assertRaises(AssertionError, self.ls.add, 'eight')
855 d2aff862 Guido Trotter
    self.ls.release()
856 d2aff862 Guido Trotter
    self.ls.acquire(None)
857 d2aff862 Guido Trotter
    self.ls.add('eight', acquired=1)
858 d2aff862 Guido Trotter
    self.assert_('eight' in self.ls._names())
859 d2aff862 Guido Trotter
    self.assert_('eight' in self.ls._list_owned())
860 d2aff862 Guido Trotter
    self.ls.add('nine')
861 d2aff862 Guido Trotter
    self.assert_('nine' in self.ls._names())
862 d2aff862 Guido Trotter
    self.assert_('nine' not in self.ls._list_owned())
863 aaae9bc0 Guido Trotter
    self.ls.release()
864 aaae9bc0 Guido Trotter
    self.ls.remove(['two'])
865 aaae9bc0 Guido Trotter
    self.assert_('two' not in self.ls._names())
866 aaae9bc0 Guido Trotter
    self.ls.acquire('three')
867 3f404fc5 Guido Trotter
    self.assertEquals(self.ls.remove(['three']), ['three'])
868 aaae9bc0 Guido Trotter
    self.assert_('three' not in self.ls._names())
869 3f404fc5 Guido Trotter
    self.assertEquals(self.ls.remove('three'), [])
870 3f404fc5 Guido Trotter
    self.assertEquals(self.ls.remove(['one', 'three', 'six']), ['one'])
871 aaae9bc0 Guido Trotter
    self.assert_('one' not in self.ls._names())
872 aaae9bc0 Guido Trotter
873 aaae9bc0 Guido Trotter
  def testRemoveNonBlocking(self):
874 aaae9bc0 Guido Trotter
    self.ls.acquire('one')
875 5e0a6daf Michael Hanselmann
    self.assertEquals(self.ls.remove('one'), ['one'])
876 aaae9bc0 Guido Trotter
    self.ls.acquire(['two', 'three'])
877 5e0a6daf Michael Hanselmann
    self.assertEquals(self.ls.remove(['two', 'three']),
878 3f404fc5 Guido Trotter
                      ['two', 'three'])
879 aaae9bc0 Guido Trotter
880 aaae9bc0 Guido Trotter
  def testNoDoubleAdd(self):
881 aaae9bc0 Guido Trotter
    self.assertRaises(errors.LockError, self.ls.add, 'two')
882 aaae9bc0 Guido Trotter
    self.ls.add('four')
883 aaae9bc0 Guido Trotter
    self.assertRaises(errors.LockError, self.ls.add, 'four')
884 aaae9bc0 Guido Trotter
885 aaae9bc0 Guido Trotter
  def testNoWrongRemoves(self):
886 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'three'], shared=1)
887 aaae9bc0 Guido Trotter
    # Cannot remove 'two' while holding something which is not a superset
888 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.remove, 'two')
889 aaae9bc0 Guido Trotter
    # Cannot remove 'three' as we are sharing it
890 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.remove, 'three')
891 aaae9bc0 Guido Trotter
892 3b7ed473 Guido Trotter
  def testAcquireSetLock(self):
893 3b7ed473 Guido Trotter
    # acquire the set-lock exclusively
894 3b7ed473 Guido Trotter
    self.assertEquals(self.ls.acquire(None), set(['one', 'two', 'three']))
895 d4803c24 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['one', 'two', 'three']))
896 d4803c24 Guido Trotter
    self.assertEquals(self.ls._is_owned(), True)
897 d4803c24 Guido Trotter
    self.assertEquals(self.ls._names(), set(['one', 'two', 'three']))
898 3b7ed473 Guido Trotter
    # I can still add/remove elements...
899 3b7ed473 Guido Trotter
    self.assertEquals(self.ls.remove(['two', 'three']), ['two', 'three'])
900 3b7ed473 Guido Trotter
    self.assert_(self.ls.add('six'))
901 3b7ed473 Guido Trotter
    self.ls.release()
902 3b7ed473 Guido Trotter
    # share the set-lock
903 3b7ed473 Guido Trotter
    self.assertEquals(self.ls.acquire(None, shared=1), set(['one', 'six']))
904 3b7ed473 Guido Trotter
    # adding new elements is not possible
905 3b7ed473 Guido Trotter
    self.assertRaises(AssertionError, self.ls.add, 'five')
906 3b7ed473 Guido Trotter
    self.ls.release()
907 3b7ed473 Guido Trotter
908 d4f6a91c Guido Trotter
  def testAcquireWithRepetitions(self):
909 d4f6a91c Guido Trotter
    self.assertEquals(self.ls.acquire(['two', 'two', 'three'], shared=1),
910 d4f6a91c Guido Trotter
                      set(['two', 'two', 'three']))
911 d4f6a91c Guido Trotter
    self.ls.release(['two', 'two'])
912 d4f6a91c Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['three']))
913 d4f6a91c Guido Trotter
914 2e1d6d96 Guido Trotter
  def testEmptyAcquire(self):
915 2e1d6d96 Guido Trotter
    # Acquire an empty list of locks...
916 2e1d6d96 Guido Trotter
    self.assertEquals(self.ls.acquire([]), set())
917 2e1d6d96 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set())
918 2e1d6d96 Guido Trotter
    # New locks can still be addded
919 2e1d6d96 Guido Trotter
    self.assert_(self.ls.add('six'))
920 2e1d6d96 Guido Trotter
    # "re-acquiring" is not an issue, since we had really acquired nothing
921 2e1d6d96 Guido Trotter
    self.assertEquals(self.ls.acquire([], shared=1), set())
922 2e1d6d96 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set())
923 2e1d6d96 Guido Trotter
    # We haven't really acquired anything, so we cannot release
924 2e1d6d96 Guido Trotter
    self.assertRaises(AssertionError, self.ls.release)
925 2e1d6d96 Guido Trotter
926 84e344d4 Michael Hanselmann
  def _doLockSet(self, names, shared):
927 aaae9bc0 Guido Trotter
    try:
928 84e344d4 Michael Hanselmann
      self.ls.acquire(names, shared=shared)
929 aaae9bc0 Guido Trotter
      self.done.put('DONE')
930 aaae9bc0 Guido Trotter
      self.ls.release()
931 aaae9bc0 Guido Trotter
    except errors.LockError:
932 aaae9bc0 Guido Trotter
      self.done.put('ERR')
933 aaae9bc0 Guido Trotter
934 84e344d4 Michael Hanselmann
  def _doAddSet(self, names):
935 3b7ed473 Guido Trotter
    try:
936 84e344d4 Michael Hanselmann
      self.ls.add(names, acquired=1)
937 3b7ed473 Guido Trotter
      self.done.put('DONE')
938 3b7ed473 Guido Trotter
      self.ls.release()
939 3b7ed473 Guido Trotter
    except errors.LockError:
940 3b7ed473 Guido Trotter
      self.done.put('ERR')
941 3b7ed473 Guido Trotter
942 84e344d4 Michael Hanselmann
  def _doRemoveSet(self, names):
943 84e344d4 Michael Hanselmann
    self.done.put(self.ls.remove(names))
944 aaae9bc0 Guido Trotter
945 4607c978 Iustin Pop
  @_Repeat
946 aaae9bc0 Guido Trotter
  def testConcurrentSharedAcquire(self):
947 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'two'], shared=1)
948 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['one', 'two'], 1))
949 4607c978 Iustin Pop
    self._waitThreads()
950 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
951 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['one', 'two', 'three'], 1))
952 4607c978 Iustin Pop
    self._waitThreads()
953 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
954 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=('three', 1))
955 4607c978 Iustin Pop
    self._waitThreads()
956 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
957 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['one', 'two'], 0))
958 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['two', 'three'], 0))
959 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
960 aaae9bc0 Guido Trotter
    self.ls.release()
961 4607c978 Iustin Pop
    self._waitThreads()
962 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
963 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
964 aaae9bc0 Guido Trotter
965 4607c978 Iustin Pop
  @_Repeat
966 aaae9bc0 Guido Trotter
  def testConcurrentExclusiveAcquire(self):
967 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'two'])
968 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=('three', 1))
969 4607c978 Iustin Pop
    self._waitThreads()
970 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
971 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=('three', 0))
972 4607c978 Iustin Pop
    self._waitThreads()
973 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
974 84e344d4 Michael Hanselmann
    self.assertRaises(Queue.Empty, self.done.get_nowait)
975 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['one', 'two'], 0))
976 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['one', 'two'], 1))
977 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=('one', 0))
978 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=('one', 1))
979 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['two', 'three'], 0))
980 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['two', 'three'], 1))
981 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
982 aaae9bc0 Guido Trotter
    self.ls.release()
983 4607c978 Iustin Pop
    self._waitThreads()
984 4607c978 Iustin Pop
    for _ in range(6):
985 4607c978 Iustin Pop
      self.failUnlessEqual(self.done.get_nowait(), 'DONE')
986 aaae9bc0 Guido Trotter
987 4607c978 Iustin Pop
  @_Repeat
988 aaae9bc0 Guido Trotter
  def testConcurrentRemove(self):
989 aaae9bc0 Guido Trotter
    self.ls.add('four')
990 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'two', 'four'])
991 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['one', 'four'], 0))
992 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['one', 'four'], 1))
993 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['one', 'two'], 0))
994 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['one', 'two'], 1))
995 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
996 aaae9bc0 Guido Trotter
    self.ls.remove('one')
997 aaae9bc0 Guido Trotter
    self.ls.release()
998 4607c978 Iustin Pop
    self._waitThreads()
999 4607c978 Iustin Pop
    for i in range(4):
1000 4607c978 Iustin Pop
      self.failUnlessEqual(self.done.get_nowait(), 'ERR')
1001 aaae9bc0 Guido Trotter
    self.ls.add(['five', 'six'], acquired=1)
1002 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['three', 'six'], 1))
1003 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['three', 'six'], 0))
1004 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['four', 'six'], 1))
1005 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['four', 'six'], 0))
1006 aaae9bc0 Guido Trotter
    self.ls.remove('five')
1007 aaae9bc0 Guido Trotter
    self.ls.release()
1008 4607c978 Iustin Pop
    self._waitThreads()
1009 4607c978 Iustin Pop
    for i in range(4):
1010 4607c978 Iustin Pop
      self.failUnlessEqual(self.done.get_nowait(), 'DONE')
1011 aaae9bc0 Guido Trotter
    self.ls.acquire(['three', 'four'])
1012 4607c978 Iustin Pop
    self._addThread(target=self._doRemoveSet, args=(['four', 'six'], ))
1013 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1014 aaae9bc0 Guido Trotter
    self.ls.remove('four')
1015 4607c978 Iustin Pop
    self._waitThreads()
1016 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), ['six'])
1017 4607c978 Iustin Pop
    self._addThread(target=self._doRemoveSet, args=(['two']))
1018 4607c978 Iustin Pop
    self._waitThreads()
1019 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), ['two'])
1020 aaae9bc0 Guido Trotter
    self.ls.release()
1021 4607c978 Iustin Pop
    # reset lockset
1022 4607c978 Iustin Pop
    self._setUpLS()
1023 aaae9bc0 Guido Trotter
1024 4607c978 Iustin Pop
  @_Repeat
1025 3b7ed473 Guido Trotter
  def testConcurrentSharedSetLock(self):
1026 3b7ed473 Guido Trotter
    # share the set-lock...
1027 3b7ed473 Guido Trotter
    self.ls.acquire(None, shared=1)
1028 3b7ed473 Guido Trotter
    # ...another thread can share it too
1029 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(None, 1))
1030 4607c978 Iustin Pop
    self._waitThreads()
1031 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1032 3b7ed473 Guido Trotter
    # ...or just share some elements
1033 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['one', 'three'], 1))
1034 4607c978 Iustin Pop
    self._waitThreads()
1035 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1036 3b7ed473 Guido Trotter
    # ...but not add new ones or remove any
1037 4607c978 Iustin Pop
    t = self._addThread(target=self._doAddSet, args=(['nine']))
1038 4607c978 Iustin Pop
    self._addThread(target=self._doRemoveSet, args=(['two'], ))
1039 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1040 3b7ed473 Guido Trotter
    # this just releases the set-lock
1041 3b7ed473 Guido Trotter
    self.ls.release([])
1042 4607c978 Iustin Pop
    t.join(60)
1043 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1044 3b7ed473 Guido Trotter
    # release the lock on the actual elements so remove() can proceed too
1045 3b7ed473 Guido Trotter
    self.ls.release()
1046 4607c978 Iustin Pop
    self._waitThreads()
1047 4607c978 Iustin Pop
    self.failUnlessEqual(self.done.get_nowait(), ['two'])
1048 4607c978 Iustin Pop
    # reset lockset
1049 4607c978 Iustin Pop
    self._setUpLS()
1050 3b7ed473 Guido Trotter
1051 4607c978 Iustin Pop
  @_Repeat
1052 3b7ed473 Guido Trotter
  def testConcurrentExclusiveSetLock(self):
1053 3b7ed473 Guido Trotter
    # acquire the set-lock...
1054 3b7ed473 Guido Trotter
    self.ls.acquire(None, shared=0)
1055 3b7ed473 Guido Trotter
    # ...no one can do anything else
1056 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(None, 1))
1057 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(None, 0))
1058 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['three'], 0))
1059 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['two'], 1))
1060 4607c978 Iustin Pop
    self._addThread(target=self._doAddSet, args=(['nine']))
1061 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1062 3b7ed473 Guido Trotter
    self.ls.release()
1063 4607c978 Iustin Pop
    self._waitThreads()
1064 4607c978 Iustin Pop
    for _ in range(5):
1065 4607c978 Iustin Pop
      self.assertEqual(self.done.get(True, 1), 'DONE')
1066 4607c978 Iustin Pop
    # cleanup
1067 4607c978 Iustin Pop
    self._setUpLS()
1068 3b7ed473 Guido Trotter
1069 4607c978 Iustin Pop
  @_Repeat
1070 d2aff862 Guido Trotter
  def testConcurrentSetLockAdd(self):
1071 d2aff862 Guido Trotter
    self.ls.acquire('one')
1072 d2aff862 Guido Trotter
    # Another thread wants the whole SetLock
1073 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(None, 0))
1074 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(None, 1))
1075 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1076 d2aff862 Guido Trotter
    self.assertRaises(AssertionError, self.ls.add, 'four')
1077 d2aff862 Guido Trotter
    self.ls.release()
1078 4607c978 Iustin Pop
    self._waitThreads()
1079 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1080 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1081 d2aff862 Guido Trotter
    self.ls.acquire(None)
1082 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(None, 0))
1083 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(None, 1))
1084 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1085 d2aff862 Guido Trotter
    self.ls.add('four')
1086 d2aff862 Guido Trotter
    self.ls.add('five', acquired=1)
1087 d2aff862 Guido Trotter
    self.ls.add('six', acquired=1, shared=1)
1088 d2aff862 Guido Trotter
    self.assertEquals(self.ls._list_owned(),
1089 d2aff862 Guido Trotter
      set(['one', 'two', 'three', 'five', 'six']))
1090 d2aff862 Guido Trotter
    self.assertEquals(self.ls._is_owned(), True)
1091 d2aff862 Guido Trotter
    self.assertEquals(self.ls._names(),
1092 d2aff862 Guido Trotter
      set(['one', 'two', 'three', 'four', 'five', 'six']))
1093 d2aff862 Guido Trotter
    self.ls.release()
1094 4607c978 Iustin Pop
    self._waitThreads()
1095 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1096 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1097 4607c978 Iustin Pop
    self._setUpLS()
1098 d2aff862 Guido Trotter
1099 4607c978 Iustin Pop
  @_Repeat
1100 b2dabfd6 Guido Trotter
  def testEmptyLockSet(self):
1101 b2dabfd6 Guido Trotter
    # get the set-lock
1102 b2dabfd6 Guido Trotter
    self.assertEqual(self.ls.acquire(None), set(['one', 'two', 'three']))
1103 b2dabfd6 Guido Trotter
    # now empty it...
1104 b2dabfd6 Guido Trotter
    self.ls.remove(['one', 'two', 'three'])
1105 b2dabfd6 Guido Trotter
    # and adds/locks by another thread still wait
1106 4607c978 Iustin Pop
    self._addThread(target=self._doAddSet, args=(['nine']))
1107 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(None, 1))
1108 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(None, 0))
1109 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1110 b2dabfd6 Guido Trotter
    self.ls.release()
1111 4607c978 Iustin Pop
    self._waitThreads()
1112 4607c978 Iustin Pop
    for _ in range(3):
1113 4607c978 Iustin Pop
      self.assertEqual(self.done.get_nowait(), 'DONE')
1114 b2dabfd6 Guido Trotter
    # empty it again...
1115 b2dabfd6 Guido Trotter
    self.assertEqual(self.ls.remove(['nine']), ['nine'])
1116 b2dabfd6 Guido Trotter
    # now share it...
1117 b2dabfd6 Guido Trotter
    self.assertEqual(self.ls.acquire(None, shared=1), set())
1118 b2dabfd6 Guido Trotter
    # other sharers can go, adds still wait
1119 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(None, 1))
1120 4607c978 Iustin Pop
    self._waitThreads()
1121 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1122 4607c978 Iustin Pop
    self._addThread(target=self._doAddSet, args=(['nine']))
1123 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1124 b2dabfd6 Guido Trotter
    self.ls.release()
1125 4607c978 Iustin Pop
    self._waitThreads()
1126 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1127 4607c978 Iustin Pop
    self._setUpLS()
1128 b2dabfd6 Guido Trotter
1129 aaae9bc0 Guido Trotter
1130 4607c978 Iustin Pop
class TestGanetiLockManager(_ThreadedTestCase):
1131 7ee7c0c7 Guido Trotter
1132 7ee7c0c7 Guido Trotter
  def setUp(self):
1133 4607c978 Iustin Pop
    _ThreadedTestCase.setUp(self)
1134 7ee7c0c7 Guido Trotter
    self.nodes=['n1', 'n2']
1135 7ee7c0c7 Guido Trotter
    self.instances=['i1', 'i2', 'i3']
1136 7ee7c0c7 Guido Trotter
    self.GL = locking.GanetiLockManager(nodes=self.nodes,
1137 7ee7c0c7 Guido Trotter
                                        instances=self.instances)
1138 7ee7c0c7 Guido Trotter
    self.done = Queue.Queue(0)
1139 7ee7c0c7 Guido Trotter
1140 7ee7c0c7 Guido Trotter
  def tearDown(self):
1141 7ee7c0c7 Guido Trotter
    # Don't try this at home...
1142 7ee7c0c7 Guido Trotter
    locking.GanetiLockManager._instance = None
1143 7ee7c0c7 Guido Trotter
1144 7ee7c0c7 Guido Trotter
  def testLockingConstants(self):
1145 7ee7c0c7 Guido Trotter
    # The locking library internally cheats by assuming its constants have some
1146 7ee7c0c7 Guido Trotter
    # relationships with each other. Check those hold true.
1147 b10b9d74 Guido Trotter
    # This relationship is also used in the Processor to recursively acquire
1148 b10b9d74 Guido Trotter
    # the right locks. Again, please don't break it.
1149 7ee7c0c7 Guido Trotter
    for i in range(len(locking.LEVELS)):
1150 7ee7c0c7 Guido Trotter
      self.assertEqual(i, locking.LEVELS[i])
1151 7ee7c0c7 Guido Trotter
1152 7ee7c0c7 Guido Trotter
  def testDoubleGLFails(self):
1153 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, locking.GanetiLockManager)
1154 7ee7c0c7 Guido Trotter
1155 7ee7c0c7 Guido Trotter
  def testLockNames(self):
1156 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
1157 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set(self.nodes))
1158 cdb08f44 Michael Hanselmann
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE),
1159 cdb08f44 Michael Hanselmann
                     set(self.instances))
1160 7ee7c0c7 Guido Trotter
1161 7ee7c0c7 Guido Trotter
  def testInitAndResources(self):
1162 7ee7c0c7 Guido Trotter
    locking.GanetiLockManager._instance = None
1163 7ee7c0c7 Guido Trotter
    self.GL = locking.GanetiLockManager()
1164 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
1165 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set())
1166 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE), set())
1167 7ee7c0c7 Guido Trotter
1168 7ee7c0c7 Guido Trotter
    locking.GanetiLockManager._instance = None
1169 7ee7c0c7 Guido Trotter
    self.GL = locking.GanetiLockManager(nodes=self.nodes)
1170 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
1171 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set(self.nodes))
1172 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE), set())
1173 7ee7c0c7 Guido Trotter
1174 7ee7c0c7 Guido Trotter
    locking.GanetiLockManager._instance = None
1175 7ee7c0c7 Guido Trotter
    self.GL = locking.GanetiLockManager(instances=self.instances)
1176 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
1177 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set())
1178 cdb08f44 Michael Hanselmann
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE),
1179 cdb08f44 Michael Hanselmann
                     set(self.instances))
1180 7ee7c0c7 Guido Trotter
1181 7ee7c0c7 Guido Trotter
  def testAcquireRelease(self):
1182 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
1183 7ee7c0c7 Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_CLUSTER), set(['BGL']))
1184 04e1bfaf Guido Trotter
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i1'])
1185 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_NODE, ['n1', 'n2'], shared=1)
1186 04e1bfaf Guido Trotter
    self.GL.release(locking.LEVEL_NODE, ['n2'])
1187 7ee7c0c7 Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_NODE), set(['n1']))
1188 7ee7c0c7 Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE), set(['i1']))
1189 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_NODE)
1190 04e1bfaf Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_NODE), set())
1191 04e1bfaf Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE), set(['i1']))
1192 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
1193 7ee7c0c7 Guido Trotter
    self.assertRaises(errors.LockError, self.GL.acquire,
1194 7ee7c0c7 Guido Trotter
                      locking.LEVEL_INSTANCE, ['i5'])
1195 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i3'], shared=1)
1196 7ee7c0c7 Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE), set(['i3']))
1197 7ee7c0c7 Guido Trotter
1198 90c942d1 Guido Trotter
  def testAcquireWholeSets(self):
1199 90c942d1 Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
1200 90c942d1 Guido Trotter
    self.assertEquals(self.GL.acquire(locking.LEVEL_INSTANCE, None),
1201 90c942d1 Guido Trotter
                      set(self.instances))
1202 90c942d1 Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE),
1203 90c942d1 Guido Trotter
                      set(self.instances))
1204 90c942d1 Guido Trotter
    self.assertEquals(self.GL.acquire(locking.LEVEL_NODE, None, shared=1),
1205 90c942d1 Guido Trotter
                      set(self.nodes))
1206 90c942d1 Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_NODE),
1207 90c942d1 Guido Trotter
                      set(self.nodes))
1208 90c942d1 Guido Trotter
    self.GL.release(locking.LEVEL_NODE)
1209 d4f6a91c Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
1210 d4f6a91c Guido Trotter
    self.GL.release(locking.LEVEL_CLUSTER)
1211 d4f6a91c Guido Trotter
1212 d4f6a91c Guido Trotter
  def testAcquireWholeAndPartial(self):
1213 d4f6a91c Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
1214 d4f6a91c Guido Trotter
    self.assertEquals(self.GL.acquire(locking.LEVEL_INSTANCE, None),
1215 d4f6a91c Guido Trotter
                      set(self.instances))
1216 d4f6a91c Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE),
1217 d4f6a91c Guido Trotter
                      set(self.instances))
1218 d4f6a91c Guido Trotter
    self.assertEquals(self.GL.acquire(locking.LEVEL_NODE, ['n2'], shared=1),
1219 d4f6a91c Guido Trotter
                      set(['n2']))
1220 d4f6a91c Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_NODE),
1221 d4f6a91c Guido Trotter
                      set(['n2']))
1222 d4f6a91c Guido Trotter
    self.GL.release(locking.LEVEL_NODE)
1223 90c942d1 Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
1224 90c942d1 Guido Trotter
    self.GL.release(locking.LEVEL_CLUSTER)
1225 90c942d1 Guido Trotter
1226 7ee7c0c7 Guido Trotter
  def testBGLDependency(self):
1227 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.acquire,
1228 7ee7c0c7 Guido Trotter
                      locking.LEVEL_NODE, ['n1', 'n2'])
1229 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.acquire,
1230 7ee7c0c7 Guido Trotter
                      locking.LEVEL_INSTANCE, ['i3'])
1231 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
1232 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_NODE, ['n1'])
1233 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.release,
1234 7ee7c0c7 Guido Trotter
                      locking.LEVEL_CLUSTER, ['BGL'])
1235 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.release,
1236 7ee7c0c7 Guido Trotter
                      locking.LEVEL_CLUSTER)
1237 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_NODE)
1238 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i1', 'i2'])
1239 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.release,
1240 7ee7c0c7 Guido Trotter
                      locking.LEVEL_CLUSTER, ['BGL'])
1241 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.release,
1242 7ee7c0c7 Guido Trotter
                      locking.LEVEL_CLUSTER)
1243 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
1244 7ee7c0c7 Guido Trotter
1245 7ee7c0c7 Guido Trotter
  def testWrongOrder(self):
1246 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
1247 04e1bfaf Guido Trotter
    self.GL.acquire(locking.LEVEL_NODE, ['n2'])
1248 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.acquire,
1249 7ee7c0c7 Guido Trotter
                      locking.LEVEL_NODE, ['n1'])
1250 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.acquire,
1251 7ee7c0c7 Guido Trotter
                      locking.LEVEL_INSTANCE, ['i2'])
1252 7ee7c0c7 Guido Trotter
1253 7ee7c0c7 Guido Trotter
  # Helper function to run as a thread that shared the BGL and then acquires
1254 7ee7c0c7 Guido Trotter
  # some locks at another level.
1255 7ee7c0c7 Guido Trotter
  def _doLock(self, level, names, shared):
1256 7ee7c0c7 Guido Trotter
    try:
1257 7ee7c0c7 Guido Trotter
      self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
1258 7ee7c0c7 Guido Trotter
      self.GL.acquire(level, names, shared=shared)
1259 7ee7c0c7 Guido Trotter
      self.done.put('DONE')
1260 7ee7c0c7 Guido Trotter
      self.GL.release(level)
1261 7ee7c0c7 Guido Trotter
      self.GL.release(locking.LEVEL_CLUSTER)
1262 7ee7c0c7 Guido Trotter
    except errors.LockError:
1263 7ee7c0c7 Guido Trotter
      self.done.put('ERR')
1264 7ee7c0c7 Guido Trotter
1265 4607c978 Iustin Pop
  @_Repeat
1266 7ee7c0c7 Guido Trotter
  def testConcurrency(self):
1267 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
1268 4607c978 Iustin Pop
    self._addThread(target=self._doLock,
1269 4607c978 Iustin Pop
                    args=(locking.LEVEL_INSTANCE, 'i1', 1))
1270 4607c978 Iustin Pop
    self._waitThreads()
1271 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1272 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i3'])
1273 4607c978 Iustin Pop
    self._addThread(target=self._doLock,
1274 4607c978 Iustin Pop
                    args=(locking.LEVEL_INSTANCE, 'i1', 1))
1275 4607c978 Iustin Pop
    self._waitThreads()
1276 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1277 4607c978 Iustin Pop
    self._addThread(target=self._doLock,
1278 4607c978 Iustin Pop
                    args=(locking.LEVEL_INSTANCE, 'i3', 1))
1279 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1280 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
1281 4607c978 Iustin Pop
    self._waitThreads()
1282 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1283 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i2'], shared=1)
1284 4607c978 Iustin Pop
    self._addThread(target=self._doLock,
1285 4607c978 Iustin Pop
                    args=(locking.LEVEL_INSTANCE, 'i2', 1))
1286 4607c978 Iustin Pop
    self._waitThreads()
1287 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1288 4607c978 Iustin Pop
    self._addThread(target=self._doLock,
1289 4607c978 Iustin Pop
                    args=(locking.LEVEL_INSTANCE, 'i2', 0))
1290 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1291 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
1292 4607c978 Iustin Pop
    self._waitThreads()
1293 7ee7c0c7 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
1294 4607c978 Iustin Pop
    self.GL.release(locking.LEVEL_CLUSTER, ['BGL'])
1295 7ee7c0c7 Guido Trotter
1296 7ee7c0c7 Guido Trotter
1297 162c1c1f Guido Trotter
if __name__ == '__main__':
1298 162c1c1f Guido Trotter
  unittest.main()
1299 162c1c1f Guido Trotter
  #suite = unittest.TestLoader().loadTestsFromTestCase(TestSharedLock)
1300 162c1c1f Guido Trotter
  #unittest.TextTestRunner(verbosity=2).run(suite)