Statistics
| Branch: | Tag: | Revision:

root / test / ganeti.locking_unittest.py @ c74cda62

History | View | Annotate | Download (59.4 kB)

1 162c1c1f Guido Trotter
#!/usr/bin/python
2 162c1c1f Guido Trotter
#
3 162c1c1f Guido Trotter
4 7f93570a Iustin Pop
# Copyright (C) 2006, 2007, 2010 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 19b9ba9a Michael Hanselmann
import random
31 887c7aa6 Michael Hanselmann
import itertools
32 162c1c1f Guido Trotter
33 162c1c1f Guido Trotter
from ganeti import locking
34 a95fd5d7 Guido Trotter
from ganeti import errors
35 19b9ba9a Michael Hanselmann
from ganeti import utils
36 887c7aa6 Michael Hanselmann
from ganeti import compat
37 162c1c1f Guido Trotter
38 25231ec5 Michael Hanselmann
import testutils
39 25231ec5 Michael Hanselmann
40 162c1c1f Guido Trotter
41 42a999d1 Guido Trotter
# This is used to test the ssynchronize decorator.
42 42a999d1 Guido Trotter
# Since it's passed as input to a decorator it must be declared as a global.
43 7f93570a Iustin Pop
_decoratorlock = locking.SharedLock("decorator lock")
44 42a999d1 Guido Trotter
45 4607c978 Iustin Pop
#: List for looping tests
46 4607c978 Iustin Pop
ITERATIONS = range(8)
47 4607c978 Iustin Pop
48 84e344d4 Michael Hanselmann
49 4607c978 Iustin Pop
def _Repeat(fn):
50 4607c978 Iustin Pop
  """Decorator for executing a function many times"""
51 4607c978 Iustin Pop
  def wrapper(*args, **kwargs):
52 4607c978 Iustin Pop
    for i in ITERATIONS:
53 4607c978 Iustin Pop
      fn(*args, **kwargs)
54 4607c978 Iustin Pop
  return wrapper
55 4607c978 Iustin Pop
56 84e344d4 Michael Hanselmann
57 5aab242c Michael Hanselmann
def SafeSleep(duration):
58 5aab242c Michael Hanselmann
  start = time.time()
59 5aab242c Michael Hanselmann
  while True:
60 5aab242c Michael Hanselmann
    delay = start + duration - time.time()
61 5aab242c Michael Hanselmann
    if delay <= 0.0:
62 5aab242c Michael Hanselmann
      break
63 5aab242c Michael Hanselmann
    time.sleep(delay)
64 5aab242c Michael Hanselmann
65 5aab242c Michael Hanselmann
66 4607c978 Iustin Pop
class _ThreadedTestCase(unittest.TestCase):
67 4607c978 Iustin Pop
  """Test class that supports adding/waiting on threads"""
68 4607c978 Iustin Pop
  def setUp(self):
69 4607c978 Iustin Pop
    unittest.TestCase.setUp(self)
70 63f2e724 Guido Trotter
    self.done = Queue.Queue(0)
71 4607c978 Iustin Pop
    self.threads = []
72 4607c978 Iustin Pop
73 4607c978 Iustin Pop
  def _addThread(self, *args, **kwargs):
74 4607c978 Iustin Pop
    """Create and remember a new thread"""
75 84e344d4 Michael Hanselmann
    t = threading.Thread(*args, **kwargs)
76 4607c978 Iustin Pop
    self.threads.append(t)
77 4607c978 Iustin Pop
    t.start()
78 4607c978 Iustin Pop
    return t
79 4607c978 Iustin Pop
80 4607c978 Iustin Pop
  def _waitThreads(self):
81 4607c978 Iustin Pop
    """Wait for all our threads to finish"""
82 4607c978 Iustin Pop
    for t in self.threads:
83 4607c978 Iustin Pop
      t.join(60)
84 4607c978 Iustin Pop
      self.failIf(t.isAlive())
85 4607c978 Iustin Pop
    self.threads = []
86 42a999d1 Guido Trotter
87 4607c978 Iustin Pop
88 c5fe2a67 Guido Trotter
class _ConditionTestCase(_ThreadedTestCase):
89 c5fe2a67 Guido Trotter
  """Common test case for conditions"""
90 48dabc6a Michael Hanselmann
91 c5fe2a67 Guido Trotter
  def setUp(self, cls):
92 48dabc6a Michael Hanselmann
    _ThreadedTestCase.setUp(self)
93 48dabc6a Michael Hanselmann
    self.lock = threading.Lock()
94 c5fe2a67 Guido Trotter
    self.cond = cls(self.lock)
95 48dabc6a Michael Hanselmann
96 c5fe2a67 Guido Trotter
  def _testAcquireRelease(self):
97 158206e0 Manuel Franceschini
    self.assertFalse(self.cond._is_owned())
98 48dabc6a Michael Hanselmann
    self.assertRaises(RuntimeError, self.cond.wait)
99 48dabc6a Michael Hanselmann
    self.assertRaises(RuntimeError, self.cond.notifyAll)
100 48dabc6a Michael Hanselmann
101 48dabc6a Michael Hanselmann
    self.cond.acquire()
102 48dabc6a Michael Hanselmann
    self.assert_(self.cond._is_owned())
103 48dabc6a Michael Hanselmann
    self.cond.notifyAll()
104 48dabc6a Michael Hanselmann
    self.assert_(self.cond._is_owned())
105 48dabc6a Michael Hanselmann
    self.cond.release()
106 48dabc6a Michael Hanselmann
107 158206e0 Manuel Franceschini
    self.assertFalse(self.cond._is_owned())
108 48dabc6a Michael Hanselmann
    self.assertRaises(RuntimeError, self.cond.wait)
109 48dabc6a Michael Hanselmann
    self.assertRaises(RuntimeError, self.cond.notifyAll)
110 48dabc6a Michael Hanselmann
111 c5fe2a67 Guido Trotter
  def _testNotification(self):
112 48dabc6a Michael Hanselmann
    def _NotifyAll():
113 b8140229 Guido Trotter
      self.done.put("NE")
114 48dabc6a Michael Hanselmann
      self.cond.acquire()
115 b8140229 Guido Trotter
      self.done.put("NA")
116 48dabc6a Michael Hanselmann
      self.cond.notifyAll()
117 b8140229 Guido Trotter
      self.done.put("NN")
118 48dabc6a Michael Hanselmann
      self.cond.release()
119 48dabc6a Michael Hanselmann
120 48dabc6a Michael Hanselmann
    self.cond.acquire()
121 48dabc6a Michael Hanselmann
    self._addThread(target=_NotifyAll)
122 b8140229 Guido Trotter
    self.assertEqual(self.done.get(True, 1), "NE")
123 b8140229 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get_nowait)
124 48dabc6a Michael Hanselmann
    self.cond.wait()
125 b8140229 Guido Trotter
    self.assertEqual(self.done.get(True, 1), "NA")
126 b8140229 Guido Trotter
    self.assertEqual(self.done.get(True, 1), "NN")
127 48dabc6a Michael Hanselmann
    self.assert_(self.cond._is_owned())
128 48dabc6a Michael Hanselmann
    self.cond.release()
129 158206e0 Manuel Franceschini
    self.assertFalse(self.cond._is_owned())
130 48dabc6a Michael Hanselmann
131 c5fe2a67 Guido Trotter
132 34cb5617 Guido Trotter
class TestSingleNotifyPipeCondition(_ConditionTestCase):
133 34cb5617 Guido Trotter
  """SingleNotifyPipeCondition tests"""
134 34cb5617 Guido Trotter
135 34cb5617 Guido Trotter
  def setUp(self):
136 34cb5617 Guido Trotter
    _ConditionTestCase.setUp(self, locking.SingleNotifyPipeCondition)
137 34cb5617 Guido Trotter
138 34cb5617 Guido Trotter
  def testAcquireRelease(self):
139 34cb5617 Guido Trotter
    self._testAcquireRelease()
140 34cb5617 Guido Trotter
141 34cb5617 Guido Trotter
  def testNotification(self):
142 34cb5617 Guido Trotter
    self._testNotification()
143 34cb5617 Guido Trotter
144 34cb5617 Guido Trotter
  def testWaitReuse(self):
145 34cb5617 Guido Trotter
    self.cond.acquire()
146 34cb5617 Guido Trotter
    self.cond.wait(0)
147 34cb5617 Guido Trotter
    self.cond.wait(0.1)
148 34cb5617 Guido Trotter
    self.cond.release()
149 34cb5617 Guido Trotter
150 34cb5617 Guido Trotter
  def testNoNotifyReuse(self):
151 34cb5617 Guido Trotter
    self.cond.acquire()
152 34cb5617 Guido Trotter
    self.cond.notifyAll()
153 34cb5617 Guido Trotter
    self.assertRaises(RuntimeError, self.cond.wait)
154 34cb5617 Guido Trotter
    self.assertRaises(RuntimeError, self.cond.notifyAll)
155 34cb5617 Guido Trotter
    self.cond.release()
156 34cb5617 Guido Trotter
157 34cb5617 Guido Trotter
158 c5fe2a67 Guido Trotter
class TestPipeCondition(_ConditionTestCase):
159 34cb5617 Guido Trotter
  """PipeCondition tests"""
160 c5fe2a67 Guido Trotter
161 c5fe2a67 Guido Trotter
  def setUp(self):
162 34cb5617 Guido Trotter
    _ConditionTestCase.setUp(self, locking.PipeCondition)
163 c5fe2a67 Guido Trotter
164 c5fe2a67 Guido Trotter
  def testAcquireRelease(self):
165 c5fe2a67 Guido Trotter
    self._testAcquireRelease()
166 c5fe2a67 Guido Trotter
167 c5fe2a67 Guido Trotter
  def testNotification(self):
168 c5fe2a67 Guido Trotter
    self._testNotification()
169 c5fe2a67 Guido Trotter
170 48dabc6a Michael Hanselmann
  def _TestWait(self, fn):
171 c31825f7 Michael Hanselmann
    threads = [
172 c31825f7 Michael Hanselmann
      self._addThread(target=fn),
173 c31825f7 Michael Hanselmann
      self._addThread(target=fn),
174 c31825f7 Michael Hanselmann
      self._addThread(target=fn),
175 c31825f7 Michael Hanselmann
      ]
176 48dabc6a Michael Hanselmann
177 48dabc6a Michael Hanselmann
    # Wait for threads to be waiting
178 c31825f7 Michael Hanselmann
    for _ in threads:
179 c31825f7 Michael Hanselmann
      self.assertEqual(self.done.get(True, 1), "A")
180 48dabc6a Michael Hanselmann
181 48dabc6a Michael Hanselmann
    self.assertRaises(Queue.Empty, self.done.get_nowait)
182 48dabc6a Michael Hanselmann
183 48dabc6a Michael Hanselmann
    self.cond.acquire()
184 c31825f7 Michael Hanselmann
    self.assertEqual(len(self.cond._waiters), 3)
185 c31825f7 Michael Hanselmann
    self.assertEqual(self.cond._waiters, set(threads))
186 c31825f7 Michael Hanselmann
    # This new thread can't acquire the lock, and thus call wait, before we
187 48dabc6a Michael Hanselmann
    # release it
188 48dabc6a Michael Hanselmann
    self._addThread(target=fn)
189 48dabc6a Michael Hanselmann
    self.cond.notifyAll()
190 48dabc6a Michael Hanselmann
    self.assertRaises(Queue.Empty, self.done.get_nowait)
191 48dabc6a Michael Hanselmann
    self.cond.release()
192 48dabc6a Michael Hanselmann
193 48dabc6a Michael Hanselmann
    # We should now get 3 W and 1 A (for the new thread) in whatever order
194 48dabc6a Michael Hanselmann
    w = 0
195 48dabc6a Michael Hanselmann
    a = 0
196 48dabc6a Michael Hanselmann
    for i in range(4):
197 48dabc6a Michael Hanselmann
      got = self.done.get(True, 1)
198 48dabc6a Michael Hanselmann
      if got == "W":
199 48dabc6a Michael Hanselmann
        w += 1
200 48dabc6a Michael Hanselmann
      elif got == "A":
201 48dabc6a Michael Hanselmann
        a += 1
202 48dabc6a Michael Hanselmann
      else:
203 48dabc6a Michael Hanselmann
        self.fail("Got %s on the done queue" % got)
204 48dabc6a Michael Hanselmann
205 48dabc6a Michael Hanselmann
    self.assertEqual(w, 3)
206 48dabc6a Michael Hanselmann
    self.assertEqual(a, 1)
207 48dabc6a Michael Hanselmann
208 48dabc6a Michael Hanselmann
    self.cond.acquire()
209 48dabc6a Michael Hanselmann
    self.cond.notifyAll()
210 48dabc6a Michael Hanselmann
    self.cond.release()
211 48dabc6a Michael Hanselmann
    self._waitThreads()
212 48dabc6a Michael Hanselmann
    self.assertEqual(self.done.get_nowait(), "W")
213 48dabc6a Michael Hanselmann
    self.assertRaises(Queue.Empty, self.done.get_nowait)
214 48dabc6a Michael Hanselmann
215 48dabc6a Michael Hanselmann
  def testBlockingWait(self):
216 48dabc6a Michael Hanselmann
    def _BlockingWait():
217 48dabc6a Michael Hanselmann
      self.cond.acquire()
218 48dabc6a Michael Hanselmann
      self.done.put("A")
219 48dabc6a Michael Hanselmann
      self.cond.wait()
220 48dabc6a Michael Hanselmann
      self.cond.release()
221 48dabc6a Michael Hanselmann
      self.done.put("W")
222 48dabc6a Michael Hanselmann
223 48dabc6a Michael Hanselmann
    self._TestWait(_BlockingWait)
224 48dabc6a Michael Hanselmann
225 48dabc6a Michael Hanselmann
  def testLongTimeoutWait(self):
226 48dabc6a Michael Hanselmann
    def _Helper():
227 48dabc6a Michael Hanselmann
      self.cond.acquire()
228 48dabc6a Michael Hanselmann
      self.done.put("A")
229 48dabc6a Michael Hanselmann
      self.cond.wait(15.0)
230 48dabc6a Michael Hanselmann
      self.cond.release()
231 48dabc6a Michael Hanselmann
      self.done.put("W")
232 48dabc6a Michael Hanselmann
233 48dabc6a Michael Hanselmann
    self._TestWait(_Helper)
234 48dabc6a Michael Hanselmann
235 48dabc6a Michael Hanselmann
  def _TimeoutWait(self, timeout, check):
236 48dabc6a Michael Hanselmann
    self.cond.acquire()
237 48dabc6a Michael Hanselmann
    self.cond.wait(timeout)
238 48dabc6a Michael Hanselmann
    self.cond.release()
239 48dabc6a Michael Hanselmann
    self.done.put(check)
240 48dabc6a Michael Hanselmann
241 48dabc6a Michael Hanselmann
  def testShortTimeoutWait(self):
242 48dabc6a Michael Hanselmann
    self._addThread(target=self._TimeoutWait, args=(0.1, "T1"))
243 48dabc6a Michael Hanselmann
    self._addThread(target=self._TimeoutWait, args=(0.1, "T1"))
244 48dabc6a Michael Hanselmann
    self._waitThreads()
245 48dabc6a Michael Hanselmann
    self.assertEqual(self.done.get_nowait(), "T1")
246 48dabc6a Michael Hanselmann
    self.assertEqual(self.done.get_nowait(), "T1")
247 48dabc6a Michael Hanselmann
    self.assertRaises(Queue.Empty, self.done.get_nowait)
248 48dabc6a Michael Hanselmann
249 48dabc6a Michael Hanselmann
  def testZeroTimeoutWait(self):
250 48dabc6a Michael Hanselmann
    self._addThread(target=self._TimeoutWait, args=(0, "T0"))
251 48dabc6a Michael Hanselmann
    self._addThread(target=self._TimeoutWait, args=(0, "T0"))
252 48dabc6a Michael Hanselmann
    self._addThread(target=self._TimeoutWait, args=(0, "T0"))
253 48dabc6a Michael Hanselmann
    self._waitThreads()
254 48dabc6a Michael Hanselmann
    self.assertEqual(self.done.get_nowait(), "T0")
255 48dabc6a Michael Hanselmann
    self.assertEqual(self.done.get_nowait(), "T0")
256 48dabc6a Michael Hanselmann
    self.assertEqual(self.done.get_nowait(), "T0")
257 48dabc6a Michael Hanselmann
    self.assertRaises(Queue.Empty, self.done.get_nowait)
258 48dabc6a Michael Hanselmann
259 48dabc6a Michael Hanselmann
260 4607c978 Iustin Pop
class TestSharedLock(_ThreadedTestCase):
261 d6646186 Guido Trotter
  """SharedLock tests"""
262 162c1c1f Guido Trotter
263 162c1c1f Guido Trotter
  def setUp(self):
264 4607c978 Iustin Pop
    _ThreadedTestCase.setUp(self)
265 7f93570a Iustin Pop
    self.sl = locking.SharedLock("TestSharedLock")
266 162c1c1f Guido Trotter
267 162c1c1f Guido Trotter
  def testSequenceAndOwnership(self):
268 158206e0 Manuel Franceschini
    self.assertFalse(self.sl._is_owned())
269 162c1c1f Guido Trotter
    self.sl.acquire(shared=1)
270 162c1c1f Guido Trotter
    self.assert_(self.sl._is_owned())
271 162c1c1f Guido Trotter
    self.assert_(self.sl._is_owned(shared=1))
272 158206e0 Manuel Franceschini
    self.assertFalse(self.sl._is_owned(shared=0))
273 162c1c1f Guido Trotter
    self.sl.release()
274 158206e0 Manuel Franceschini
    self.assertFalse(self.sl._is_owned())
275 162c1c1f Guido Trotter
    self.sl.acquire()
276 162c1c1f Guido Trotter
    self.assert_(self.sl._is_owned())
277 158206e0 Manuel Franceschini
    self.assertFalse(self.sl._is_owned(shared=1))
278 162c1c1f Guido Trotter
    self.assert_(self.sl._is_owned(shared=0))
279 162c1c1f Guido Trotter
    self.sl.release()
280 158206e0 Manuel Franceschini
    self.assertFalse(self.sl._is_owned())
281 162c1c1f Guido Trotter
    self.sl.acquire(shared=1)
282 162c1c1f Guido Trotter
    self.assert_(self.sl._is_owned())
283 162c1c1f Guido Trotter
    self.assert_(self.sl._is_owned(shared=1))
284 158206e0 Manuel Franceschini
    self.assertFalse(self.sl._is_owned(shared=0))
285 162c1c1f Guido Trotter
    self.sl.release()
286 158206e0 Manuel Franceschini
    self.assertFalse(self.sl._is_owned())
287 162c1c1f Guido Trotter
288 162c1c1f Guido Trotter
  def testBooleanValue(self):
289 162c1c1f Guido Trotter
    # semaphores are supposed to return a true value on a successful acquire
290 162c1c1f Guido Trotter
    self.assert_(self.sl.acquire(shared=1))
291 162c1c1f Guido Trotter
    self.sl.release()
292 162c1c1f Guido Trotter
    self.assert_(self.sl.acquire())
293 162c1c1f Guido Trotter
    self.sl.release()
294 162c1c1f Guido Trotter
295 162c1c1f Guido Trotter
  def testDoubleLockingStoE(self):
296 162c1c1f Guido Trotter
    self.sl.acquire(shared=1)
297 162c1c1f Guido Trotter
    self.assertRaises(AssertionError, self.sl.acquire)
298 162c1c1f Guido Trotter
299 162c1c1f Guido Trotter
  def testDoubleLockingEtoS(self):
300 162c1c1f Guido Trotter
    self.sl.acquire()
301 162c1c1f Guido Trotter
    self.assertRaises(AssertionError, self.sl.acquire, shared=1)
302 162c1c1f Guido Trotter
303 162c1c1f Guido Trotter
  def testDoubleLockingStoS(self):
304 162c1c1f Guido Trotter
    self.sl.acquire(shared=1)
305 162c1c1f Guido Trotter
    self.assertRaises(AssertionError, self.sl.acquire, shared=1)
306 162c1c1f Guido Trotter
307 162c1c1f Guido Trotter
  def testDoubleLockingEtoE(self):
308 162c1c1f Guido Trotter
    self.sl.acquire()
309 162c1c1f Guido Trotter
    self.assertRaises(AssertionError, self.sl.acquire)
310 162c1c1f Guido Trotter
311 162c1c1f Guido Trotter
  # helper functions: called in a separate thread they acquire the lock, send
312 162c1c1f Guido Trotter
  # their identifier on the done queue, then release it.
313 162c1c1f Guido Trotter
  def _doItSharer(self):
314 a95fd5d7 Guido Trotter
    try:
315 a95fd5d7 Guido Trotter
      self.sl.acquire(shared=1)
316 a95fd5d7 Guido Trotter
      self.done.put('SHR')
317 a95fd5d7 Guido Trotter
      self.sl.release()
318 a95fd5d7 Guido Trotter
    except errors.LockError:
319 a95fd5d7 Guido Trotter
      self.done.put('ERR')
320 162c1c1f Guido Trotter
321 162c1c1f Guido Trotter
  def _doItExclusive(self):
322 a95fd5d7 Guido Trotter
    try:
323 a95fd5d7 Guido Trotter
      self.sl.acquire()
324 a95fd5d7 Guido Trotter
      self.done.put('EXC')
325 a95fd5d7 Guido Trotter
      self.sl.release()
326 a95fd5d7 Guido Trotter
    except errors.LockError:
327 a95fd5d7 Guido Trotter
      self.done.put('ERR')
328 a95fd5d7 Guido Trotter
329 a95fd5d7 Guido Trotter
  def _doItDelete(self):
330 a95fd5d7 Guido Trotter
    try:
331 4354ab03 Guido Trotter
      self.sl.delete()
332 a95fd5d7 Guido Trotter
      self.done.put('DEL')
333 a95fd5d7 Guido Trotter
    except errors.LockError:
334 a95fd5d7 Guido Trotter
      self.done.put('ERR')
335 162c1c1f Guido Trotter
336 162c1c1f Guido Trotter
  def testSharersCanCoexist(self):
337 162c1c1f Guido Trotter
    self.sl.acquire(shared=1)
338 84e344d4 Michael Hanselmann
    threading.Thread(target=self._doItSharer).start()
339 162c1c1f Guido Trotter
    self.assert_(self.done.get(True, 1))
340 162c1c1f Guido Trotter
    self.sl.release()
341 162c1c1f Guido Trotter
342 4607c978 Iustin Pop
  @_Repeat
343 162c1c1f Guido Trotter
  def testExclusiveBlocksExclusive(self):
344 162c1c1f Guido Trotter
    self.sl.acquire()
345 4607c978 Iustin Pop
    self._addThread(target=self._doItExclusive)
346 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
347 162c1c1f Guido Trotter
    self.sl.release()
348 4607c978 Iustin Pop
    self._waitThreads()
349 4607c978 Iustin Pop
    self.failUnlessEqual(self.done.get_nowait(), 'EXC')
350 162c1c1f Guido Trotter
351 4607c978 Iustin Pop
  @_Repeat
352 a95fd5d7 Guido Trotter
  def testExclusiveBlocksDelete(self):
353 a95fd5d7 Guido Trotter
    self.sl.acquire()
354 4607c978 Iustin Pop
    self._addThread(target=self._doItDelete)
355 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
356 a95fd5d7 Guido Trotter
    self.sl.release()
357 4607c978 Iustin Pop
    self._waitThreads()
358 4607c978 Iustin Pop
    self.failUnlessEqual(self.done.get_nowait(), 'DEL')
359 7f93570a Iustin Pop
    self.sl = locking.SharedLock(self.sl.name)
360 a95fd5d7 Guido Trotter
361 4607c978 Iustin Pop
  @_Repeat
362 162c1c1f Guido Trotter
  def testExclusiveBlocksSharer(self):
363 162c1c1f Guido Trotter
    self.sl.acquire()
364 4607c978 Iustin Pop
    self._addThread(target=self._doItSharer)
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(), 'SHR')
369 162c1c1f Guido Trotter
370 4607c978 Iustin Pop
  @_Repeat
371 162c1c1f Guido Trotter
  def testSharerBlocksExclusive(self):
372 162c1c1f Guido Trotter
    self.sl.acquire(shared=1)
373 4607c978 Iustin Pop
    self._addThread(target=self._doItExclusive)
374 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
375 162c1c1f Guido Trotter
    self.sl.release()
376 4607c978 Iustin Pop
    self._waitThreads()
377 4607c978 Iustin Pop
    self.failUnlessEqual(self.done.get_nowait(), 'EXC')
378 162c1c1f Guido Trotter
379 4607c978 Iustin Pop
  @_Repeat
380 a95fd5d7 Guido Trotter
  def testSharerBlocksDelete(self):
381 a95fd5d7 Guido Trotter
    self.sl.acquire(shared=1)
382 4607c978 Iustin Pop
    self._addThread(target=self._doItDelete)
383 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
384 a95fd5d7 Guido Trotter
    self.sl.release()
385 4607c978 Iustin Pop
    self._waitThreads()
386 4607c978 Iustin Pop
    self.failUnlessEqual(self.done.get_nowait(), 'DEL')
387 7f93570a Iustin Pop
    self.sl = locking.SharedLock(self.sl.name)
388 a95fd5d7 Guido Trotter
389 4607c978 Iustin Pop
  @_Repeat
390 162c1c1f Guido Trotter
  def testWaitingExclusiveBlocksSharer(self):
391 e6416152 Iustin Pop
    """SKIPPED testWaitingExclusiveBlockSharer"""
392 e6416152 Iustin Pop
    return
393 e6416152 Iustin Pop
394 162c1c1f Guido Trotter
    self.sl.acquire(shared=1)
395 162c1c1f Guido Trotter
    # the lock is acquired in shared mode...
396 4607c978 Iustin Pop
    self._addThread(target=self._doItExclusive)
397 162c1c1f Guido Trotter
    # ...but now an exclusive is waiting...
398 4607c978 Iustin Pop
    self._addThread(target=self._doItSharer)
399 162c1c1f Guido Trotter
    # ...so the sharer should be blocked as well
400 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
401 162c1c1f Guido Trotter
    self.sl.release()
402 4607c978 Iustin Pop
    self._waitThreads()
403 162c1c1f Guido Trotter
    # The exclusive passed before
404 4607c978 Iustin Pop
    self.failUnlessEqual(self.done.get_nowait(), 'EXC')
405 4607c978 Iustin Pop
    self.failUnlessEqual(self.done.get_nowait(), 'SHR')
406 162c1c1f Guido Trotter
407 4607c978 Iustin Pop
  @_Repeat
408 162c1c1f Guido Trotter
  def testWaitingSharerBlocksExclusive(self):
409 a143be68 Iustin Pop
    """SKIPPED testWaitingSharerBlocksExclusive"""
410 a143be68 Iustin Pop
    return
411 a143be68 Iustin Pop
412 162c1c1f Guido Trotter
    self.sl.acquire()
413 162c1c1f Guido Trotter
    # the lock is acquired in exclusive mode...
414 4607c978 Iustin Pop
    self._addThread(target=self._doItSharer)
415 162c1c1f Guido Trotter
    # ...but now a sharer is waiting...
416 4607c978 Iustin Pop
    self._addThread(target=self._doItExclusive)
417 162c1c1f Guido Trotter
    # ...the exclusive is waiting too...
418 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
419 162c1c1f Guido Trotter
    self.sl.release()
420 4607c978 Iustin Pop
    self._waitThreads()
421 162c1c1f Guido Trotter
    # The sharer passed before
422 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'SHR')
423 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'EXC')
424 162c1c1f Guido Trotter
425 a95fd5d7 Guido Trotter
  def testDelete(self):
426 a95fd5d7 Guido Trotter
    self.sl.delete()
427 a95fd5d7 Guido Trotter
    self.assertRaises(errors.LockError, self.sl.acquire)
428 84152b96 Guido Trotter
    self.assertRaises(errors.LockError, self.sl.acquire, shared=1)
429 a95fd5d7 Guido Trotter
    self.assertRaises(errors.LockError, self.sl.delete)
430 a95fd5d7 Guido Trotter
431 a66bd91b Michael Hanselmann
  def testDeleteTimeout(self):
432 a66bd91b Michael Hanselmann
    self.sl.delete(timeout=60)
433 a66bd91b Michael Hanselmann
434 84152b96 Guido Trotter
  def testNoDeleteIfSharer(self):
435 84152b96 Guido Trotter
    self.sl.acquire(shared=1)
436 84152b96 Guido Trotter
    self.assertRaises(AssertionError, self.sl.delete)
437 84152b96 Guido Trotter
438 4607c978 Iustin Pop
  @_Repeat
439 a95fd5d7 Guido Trotter
  def testDeletePendingSharersExclusiveDelete(self):
440 a95fd5d7 Guido Trotter
    self.sl.acquire()
441 4607c978 Iustin Pop
    self._addThread(target=self._doItSharer)
442 4607c978 Iustin Pop
    self._addThread(target=self._doItSharer)
443 4607c978 Iustin Pop
    self._addThread(target=self._doItExclusive)
444 4607c978 Iustin Pop
    self._addThread(target=self._doItDelete)
445 a95fd5d7 Guido Trotter
    self.sl.delete()
446 4607c978 Iustin Pop
    self._waitThreads()
447 4607c978 Iustin Pop
    # The threads who were pending return ERR
448 4607c978 Iustin Pop
    for _ in range(4):
449 4607c978 Iustin Pop
      self.assertEqual(self.done.get_nowait(), 'ERR')
450 7f93570a Iustin Pop
    self.sl = locking.SharedLock(self.sl.name)
451 a95fd5d7 Guido Trotter
452 4607c978 Iustin Pop
  @_Repeat
453 a95fd5d7 Guido Trotter
  def testDeletePendingDeleteExclusiveSharers(self):
454 a95fd5d7 Guido Trotter
    self.sl.acquire()
455 4607c978 Iustin Pop
    self._addThread(target=self._doItDelete)
456 4607c978 Iustin Pop
    self._addThread(target=self._doItExclusive)
457 4607c978 Iustin Pop
    self._addThread(target=self._doItSharer)
458 4607c978 Iustin Pop
    self._addThread(target=self._doItSharer)
459 a95fd5d7 Guido Trotter
    self.sl.delete()
460 4607c978 Iustin Pop
    self._waitThreads()
461 a95fd5d7 Guido Trotter
    # The two threads who were pending return both ERR
462 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'ERR')
463 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'ERR')
464 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'ERR')
465 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'ERR')
466 7f93570a Iustin Pop
    self.sl = locking.SharedLock(self.sl.name)
467 a95fd5d7 Guido Trotter
468 84e344d4 Michael Hanselmann
  @_Repeat
469 84e344d4 Michael Hanselmann
  def testExclusiveAcquireTimeout(self):
470 84e344d4 Michael Hanselmann
    for shared in [0, 1]:
471 008b92fa Michael Hanselmann
      on_queue = threading.Event()
472 008b92fa Michael Hanselmann
      release_exclusive = threading.Event()
473 008b92fa Michael Hanselmann
474 008b92fa Michael Hanselmann
      def _LockExclusive():
475 008b92fa Michael Hanselmann
        self.sl.acquire(shared=0, test_notify=on_queue.set)
476 008b92fa Michael Hanselmann
        self.done.put("A: start wait")
477 008b92fa Michael Hanselmann
        release_exclusive.wait()
478 008b92fa Michael Hanselmann
        self.done.put("A: end wait")
479 008b92fa Michael Hanselmann
        self.sl.release()
480 008b92fa Michael Hanselmann
481 008b92fa Michael Hanselmann
      # Start thread to hold lock in exclusive mode
482 008b92fa Michael Hanselmann
      self._addThread(target=_LockExclusive)
483 84e344d4 Michael Hanselmann
484 008b92fa Michael Hanselmann
      # Wait for wait to begin
485 008b92fa Michael Hanselmann
      self.assertEqual(self.done.get(timeout=60), "A: start wait")
486 008b92fa Michael Hanselmann
487 008b92fa Michael Hanselmann
      # Wait up to 60s to get lock, but release exclusive lock as soon as we're
488 008b92fa Michael Hanselmann
      # on the queue
489 008b92fa Michael Hanselmann
      self.failUnless(self.sl.acquire(shared=shared, timeout=60,
490 008b92fa Michael Hanselmann
                                      test_notify=release_exclusive.set))
491 2042aa94 Michael Hanselmann
492 84e344d4 Michael Hanselmann
      self.done.put("got 2nd")
493 84e344d4 Michael Hanselmann
      self.sl.release()
494 84e344d4 Michael Hanselmann
495 84e344d4 Michael Hanselmann
      self._waitThreads()
496 84e344d4 Michael Hanselmann
497 008b92fa Michael Hanselmann
      self.assertEqual(self.done.get_nowait(), "A: end wait")
498 84e344d4 Michael Hanselmann
      self.assertEqual(self.done.get_nowait(), "got 2nd")
499 84e344d4 Michael Hanselmann
      self.assertRaises(Queue.Empty, self.done.get_nowait)
500 84e344d4 Michael Hanselmann
501 84e344d4 Michael Hanselmann
  @_Repeat
502 84e344d4 Michael Hanselmann
  def testAcquireExpiringTimeout(self):
503 84e344d4 Michael Hanselmann
    def _AcquireWithTimeout(shared, timeout):
504 84e344d4 Michael Hanselmann
      if not self.sl.acquire(shared=shared, timeout=timeout):
505 84e344d4 Michael Hanselmann
        self.done.put("timeout")
506 84e344d4 Michael Hanselmann
507 84e344d4 Michael Hanselmann
    for shared in [0, 1]:
508 84e344d4 Michael Hanselmann
      # Lock exclusively
509 84e344d4 Michael Hanselmann
      self.sl.acquire()
510 84e344d4 Michael Hanselmann
511 84e344d4 Michael Hanselmann
      # Start shared acquires with timeout between 0 and 20 ms
512 f1501b3f Michael Hanselmann
      for i in range(11):
513 84e344d4 Michael Hanselmann
        self._addThread(target=_AcquireWithTimeout,
514 84e344d4 Michael Hanselmann
                        args=(shared, i * 2.0 / 1000.0))
515 84e344d4 Michael Hanselmann
516 84e344d4 Michael Hanselmann
      # Wait for threads to finish (makes sure the acquire timeout expires
517 84e344d4 Michael Hanselmann
      # before releasing the lock)
518 84e344d4 Michael Hanselmann
      self._waitThreads()
519 84e344d4 Michael Hanselmann
520 84e344d4 Michael Hanselmann
      # Release lock
521 84e344d4 Michael Hanselmann
      self.sl.release()
522 84e344d4 Michael Hanselmann
523 f1501b3f Michael Hanselmann
      for _ in range(11):
524 84e344d4 Michael Hanselmann
        self.assertEqual(self.done.get_nowait(), "timeout")
525 84e344d4 Michael Hanselmann
526 84e344d4 Michael Hanselmann
      self.assertRaises(Queue.Empty, self.done.get_nowait)
527 84e344d4 Michael Hanselmann
528 84e344d4 Michael Hanselmann
  @_Repeat
529 84e344d4 Michael Hanselmann
  def testSharedSkipExclusiveAcquires(self):
530 84e344d4 Michael Hanselmann
    # Tests whether shared acquires jump in front of exclusive acquires in the
531 84e344d4 Michael Hanselmann
    # queue.
532 84e344d4 Michael Hanselmann
533 008b92fa Michael Hanselmann
    def _Acquire(shared, name, notify_ev, wait_ev):
534 008b92fa Michael Hanselmann
      if notify_ev:
535 008b92fa Michael Hanselmann
        notify_fn = notify_ev.set
536 008b92fa Michael Hanselmann
      else:
537 008b92fa Michael Hanselmann
        notify_fn = None
538 84e344d4 Michael Hanselmann
539 008b92fa Michael Hanselmann
      if wait_ev:
540 008b92fa Michael Hanselmann
        wait_ev.wait()
541 008b92fa Michael Hanselmann
542 008b92fa Michael Hanselmann
      if not self.sl.acquire(shared=shared, test_notify=notify_fn):
543 84e344d4 Michael Hanselmann
        return
544 84e344d4 Michael Hanselmann
545 84e344d4 Michael Hanselmann
      self.done.put(name)
546 84e344d4 Michael Hanselmann
      self.sl.release()
547 84e344d4 Michael Hanselmann
548 008b92fa Michael Hanselmann
    # Get exclusive lock while we fill the queue
549 008b92fa Michael Hanselmann
    self.sl.acquire()
550 84e344d4 Michael Hanselmann
551 008b92fa Michael Hanselmann
    shrcnt1 = 5
552 008b92fa Michael Hanselmann
    shrcnt2 = 7
553 008b92fa Michael Hanselmann
    shrcnt3 = 9
554 008b92fa Michael Hanselmann
    shrcnt4 = 2
555 84e344d4 Michael Hanselmann
556 008b92fa Michael Hanselmann
    # Add acquires using threading.Event for synchronization. They'll be
557 008b92fa Michael Hanselmann
    # acquired exactly in the order defined in this list.
558 008b92fa Michael Hanselmann
    acquires = (shrcnt1 * [(1, "shared 1")] +
559 008b92fa Michael Hanselmann
                3 * [(0, "exclusive 1")] +
560 008b92fa Michael Hanselmann
                shrcnt2 * [(1, "shared 2")] +
561 008b92fa Michael Hanselmann
                shrcnt3 * [(1, "shared 3")] +
562 008b92fa Michael Hanselmann
                shrcnt4 * [(1, "shared 4")] +
563 008b92fa Michael Hanselmann
                3 * [(0, "exclusive 2")])
564 84e344d4 Michael Hanselmann
565 008b92fa Michael Hanselmann
    ev_cur = None
566 008b92fa Michael Hanselmann
    ev_prev = None
567 008b92fa Michael Hanselmann
568 008b92fa Michael Hanselmann
    for args in acquires:
569 008b92fa Michael Hanselmann
      ev_cur = threading.Event()
570 008b92fa Michael Hanselmann
      self._addThread(target=_Acquire, args=args + (ev_cur, ev_prev))
571 008b92fa Michael Hanselmann
      ev_prev = ev_cur
572 008b92fa Michael Hanselmann
573 008b92fa Michael Hanselmann
    # Wait for last acquire to start
574 008b92fa Michael Hanselmann
    ev_prev.wait()
575 84e344d4 Michael Hanselmann
576 84e344d4 Michael Hanselmann
    # Expect 6 pending exclusive acquires and 1 for all shared acquires
577 008b92fa Michael Hanselmann
    # together
578 008b92fa Michael Hanselmann
    self.assertEqual(self.sl._count_pending(), 7)
579 84e344d4 Michael Hanselmann
580 84e344d4 Michael Hanselmann
    # Release exclusive lock and wait
581 84e344d4 Michael Hanselmann
    self.sl.release()
582 84e344d4 Michael Hanselmann
583 84e344d4 Michael Hanselmann
    self._waitThreads()
584 84e344d4 Michael Hanselmann
585 84e344d4 Michael Hanselmann
    # Check sequence
586 008b92fa Michael Hanselmann
    for _ in range(shrcnt1 + shrcnt2 + shrcnt3 + shrcnt4):
587 84e344d4 Michael Hanselmann
      # Shared locks aren't guaranteed to be notified in order, but they'll be
588 84e344d4 Michael Hanselmann
      # first
589 2042aa94 Michael Hanselmann
      tmp = self.done.get_nowait()
590 008b92fa Michael Hanselmann
      if tmp == "shared 1":
591 008b92fa Michael Hanselmann
        shrcnt1 -= 1
592 008b92fa Michael Hanselmann
      elif tmp == "shared 2":
593 008b92fa Michael Hanselmann
        shrcnt2 -= 1
594 008b92fa Michael Hanselmann
      elif tmp == "shared 3":
595 008b92fa Michael Hanselmann
        shrcnt3 -= 1
596 008b92fa Michael Hanselmann
      elif tmp == "shared 4":
597 008b92fa Michael Hanselmann
        shrcnt4 -= 1
598 008b92fa Michael Hanselmann
    self.assertEqual(shrcnt1, 0)
599 008b92fa Michael Hanselmann
    self.assertEqual(shrcnt2, 0)
600 008b92fa Michael Hanselmann
    self.assertEqual(shrcnt3, 0)
601 008b92fa Michael Hanselmann
    self.assertEqual(shrcnt3, 0)
602 84e344d4 Michael Hanselmann
603 f1501b3f Michael Hanselmann
    for _ in range(3):
604 008b92fa Michael Hanselmann
      self.assertEqual(self.done.get_nowait(), "exclusive 1")
605 84e344d4 Michael Hanselmann
606 f1501b3f Michael Hanselmann
    for _ in range(3):
607 008b92fa Michael Hanselmann
      self.assertEqual(self.done.get_nowait(), "exclusive 2")
608 84e344d4 Michael Hanselmann
609 84e344d4 Michael Hanselmann
    self.assertRaises(Queue.Empty, self.done.get_nowait)
610 84e344d4 Michael Hanselmann
611 84e344d4 Michael Hanselmann
  @_Repeat
612 84e344d4 Michael Hanselmann
  def testMixedAcquireTimeout(self):
613 51e3bb92 Michael Hanselmann
    sync = threading.Event()
614 84e344d4 Michael Hanselmann
615 84e344d4 Michael Hanselmann
    def _AcquireShared(ev):
616 84e344d4 Michael Hanselmann
      if not self.sl.acquire(shared=1, timeout=None):
617 84e344d4 Michael Hanselmann
        return
618 84e344d4 Michael Hanselmann
619 84e344d4 Michael Hanselmann
      self.done.put("shared")
620 84e344d4 Michael Hanselmann
621 84e344d4 Michael Hanselmann
      # Notify main thread
622 84e344d4 Michael Hanselmann
      ev.set()
623 84e344d4 Michael Hanselmann
624 51e3bb92 Michael Hanselmann
      # Wait for notification from main thread
625 51e3bb92 Michael Hanselmann
      sync.wait()
626 84e344d4 Michael Hanselmann
627 84e344d4 Michael Hanselmann
      # Release lock
628 84e344d4 Michael Hanselmann
      self.sl.release()
629 84e344d4 Michael Hanselmann
630 84e344d4 Michael Hanselmann
    acquires = []
631 f1501b3f Michael Hanselmann
    for _ in range(3):
632 84e344d4 Michael Hanselmann
      ev = threading.Event()
633 84e344d4 Michael Hanselmann
      self._addThread(target=_AcquireShared, args=(ev, ))
634 84e344d4 Michael Hanselmann
      acquires.append(ev)
635 84e344d4 Michael Hanselmann
636 84e344d4 Michael Hanselmann
    # Wait for all acquires to finish
637 84e344d4 Michael Hanselmann
    for i in acquires:
638 84e344d4 Michael Hanselmann
      i.wait()
639 84e344d4 Michael Hanselmann
640 84e344d4 Michael Hanselmann
    self.assertEqual(self.sl._count_pending(), 0)
641 84e344d4 Michael Hanselmann
642 84e344d4 Michael Hanselmann
    # Try to get exclusive lock
643 84e344d4 Michael Hanselmann
    self.failIf(self.sl.acquire(shared=0, timeout=0.02))
644 84e344d4 Michael Hanselmann
645 84e344d4 Michael Hanselmann
    # Acquire exclusive without timeout
646 51e3bb92 Michael Hanselmann
    exclsync = threading.Event()
647 84e344d4 Michael Hanselmann
    exclev = threading.Event()
648 84e344d4 Michael Hanselmann
649 84e344d4 Michael Hanselmann
    def _AcquireExclusive():
650 84e344d4 Michael Hanselmann
      if not self.sl.acquire(shared=0):
651 84e344d4 Michael Hanselmann
        return
652 84e344d4 Michael Hanselmann
653 84e344d4 Michael Hanselmann
      self.done.put("exclusive")
654 84e344d4 Michael Hanselmann
655 84e344d4 Michael Hanselmann
      # Notify main thread
656 84e344d4 Michael Hanselmann
      exclev.set()
657 84e344d4 Michael Hanselmann
658 51e3bb92 Michael Hanselmann
      # Wait for notification from main thread
659 51e3bb92 Michael Hanselmann
      exclsync.wait()
660 84e344d4 Michael Hanselmann
661 84e344d4 Michael Hanselmann
      self.sl.release()
662 84e344d4 Michael Hanselmann
663 84e344d4 Michael Hanselmann
    self._addThread(target=_AcquireExclusive)
664 84e344d4 Michael Hanselmann
665 84e344d4 Michael Hanselmann
    # Try to get exclusive lock
666 84e344d4 Michael Hanselmann
    self.failIf(self.sl.acquire(shared=0, timeout=0.02))
667 84e344d4 Michael Hanselmann
668 84e344d4 Michael Hanselmann
    # Make all shared holders release their locks
669 51e3bb92 Michael Hanselmann
    sync.set()
670 84e344d4 Michael Hanselmann
671 84e344d4 Michael Hanselmann
    # Wait for exclusive acquire to succeed
672 84e344d4 Michael Hanselmann
    exclev.wait()
673 84e344d4 Michael Hanselmann
674 84e344d4 Michael Hanselmann
    self.assertEqual(self.sl._count_pending(), 0)
675 84e344d4 Michael Hanselmann
676 84e344d4 Michael Hanselmann
    # Try to get exclusive lock
677 84e344d4 Michael Hanselmann
    self.failIf(self.sl.acquire(shared=0, timeout=0.02))
678 84e344d4 Michael Hanselmann
679 84e344d4 Michael Hanselmann
    def _AcquireSharedSimple():
680 84e344d4 Michael Hanselmann
      if self.sl.acquire(shared=1, timeout=None):
681 84e344d4 Michael Hanselmann
        self.done.put("shared2")
682 84e344d4 Michael Hanselmann
        self.sl.release()
683 84e344d4 Michael Hanselmann
684 f1501b3f Michael Hanselmann
    for _ in range(10):
685 84e344d4 Michael Hanselmann
      self._addThread(target=_AcquireSharedSimple)
686 84e344d4 Michael Hanselmann
687 84e344d4 Michael Hanselmann
    # Tell exclusive lock to release
688 51e3bb92 Michael Hanselmann
    exclsync.set()
689 84e344d4 Michael Hanselmann
690 84e344d4 Michael Hanselmann
    # Wait for everything to finish
691 84e344d4 Michael Hanselmann
    self._waitThreads()
692 84e344d4 Michael Hanselmann
693 84e344d4 Michael Hanselmann
    self.assertEqual(self.sl._count_pending(), 0)
694 84e344d4 Michael Hanselmann
695 84e344d4 Michael Hanselmann
    # Check sequence
696 f1501b3f Michael Hanselmann
    for _ in range(3):
697 84e344d4 Michael Hanselmann
      self.assertEqual(self.done.get_nowait(), "shared")
698 84e344d4 Michael Hanselmann
699 84e344d4 Michael Hanselmann
    self.assertEqual(self.done.get_nowait(), "exclusive")
700 84e344d4 Michael Hanselmann
701 f1501b3f Michael Hanselmann
    for _ in range(10):
702 84e344d4 Michael Hanselmann
      self.assertEqual(self.done.get_nowait(), "shared2")
703 84e344d4 Michael Hanselmann
704 84e344d4 Michael Hanselmann
    self.assertRaises(Queue.Empty, self.done.get_nowait)
705 84e344d4 Michael Hanselmann
706 887c7aa6 Michael Hanselmann
  def testPriority(self):
707 887c7aa6 Michael Hanselmann
    # Acquire in exclusive mode
708 887c7aa6 Michael Hanselmann
    self.assert_(self.sl.acquire(shared=0))
709 887c7aa6 Michael Hanselmann
710 887c7aa6 Michael Hanselmann
    # Queue acquires
711 887c7aa6 Michael Hanselmann
    def _Acquire(prev, next, shared, priority, result):
712 887c7aa6 Michael Hanselmann
      prev.wait()
713 887c7aa6 Michael Hanselmann
      self.sl.acquire(shared=shared, priority=priority, test_notify=next.set)
714 887c7aa6 Michael Hanselmann
      try:
715 887c7aa6 Michael Hanselmann
        self.done.put(result)
716 887c7aa6 Michael Hanselmann
      finally:
717 887c7aa6 Michael Hanselmann
        self.sl.release()
718 887c7aa6 Michael Hanselmann
719 887c7aa6 Michael Hanselmann
    counter = itertools.count(0)
720 887c7aa6 Michael Hanselmann
    priorities = range(-20, 30)
721 887c7aa6 Michael Hanselmann
    first = threading.Event()
722 887c7aa6 Michael Hanselmann
    prev = first
723 887c7aa6 Michael Hanselmann
724 887c7aa6 Michael Hanselmann
    # Data structure:
725 887c7aa6 Michael Hanselmann
    # {
726 887c7aa6 Michael Hanselmann
    #   priority:
727 887c7aa6 Michael Hanselmann
    #     [(shared/exclusive, set(acquire names), set(pending threads)),
728 887c7aa6 Michael Hanselmann
    #      (shared/exclusive, ...),
729 887c7aa6 Michael Hanselmann
    #      ...,
730 887c7aa6 Michael Hanselmann
    #     ],
731 887c7aa6 Michael Hanselmann
    # }
732 887c7aa6 Michael Hanselmann
    perprio = {}
733 887c7aa6 Michael Hanselmann
734 887c7aa6 Michael Hanselmann
    # References shared acquire per priority in L{perprio}. Data structure:
735 887c7aa6 Michael Hanselmann
    # {
736 887c7aa6 Michael Hanselmann
    #   priority: (shared=1, set(acquire names), set(pending threads)),
737 887c7aa6 Michael Hanselmann
    # }
738 887c7aa6 Michael Hanselmann
    prioshared = {}
739 887c7aa6 Michael Hanselmann
740 887c7aa6 Michael Hanselmann
    for seed in [4979, 9523, 14902, 32440]:
741 887c7aa6 Michael Hanselmann
      # Use a deterministic random generator
742 887c7aa6 Michael Hanselmann
      rnd = random.Random(seed)
743 887c7aa6 Michael Hanselmann
      for priority in [rnd.choice(priorities) for _ in range(30)]:
744 887c7aa6 Michael Hanselmann
        modes = [0, 1]
745 887c7aa6 Michael Hanselmann
        rnd.shuffle(modes)
746 887c7aa6 Michael Hanselmann
        for shared in modes:
747 887c7aa6 Michael Hanselmann
          # Unique name
748 887c7aa6 Michael Hanselmann
          acqname = "%s/shr=%s/prio=%s" % (counter.next(), shared, priority)
749 887c7aa6 Michael Hanselmann
750 887c7aa6 Michael Hanselmann
          ev = threading.Event()
751 887c7aa6 Michael Hanselmann
          thread = self._addThread(target=_Acquire,
752 887c7aa6 Michael Hanselmann
                                   args=(prev, ev, shared, priority, acqname))
753 887c7aa6 Michael Hanselmann
          prev = ev
754 887c7aa6 Michael Hanselmann
755 887c7aa6 Michael Hanselmann
          # Record expected aqcuire, see above for structure
756 887c7aa6 Michael Hanselmann
          data = (shared, set([acqname]), set([thread]))
757 887c7aa6 Michael Hanselmann
          priolist = perprio.setdefault(priority, [])
758 887c7aa6 Michael Hanselmann
          if shared:
759 887c7aa6 Michael Hanselmann
            priosh = prioshared.get(priority, None)
760 887c7aa6 Michael Hanselmann
            if priosh:
761 887c7aa6 Michael Hanselmann
              # Shared acquires are merged
762 887c7aa6 Michael Hanselmann
              for i, j in zip(priosh[1:], data[1:]):
763 887c7aa6 Michael Hanselmann
                i.update(j)
764 887c7aa6 Michael Hanselmann
              assert data[0] == priosh[0]
765 887c7aa6 Michael Hanselmann
            else:
766 887c7aa6 Michael Hanselmann
              prioshared[priority] = data
767 887c7aa6 Michael Hanselmann
              priolist.append(data)
768 887c7aa6 Michael Hanselmann
          else:
769 887c7aa6 Michael Hanselmann
            priolist.append(data)
770 887c7aa6 Michael Hanselmann
771 887c7aa6 Michael Hanselmann
    # Start all acquires and wait for them
772 887c7aa6 Michael Hanselmann
    first.set()
773 887c7aa6 Michael Hanselmann
    prev.wait()
774 887c7aa6 Michael Hanselmann
775 887c7aa6 Michael Hanselmann
    # Check lock information
776 887c7aa6 Michael Hanselmann
    self.assertEqual(self.sl.GetInfo(["name"]), [self.sl.name])
777 887c7aa6 Michael Hanselmann
    self.assertEqual(self.sl.GetInfo(["mode", "owner"]),
778 887c7aa6 Michael Hanselmann
                     ["exclusive", [threading.currentThread().getName()]])
779 887c7aa6 Michael Hanselmann
    self.assertEqual(self.sl.GetInfo(["name", "pending"]),
780 887c7aa6 Michael Hanselmann
                     [self.sl.name,
781 887c7aa6 Michael Hanselmann
                      [(["exclusive", "shared"][int(bool(shared))],
782 887c7aa6 Michael Hanselmann
                        sorted([t.getName() for t in threads]))
783 887c7aa6 Michael Hanselmann
                       for acquires in [perprio[i]
784 887c7aa6 Michael Hanselmann
                                        for i in sorted(perprio.keys())]
785 887c7aa6 Michael Hanselmann
                       for (shared, _, threads) in acquires]])
786 887c7aa6 Michael Hanselmann
787 887c7aa6 Michael Hanselmann
    # Let threads acquire the lock
788 887c7aa6 Michael Hanselmann
    self.sl.release()
789 887c7aa6 Michael Hanselmann
790 887c7aa6 Michael Hanselmann
    # Wait for everything to finish
791 887c7aa6 Michael Hanselmann
    self._waitThreads()
792 887c7aa6 Michael Hanselmann
793 887c7aa6 Michael Hanselmann
    self.assert_(self.sl._check_empty())
794 887c7aa6 Michael Hanselmann
795 887c7aa6 Michael Hanselmann
    # Check acquires by priority
796 887c7aa6 Michael Hanselmann
    for acquires in [perprio[i] for i in sorted(perprio.keys())]:
797 887c7aa6 Michael Hanselmann
      for (_, names, _) in acquires:
798 887c7aa6 Michael Hanselmann
        # For shared acquires, the set will contain 1..n entries. For exclusive
799 887c7aa6 Michael Hanselmann
        # acquires only one.
800 887c7aa6 Michael Hanselmann
        while names:
801 887c7aa6 Michael Hanselmann
          names.remove(self.done.get_nowait())
802 887c7aa6 Michael Hanselmann
      self.assertFalse(compat.any(names for (_, names, _) in acquires))
803 887c7aa6 Michael Hanselmann
804 887c7aa6 Michael Hanselmann
    self.assertRaises(Queue.Empty, self.done.get_nowait)
805 887c7aa6 Michael Hanselmann
806 162c1c1f Guido Trotter
807 1a4e32d0 Guido Trotter
class TestSharedLockInCondition(_ThreadedTestCase):
808 1a4e32d0 Guido Trotter
  """SharedLock as a condition lock tests"""
809 1a4e32d0 Guido Trotter
810 1a4e32d0 Guido Trotter
  def setUp(self):
811 1a4e32d0 Guido Trotter
    _ThreadedTestCase.setUp(self)
812 7f93570a Iustin Pop
    self.sl = locking.SharedLock("TestSharedLockInCondition")
813 7f890059 Guido Trotter
    self.setCondition()
814 7f890059 Guido Trotter
815 7f890059 Guido Trotter
  def setCondition(self):
816 1a4e32d0 Guido Trotter
    self.cond = threading.Condition(self.sl)
817 1a4e32d0 Guido Trotter
818 1a4e32d0 Guido Trotter
  def testKeepMode(self):
819 1a4e32d0 Guido Trotter
    self.cond.acquire(shared=1)
820 1a4e32d0 Guido Trotter
    self.assert_(self.sl._is_owned(shared=1))
821 1a4e32d0 Guido Trotter
    self.cond.wait(0)
822 1a4e32d0 Guido Trotter
    self.assert_(self.sl._is_owned(shared=1))
823 1a4e32d0 Guido Trotter
    self.cond.release()
824 1a4e32d0 Guido Trotter
    self.cond.acquire(shared=0)
825 1a4e32d0 Guido Trotter
    self.assert_(self.sl._is_owned(shared=0))
826 1a4e32d0 Guido Trotter
    self.cond.wait(0)
827 1a4e32d0 Guido Trotter
    self.assert_(self.sl._is_owned(shared=0))
828 1a4e32d0 Guido Trotter
    self.cond.release()
829 1a4e32d0 Guido Trotter
830 1a4e32d0 Guido Trotter
831 7f890059 Guido Trotter
class TestSharedLockInPipeCondition(TestSharedLockInCondition):
832 7f890059 Guido Trotter
  """SharedLock as a pipe condition lock tests"""
833 7f890059 Guido Trotter
834 7f890059 Guido Trotter
  def setCondition(self):
835 7f890059 Guido Trotter
    self.cond = locking.PipeCondition(self.sl)
836 7f890059 Guido Trotter
837 7f890059 Guido Trotter
838 4607c978 Iustin Pop
class TestSSynchronizedDecorator(_ThreadedTestCase):
839 42a999d1 Guido Trotter
  """Shared Lock Synchronized decorator test"""
840 42a999d1 Guido Trotter
841 42a999d1 Guido Trotter
  def setUp(self):
842 4607c978 Iustin Pop
    _ThreadedTestCase.setUp(self)
843 42a999d1 Guido Trotter
844 42a999d1 Guido Trotter
  @locking.ssynchronized(_decoratorlock)
845 42a999d1 Guido Trotter
  def _doItExclusive(self):
846 42a999d1 Guido Trotter
    self.assert_(_decoratorlock._is_owned())
847 42a999d1 Guido Trotter
    self.done.put('EXC')
848 42a999d1 Guido Trotter
849 42a999d1 Guido Trotter
  @locking.ssynchronized(_decoratorlock, shared=1)
850 42a999d1 Guido Trotter
  def _doItSharer(self):
851 42a999d1 Guido Trotter
    self.assert_(_decoratorlock._is_owned(shared=1))
852 42a999d1 Guido Trotter
    self.done.put('SHR')
853 42a999d1 Guido Trotter
854 42a999d1 Guido Trotter
  def testDecoratedFunctions(self):
855 42a999d1 Guido Trotter
    self._doItExclusive()
856 158206e0 Manuel Franceschini
    self.assertFalse(_decoratorlock._is_owned())
857 42a999d1 Guido Trotter
    self._doItSharer()
858 158206e0 Manuel Franceschini
    self.assertFalse(_decoratorlock._is_owned())
859 42a999d1 Guido Trotter
860 42a999d1 Guido Trotter
  def testSharersCanCoexist(self):
861 42a999d1 Guido Trotter
    _decoratorlock.acquire(shared=1)
862 84e344d4 Michael Hanselmann
    threading.Thread(target=self._doItSharer).start()
863 42a999d1 Guido Trotter
    self.assert_(self.done.get(True, 1))
864 42a999d1 Guido Trotter
    _decoratorlock.release()
865 42a999d1 Guido Trotter
866 4607c978 Iustin Pop
  @_Repeat
867 42a999d1 Guido Trotter
  def testExclusiveBlocksExclusive(self):
868 42a999d1 Guido Trotter
    _decoratorlock.acquire()
869 4607c978 Iustin Pop
    self._addThread(target=self._doItExclusive)
870 42a999d1 Guido Trotter
    # give it a bit of time to check that it's not actually doing anything
871 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
872 42a999d1 Guido Trotter
    _decoratorlock.release()
873 4607c978 Iustin Pop
    self._waitThreads()
874 4607c978 Iustin Pop
    self.failUnlessEqual(self.done.get_nowait(), 'EXC')
875 42a999d1 Guido Trotter
876 4607c978 Iustin Pop
  @_Repeat
877 42a999d1 Guido Trotter
  def testExclusiveBlocksSharer(self):
878 42a999d1 Guido Trotter
    _decoratorlock.acquire()
879 4607c978 Iustin Pop
    self._addThread(target=self._doItSharer)
880 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
881 42a999d1 Guido Trotter
    _decoratorlock.release()
882 4607c978 Iustin Pop
    self._waitThreads()
883 4607c978 Iustin Pop
    self.failUnlessEqual(self.done.get_nowait(), 'SHR')
884 42a999d1 Guido Trotter
885 4607c978 Iustin Pop
  @_Repeat
886 42a999d1 Guido Trotter
  def testSharerBlocksExclusive(self):
887 42a999d1 Guido Trotter
    _decoratorlock.acquire(shared=1)
888 4607c978 Iustin Pop
    self._addThread(target=self._doItExclusive)
889 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
890 42a999d1 Guido Trotter
    _decoratorlock.release()
891 4607c978 Iustin Pop
    self._waitThreads()
892 4607c978 Iustin Pop
    self.failUnlessEqual(self.done.get_nowait(), 'EXC')
893 42a999d1 Guido Trotter
894 42a999d1 Guido Trotter
895 4607c978 Iustin Pop
class TestLockSet(_ThreadedTestCase):
896 aaae9bc0 Guido Trotter
  """LockSet tests"""
897 aaae9bc0 Guido Trotter
898 aaae9bc0 Guido Trotter
  def setUp(self):
899 4607c978 Iustin Pop
    _ThreadedTestCase.setUp(self)
900 4607c978 Iustin Pop
    self._setUpLS()
901 aaae9bc0 Guido Trotter
902 4607c978 Iustin Pop
  def _setUpLS(self):
903 4607c978 Iustin Pop
    """Helper to (re)initialize the lock set"""
904 4607c978 Iustin Pop
    self.resources = ['one', 'two', 'three']
905 7f93570a Iustin Pop
    self.ls = locking.LockSet(self.resources, "TestLockSet")
906 4607c978 Iustin Pop
907 aaae9bc0 Guido Trotter
  def testResources(self):
908 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._names(), set(self.resources))
909 7f93570a Iustin Pop
    newls = locking.LockSet([], "TestLockSet.testResources")
910 aaae9bc0 Guido Trotter
    self.assertEquals(newls._names(), set())
911 aaae9bc0 Guido Trotter
912 aaae9bc0 Guido Trotter
  def testAcquireRelease(self):
913 0cc00929 Guido Trotter
    self.assert_(self.ls.acquire('one'))
914 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['one']))
915 aaae9bc0 Guido Trotter
    self.ls.release()
916 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set())
917 0cc00929 Guido Trotter
    self.assertEquals(self.ls.acquire(['one']), set(['one']))
918 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['one']))
919 aaae9bc0 Guido Trotter
    self.ls.release()
920 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set())
921 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'two', 'three'])
922 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['one', 'two', 'three']))
923 aaae9bc0 Guido Trotter
    self.ls.release('one')
924 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['two', 'three']))
925 aaae9bc0 Guido Trotter
    self.ls.release(['three'])
926 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['two']))
927 aaae9bc0 Guido Trotter
    self.ls.release()
928 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set())
929 0cc00929 Guido Trotter
    self.assertEquals(self.ls.acquire(['one', 'three']), set(['one', 'three']))
930 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['one', 'three']))
931 aaae9bc0 Guido Trotter
    self.ls.release()
932 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set())
933 aaae9bc0 Guido Trotter
934 aaae9bc0 Guido Trotter
  def testNoDoubleAcquire(self):
935 aaae9bc0 Guido Trotter
    self.ls.acquire('one')
936 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.acquire, 'one')
937 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.acquire, ['two'])
938 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.acquire, ['two', 'three'])
939 aaae9bc0 Guido Trotter
    self.ls.release()
940 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'three'])
941 aaae9bc0 Guido Trotter
    self.ls.release('one')
942 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.acquire, ['two'])
943 aaae9bc0 Guido Trotter
    self.ls.release('three')
944 aaae9bc0 Guido Trotter
945 aaae9bc0 Guido Trotter
  def testNoWrongRelease(self):
946 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.release)
947 aaae9bc0 Guido Trotter
    self.ls.acquire('one')
948 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.release, 'two')
949 aaae9bc0 Guido Trotter
950 aaae9bc0 Guido Trotter
  def testAddRemove(self):
951 aaae9bc0 Guido Trotter
    self.ls.add('four')
952 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set())
953 aaae9bc0 Guido Trotter
    self.assert_('four' in self.ls._names())
954 aaae9bc0 Guido Trotter
    self.ls.add(['five', 'six', 'seven'], acquired=1)
955 aaae9bc0 Guido Trotter
    self.assert_('five' in self.ls._names())
956 aaae9bc0 Guido Trotter
    self.assert_('six' in self.ls._names())
957 aaae9bc0 Guido Trotter
    self.assert_('seven' in self.ls._names())
958 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['five', 'six', 'seven']))
959 3f404fc5 Guido Trotter
    self.assertEquals(self.ls.remove(['five', 'six']), ['five', 'six'])
960 aaae9bc0 Guido Trotter
    self.assert_('five' not in self.ls._names())
961 aaae9bc0 Guido Trotter
    self.assert_('six' not in self.ls._names())
962 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['seven']))
963 d2aff862 Guido Trotter
    self.assertRaises(AssertionError, self.ls.add, 'eight', acquired=1)
964 aaae9bc0 Guido Trotter
    self.ls.remove('seven')
965 aaae9bc0 Guido Trotter
    self.assert_('seven' not in self.ls._names())
966 d2aff862 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set([]))
967 d2aff862 Guido Trotter
    self.ls.acquire(None, shared=1)
968 d2aff862 Guido Trotter
    self.assertRaises(AssertionError, self.ls.add, 'eight')
969 d2aff862 Guido Trotter
    self.ls.release()
970 d2aff862 Guido Trotter
    self.ls.acquire(None)
971 d2aff862 Guido Trotter
    self.ls.add('eight', acquired=1)
972 d2aff862 Guido Trotter
    self.assert_('eight' in self.ls._names())
973 d2aff862 Guido Trotter
    self.assert_('eight' in self.ls._list_owned())
974 d2aff862 Guido Trotter
    self.ls.add('nine')
975 d2aff862 Guido Trotter
    self.assert_('nine' in self.ls._names())
976 d2aff862 Guido Trotter
    self.assert_('nine' not in self.ls._list_owned())
977 aaae9bc0 Guido Trotter
    self.ls.release()
978 aaae9bc0 Guido Trotter
    self.ls.remove(['two'])
979 aaae9bc0 Guido Trotter
    self.assert_('two' not in self.ls._names())
980 aaae9bc0 Guido Trotter
    self.ls.acquire('three')
981 3f404fc5 Guido Trotter
    self.assertEquals(self.ls.remove(['three']), ['three'])
982 aaae9bc0 Guido Trotter
    self.assert_('three' not in self.ls._names())
983 3f404fc5 Guido Trotter
    self.assertEquals(self.ls.remove('three'), [])
984 3f404fc5 Guido Trotter
    self.assertEquals(self.ls.remove(['one', 'three', 'six']), ['one'])
985 aaae9bc0 Guido Trotter
    self.assert_('one' not in self.ls._names())
986 aaae9bc0 Guido Trotter
987 aaae9bc0 Guido Trotter
  def testRemoveNonBlocking(self):
988 aaae9bc0 Guido Trotter
    self.ls.acquire('one')
989 5e0a6daf Michael Hanselmann
    self.assertEquals(self.ls.remove('one'), ['one'])
990 aaae9bc0 Guido Trotter
    self.ls.acquire(['two', 'three'])
991 5e0a6daf Michael Hanselmann
    self.assertEquals(self.ls.remove(['two', 'three']),
992 3f404fc5 Guido Trotter
                      ['two', 'three'])
993 aaae9bc0 Guido Trotter
994 aaae9bc0 Guido Trotter
  def testNoDoubleAdd(self):
995 aaae9bc0 Guido Trotter
    self.assertRaises(errors.LockError, self.ls.add, 'two')
996 aaae9bc0 Guido Trotter
    self.ls.add('four')
997 aaae9bc0 Guido Trotter
    self.assertRaises(errors.LockError, self.ls.add, 'four')
998 aaae9bc0 Guido Trotter
999 aaae9bc0 Guido Trotter
  def testNoWrongRemoves(self):
1000 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'three'], shared=1)
1001 aaae9bc0 Guido Trotter
    # Cannot remove 'two' while holding something which is not a superset
1002 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.remove, 'two')
1003 aaae9bc0 Guido Trotter
    # Cannot remove 'three' as we are sharing it
1004 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.remove, 'three')
1005 aaae9bc0 Guido Trotter
1006 3b7ed473 Guido Trotter
  def testAcquireSetLock(self):
1007 3b7ed473 Guido Trotter
    # acquire the set-lock exclusively
1008 3b7ed473 Guido Trotter
    self.assertEquals(self.ls.acquire(None), set(['one', 'two', 'three']))
1009 d4803c24 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['one', 'two', 'three']))
1010 d4803c24 Guido Trotter
    self.assertEquals(self.ls._is_owned(), True)
1011 d4803c24 Guido Trotter
    self.assertEquals(self.ls._names(), set(['one', 'two', 'three']))
1012 3b7ed473 Guido Trotter
    # I can still add/remove elements...
1013 3b7ed473 Guido Trotter
    self.assertEquals(self.ls.remove(['two', 'three']), ['two', 'three'])
1014 3b7ed473 Guido Trotter
    self.assert_(self.ls.add('six'))
1015 3b7ed473 Guido Trotter
    self.ls.release()
1016 3b7ed473 Guido Trotter
    # share the set-lock
1017 3b7ed473 Guido Trotter
    self.assertEquals(self.ls.acquire(None, shared=1), set(['one', 'six']))
1018 3b7ed473 Guido Trotter
    # adding new elements is not possible
1019 3b7ed473 Guido Trotter
    self.assertRaises(AssertionError, self.ls.add, 'five')
1020 3b7ed473 Guido Trotter
    self.ls.release()
1021 3b7ed473 Guido Trotter
1022 d4f6a91c Guido Trotter
  def testAcquireWithRepetitions(self):
1023 d4f6a91c Guido Trotter
    self.assertEquals(self.ls.acquire(['two', 'two', 'three'], shared=1),
1024 d4f6a91c Guido Trotter
                      set(['two', 'two', 'three']))
1025 d4f6a91c Guido Trotter
    self.ls.release(['two', 'two'])
1026 d4f6a91c Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['three']))
1027 d4f6a91c Guido Trotter
1028 2e1d6d96 Guido Trotter
  def testEmptyAcquire(self):
1029 2e1d6d96 Guido Trotter
    # Acquire an empty list of locks...
1030 2e1d6d96 Guido Trotter
    self.assertEquals(self.ls.acquire([]), set())
1031 2e1d6d96 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set())
1032 2e1d6d96 Guido Trotter
    # New locks can still be addded
1033 2e1d6d96 Guido Trotter
    self.assert_(self.ls.add('six'))
1034 2e1d6d96 Guido Trotter
    # "re-acquiring" is not an issue, since we had really acquired nothing
1035 2e1d6d96 Guido Trotter
    self.assertEquals(self.ls.acquire([], shared=1), set())
1036 2e1d6d96 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set())
1037 2e1d6d96 Guido Trotter
    # We haven't really acquired anything, so we cannot release
1038 2e1d6d96 Guido Trotter
    self.assertRaises(AssertionError, self.ls.release)
1039 2e1d6d96 Guido Trotter
1040 84e344d4 Michael Hanselmann
  def _doLockSet(self, names, shared):
1041 aaae9bc0 Guido Trotter
    try:
1042 84e344d4 Michael Hanselmann
      self.ls.acquire(names, shared=shared)
1043 aaae9bc0 Guido Trotter
      self.done.put('DONE')
1044 aaae9bc0 Guido Trotter
      self.ls.release()
1045 aaae9bc0 Guido Trotter
    except errors.LockError:
1046 aaae9bc0 Guido Trotter
      self.done.put('ERR')
1047 aaae9bc0 Guido Trotter
1048 84e344d4 Michael Hanselmann
  def _doAddSet(self, names):
1049 3b7ed473 Guido Trotter
    try:
1050 84e344d4 Michael Hanselmann
      self.ls.add(names, acquired=1)
1051 3b7ed473 Guido Trotter
      self.done.put('DONE')
1052 3b7ed473 Guido Trotter
      self.ls.release()
1053 3b7ed473 Guido Trotter
    except errors.LockError:
1054 3b7ed473 Guido Trotter
      self.done.put('ERR')
1055 3b7ed473 Guido Trotter
1056 84e344d4 Michael Hanselmann
  def _doRemoveSet(self, names):
1057 84e344d4 Michael Hanselmann
    self.done.put(self.ls.remove(names))
1058 aaae9bc0 Guido Trotter
1059 4607c978 Iustin Pop
  @_Repeat
1060 aaae9bc0 Guido Trotter
  def testConcurrentSharedAcquire(self):
1061 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'two'], shared=1)
1062 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['one', 'two'], 1))
1063 4607c978 Iustin Pop
    self._waitThreads()
1064 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1065 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['one', 'two', 'three'], 1))
1066 4607c978 Iustin Pop
    self._waitThreads()
1067 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1068 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=('three', 1))
1069 4607c978 Iustin Pop
    self._waitThreads()
1070 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1071 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['one', 'two'], 0))
1072 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['two', 'three'], 0))
1073 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1074 aaae9bc0 Guido Trotter
    self.ls.release()
1075 4607c978 Iustin Pop
    self._waitThreads()
1076 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1077 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1078 aaae9bc0 Guido Trotter
1079 4607c978 Iustin Pop
  @_Repeat
1080 aaae9bc0 Guido Trotter
  def testConcurrentExclusiveAcquire(self):
1081 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'two'])
1082 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=('three', 1))
1083 4607c978 Iustin Pop
    self._waitThreads()
1084 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1085 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=('three', 0))
1086 4607c978 Iustin Pop
    self._waitThreads()
1087 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1088 84e344d4 Michael Hanselmann
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1089 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['one', 'two'], 0))
1090 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['one', 'two'], 1))
1091 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=('one', 0))
1092 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=('one', 1))
1093 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['two', 'three'], 0))
1094 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['two', 'three'], 1))
1095 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1096 aaae9bc0 Guido Trotter
    self.ls.release()
1097 4607c978 Iustin Pop
    self._waitThreads()
1098 4607c978 Iustin Pop
    for _ in range(6):
1099 4607c978 Iustin Pop
      self.failUnlessEqual(self.done.get_nowait(), 'DONE')
1100 aaae9bc0 Guido Trotter
1101 4607c978 Iustin Pop
  @_Repeat
1102 5aab242c Michael Hanselmann
  def testSimpleAcquireTimeoutExpiring(self):
1103 5aab242c Michael Hanselmann
    names = sorted(self.ls._names())
1104 5aab242c Michael Hanselmann
    self.assert_(len(names) >= 3)
1105 5aab242c Michael Hanselmann
1106 5aab242c Michael Hanselmann
    # Get name of first lock
1107 5aab242c Michael Hanselmann
    first = names[0]
1108 5aab242c Michael Hanselmann
1109 5aab242c Michael Hanselmann
    # Get name of last lock
1110 5aab242c Michael Hanselmann
    last = names.pop()
1111 5aab242c Michael Hanselmann
1112 5aab242c Michael Hanselmann
    checks = [
1113 5aab242c Michael Hanselmann
      # Block first and try to lock it again
1114 5aab242c Michael Hanselmann
      (first, first),
1115 5aab242c Michael Hanselmann
1116 5aab242c Michael Hanselmann
      # Block last and try to lock all locks
1117 5aab242c Michael Hanselmann
      (None, first),
1118 5aab242c Michael Hanselmann
1119 5aab242c Michael Hanselmann
      # Block last and try to lock it again
1120 5aab242c Michael Hanselmann
      (last, last),
1121 5aab242c Michael Hanselmann
      ]
1122 5aab242c Michael Hanselmann
1123 5aab242c Michael Hanselmann
    for (wanted, block) in checks:
1124 5aab242c Michael Hanselmann
      # Lock in exclusive mode
1125 5aab242c Michael Hanselmann
      self.assert_(self.ls.acquire(block, shared=0))
1126 5aab242c Michael Hanselmann
1127 5aab242c Michael Hanselmann
      def _AcquireOne():
1128 5aab242c Michael Hanselmann
        # Try to get the same lock again with a timeout (should never succeed)
1129 23683c26 Michael Hanselmann
        acquired = self.ls.acquire(wanted, timeout=0.1, shared=0)
1130 23683c26 Michael Hanselmann
        if acquired:
1131 5aab242c Michael Hanselmann
          self.done.put("acquired")
1132 5aab242c Michael Hanselmann
          self.ls.release()
1133 5aab242c Michael Hanselmann
        else:
1134 23683c26 Michael Hanselmann
          self.assert_(acquired is None)
1135 158206e0 Manuel Franceschini
          self.assertFalse(self.ls._list_owned())
1136 158206e0 Manuel Franceschini
          self.assertFalse(self.ls._is_owned())
1137 5aab242c Michael Hanselmann
          self.done.put("not acquired")
1138 5aab242c Michael Hanselmann
1139 5aab242c Michael Hanselmann
      self._addThread(target=_AcquireOne)
1140 5aab242c Michael Hanselmann
1141 5aab242c Michael Hanselmann
      # Wait for timeout in thread to expire
1142 5aab242c Michael Hanselmann
      self._waitThreads()
1143 5aab242c Michael Hanselmann
1144 5aab242c Michael Hanselmann
      # Release exclusive lock again
1145 5aab242c Michael Hanselmann
      self.ls.release()
1146 5aab242c Michael Hanselmann
1147 5aab242c Michael Hanselmann
      self.assertEqual(self.done.get_nowait(), "not acquired")
1148 5aab242c Michael Hanselmann
      self.assertRaises(Queue.Empty, self.done.get_nowait)
1149 5aab242c Michael Hanselmann
1150 5aab242c Michael Hanselmann
  @_Repeat
1151 5aab242c Michael Hanselmann
  def testDelayedAndExpiringLockAcquire(self):
1152 5aab242c Michael Hanselmann
    self._setUpLS()
1153 5aab242c Michael Hanselmann
    self.ls.add(['five', 'six', 'seven', 'eight', 'nine'])
1154 5aab242c Michael Hanselmann
1155 5aab242c Michael Hanselmann
    for expire in (False, True):
1156 5aab242c Michael Hanselmann
      names = sorted(self.ls._names())
1157 5aab242c Michael Hanselmann
      self.assertEqual(len(names), 8)
1158 5aab242c Michael Hanselmann
1159 5aab242c Michael Hanselmann
      lock_ev = dict([(i, threading.Event()) for i in names])
1160 5aab242c Michael Hanselmann
1161 5aab242c Michael Hanselmann
      # Lock all in exclusive mode
1162 5aab242c Michael Hanselmann
      self.assert_(self.ls.acquire(names, shared=0))
1163 5aab242c Michael Hanselmann
1164 5aab242c Michael Hanselmann
      if expire:
1165 5aab242c Michael Hanselmann
        # We'll wait at least 300ms per lock
1166 5aab242c Michael Hanselmann
        lockwait = len(names) * [0.3]
1167 5aab242c Michael Hanselmann
1168 5aab242c Michael Hanselmann
        # Fail if we can't acquire all locks in 400ms. There are 8 locks, so
1169 5aab242c Michael Hanselmann
        # this gives us up to 2.4s to fail.
1170 5aab242c Michael Hanselmann
        lockall_timeout = 0.4
1171 5aab242c Michael Hanselmann
      else:
1172 5aab242c Michael Hanselmann
        # This should finish rather quickly
1173 5aab242c Michael Hanselmann
        lockwait = None
1174 5aab242c Michael Hanselmann
        lockall_timeout = len(names) * 5.0
1175 5aab242c Michael Hanselmann
1176 5aab242c Michael Hanselmann
      def _LockAll():
1177 5aab242c Michael Hanselmann
        def acquire_notification(name):
1178 5aab242c Michael Hanselmann
          if not expire:
1179 5aab242c Michael Hanselmann
            self.done.put("getting %s" % name)
1180 5aab242c Michael Hanselmann
1181 5aab242c Michael Hanselmann
          # Kick next lock
1182 5aab242c Michael Hanselmann
          lock_ev[name].set()
1183 5aab242c Michael Hanselmann
1184 5aab242c Michael Hanselmann
        if self.ls.acquire(names, shared=0, timeout=lockall_timeout,
1185 5aab242c Michael Hanselmann
                           test_notify=acquire_notification):
1186 5aab242c Michael Hanselmann
          self.done.put("got all")
1187 5aab242c Michael Hanselmann
          self.ls.release()
1188 5aab242c Michael Hanselmann
        else:
1189 5aab242c Michael Hanselmann
          self.done.put("timeout on all")
1190 5aab242c Michael Hanselmann
1191 5aab242c Michael Hanselmann
        # Notify all locks
1192 5aab242c Michael Hanselmann
        for ev in lock_ev.values():
1193 5aab242c Michael Hanselmann
          ev.set()
1194 5aab242c Michael Hanselmann
1195 5aab242c Michael Hanselmann
      t = self._addThread(target=_LockAll)
1196 5aab242c Michael Hanselmann
1197 5aab242c Michael Hanselmann
      for idx, name in enumerate(names):
1198 5aab242c Michael Hanselmann
        # Wait for actual acquire on this lock to start
1199 5aab242c Michael Hanselmann
        lock_ev[name].wait(10.0)
1200 5aab242c Michael Hanselmann
1201 5aab242c Michael Hanselmann
        if expire and t.isAlive():
1202 5aab242c Michael Hanselmann
          # Wait some time after getting the notification to make sure the lock
1203 5aab242c Michael Hanselmann
          # acquire will expire
1204 5aab242c Michael Hanselmann
          SafeSleep(lockwait[idx])
1205 5aab242c Michael Hanselmann
1206 5aab242c Michael Hanselmann
        self.ls.release(names=name)
1207 5aab242c Michael Hanselmann
1208 158206e0 Manuel Franceschini
      self.assertFalse(self.ls._list_owned())
1209 5aab242c Michael Hanselmann
1210 5aab242c Michael Hanselmann
      self._waitThreads()
1211 5aab242c Michael Hanselmann
1212 5aab242c Michael Hanselmann
      if expire:
1213 5aab242c Michael Hanselmann
        # Not checking which locks were actually acquired. Doing so would be
1214 5aab242c Michael Hanselmann
        # too timing-dependant.
1215 5aab242c Michael Hanselmann
        self.assertEqual(self.done.get_nowait(), "timeout on all")
1216 5aab242c Michael Hanselmann
      else:
1217 5aab242c Michael Hanselmann
        for i in names:
1218 5aab242c Michael Hanselmann
          self.assertEqual(self.done.get_nowait(), "getting %s" % i)
1219 5aab242c Michael Hanselmann
        self.assertEqual(self.done.get_nowait(), "got all")
1220 5aab242c Michael Hanselmann
      self.assertRaises(Queue.Empty, self.done.get_nowait)
1221 5aab242c Michael Hanselmann
1222 5aab242c Michael Hanselmann
  @_Repeat
1223 aaae9bc0 Guido Trotter
  def testConcurrentRemove(self):
1224 aaae9bc0 Guido Trotter
    self.ls.add('four')
1225 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'two', 'four'])
1226 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['one', 'four'], 0))
1227 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['one', 'four'], 1))
1228 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['one', 'two'], 0))
1229 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['one', 'two'], 1))
1230 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1231 aaae9bc0 Guido Trotter
    self.ls.remove('one')
1232 aaae9bc0 Guido Trotter
    self.ls.release()
1233 4607c978 Iustin Pop
    self._waitThreads()
1234 4607c978 Iustin Pop
    for i in range(4):
1235 4607c978 Iustin Pop
      self.failUnlessEqual(self.done.get_nowait(), 'ERR')
1236 aaae9bc0 Guido Trotter
    self.ls.add(['five', 'six'], acquired=1)
1237 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['three', 'six'], 1))
1238 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['three', 'six'], 0))
1239 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['four', 'six'], 1))
1240 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['four', 'six'], 0))
1241 aaae9bc0 Guido Trotter
    self.ls.remove('five')
1242 aaae9bc0 Guido Trotter
    self.ls.release()
1243 4607c978 Iustin Pop
    self._waitThreads()
1244 4607c978 Iustin Pop
    for i in range(4):
1245 4607c978 Iustin Pop
      self.failUnlessEqual(self.done.get_nowait(), 'DONE')
1246 aaae9bc0 Guido Trotter
    self.ls.acquire(['three', 'four'])
1247 4607c978 Iustin Pop
    self._addThread(target=self._doRemoveSet, args=(['four', 'six'], ))
1248 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1249 aaae9bc0 Guido Trotter
    self.ls.remove('four')
1250 4607c978 Iustin Pop
    self._waitThreads()
1251 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), ['six'])
1252 4607c978 Iustin Pop
    self._addThread(target=self._doRemoveSet, args=(['two']))
1253 4607c978 Iustin Pop
    self._waitThreads()
1254 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), ['two'])
1255 aaae9bc0 Guido Trotter
    self.ls.release()
1256 4607c978 Iustin Pop
    # reset lockset
1257 4607c978 Iustin Pop
    self._setUpLS()
1258 aaae9bc0 Guido Trotter
1259 4607c978 Iustin Pop
  @_Repeat
1260 3b7ed473 Guido Trotter
  def testConcurrentSharedSetLock(self):
1261 3b7ed473 Guido Trotter
    # share the set-lock...
1262 3b7ed473 Guido Trotter
    self.ls.acquire(None, shared=1)
1263 3b7ed473 Guido Trotter
    # ...another thread can share it too
1264 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(None, 1))
1265 4607c978 Iustin Pop
    self._waitThreads()
1266 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1267 3b7ed473 Guido Trotter
    # ...or just share some elements
1268 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['one', 'three'], 1))
1269 4607c978 Iustin Pop
    self._waitThreads()
1270 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1271 3b7ed473 Guido Trotter
    # ...but not add new ones or remove any
1272 4607c978 Iustin Pop
    t = self._addThread(target=self._doAddSet, args=(['nine']))
1273 4607c978 Iustin Pop
    self._addThread(target=self._doRemoveSet, args=(['two'], ))
1274 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1275 3b7ed473 Guido Trotter
    # this just releases the set-lock
1276 3b7ed473 Guido Trotter
    self.ls.release([])
1277 4607c978 Iustin Pop
    t.join(60)
1278 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1279 3b7ed473 Guido Trotter
    # release the lock on the actual elements so remove() can proceed too
1280 3b7ed473 Guido Trotter
    self.ls.release()
1281 4607c978 Iustin Pop
    self._waitThreads()
1282 4607c978 Iustin Pop
    self.failUnlessEqual(self.done.get_nowait(), ['two'])
1283 4607c978 Iustin Pop
    # reset lockset
1284 4607c978 Iustin Pop
    self._setUpLS()
1285 3b7ed473 Guido Trotter
1286 4607c978 Iustin Pop
  @_Repeat
1287 3b7ed473 Guido Trotter
  def testConcurrentExclusiveSetLock(self):
1288 3b7ed473 Guido Trotter
    # acquire the set-lock...
1289 3b7ed473 Guido Trotter
    self.ls.acquire(None, shared=0)
1290 3b7ed473 Guido Trotter
    # ...no one can do anything else
1291 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(None, 1))
1292 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(None, 0))
1293 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['three'], 0))
1294 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['two'], 1))
1295 4607c978 Iustin Pop
    self._addThread(target=self._doAddSet, args=(['nine']))
1296 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1297 3b7ed473 Guido Trotter
    self.ls.release()
1298 4607c978 Iustin Pop
    self._waitThreads()
1299 4607c978 Iustin Pop
    for _ in range(5):
1300 4607c978 Iustin Pop
      self.assertEqual(self.done.get(True, 1), 'DONE')
1301 4607c978 Iustin Pop
    # cleanup
1302 4607c978 Iustin Pop
    self._setUpLS()
1303 3b7ed473 Guido Trotter
1304 4607c978 Iustin Pop
  @_Repeat
1305 d2aff862 Guido Trotter
  def testConcurrentSetLockAdd(self):
1306 d2aff862 Guido Trotter
    self.ls.acquire('one')
1307 d2aff862 Guido Trotter
    # Another thread wants the whole SetLock
1308 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(None, 0))
1309 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(None, 1))
1310 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1311 d2aff862 Guido Trotter
    self.assertRaises(AssertionError, self.ls.add, 'four')
1312 d2aff862 Guido Trotter
    self.ls.release()
1313 4607c978 Iustin Pop
    self._waitThreads()
1314 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1315 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1316 d2aff862 Guido Trotter
    self.ls.acquire(None)
1317 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(None, 0))
1318 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(None, 1))
1319 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1320 d2aff862 Guido Trotter
    self.ls.add('four')
1321 d2aff862 Guido Trotter
    self.ls.add('five', acquired=1)
1322 d2aff862 Guido Trotter
    self.ls.add('six', acquired=1, shared=1)
1323 d2aff862 Guido Trotter
    self.assertEquals(self.ls._list_owned(),
1324 d2aff862 Guido Trotter
      set(['one', 'two', 'three', 'five', 'six']))
1325 d2aff862 Guido Trotter
    self.assertEquals(self.ls._is_owned(), True)
1326 d2aff862 Guido Trotter
    self.assertEquals(self.ls._names(),
1327 d2aff862 Guido Trotter
      set(['one', 'two', 'three', 'four', 'five', 'six']))
1328 d2aff862 Guido Trotter
    self.ls.release()
1329 4607c978 Iustin Pop
    self._waitThreads()
1330 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1331 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1332 4607c978 Iustin Pop
    self._setUpLS()
1333 d2aff862 Guido Trotter
1334 4607c978 Iustin Pop
  @_Repeat
1335 b2dabfd6 Guido Trotter
  def testEmptyLockSet(self):
1336 b2dabfd6 Guido Trotter
    # get the set-lock
1337 b2dabfd6 Guido Trotter
    self.assertEqual(self.ls.acquire(None), set(['one', 'two', 'three']))
1338 b2dabfd6 Guido Trotter
    # now empty it...
1339 b2dabfd6 Guido Trotter
    self.ls.remove(['one', 'two', 'three'])
1340 b2dabfd6 Guido Trotter
    # and adds/locks by another thread still wait
1341 4607c978 Iustin Pop
    self._addThread(target=self._doAddSet, args=(['nine']))
1342 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(None, 1))
1343 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(None, 0))
1344 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1345 b2dabfd6 Guido Trotter
    self.ls.release()
1346 4607c978 Iustin Pop
    self._waitThreads()
1347 4607c978 Iustin Pop
    for _ in range(3):
1348 4607c978 Iustin Pop
      self.assertEqual(self.done.get_nowait(), 'DONE')
1349 b2dabfd6 Guido Trotter
    # empty it again...
1350 b2dabfd6 Guido Trotter
    self.assertEqual(self.ls.remove(['nine']), ['nine'])
1351 b2dabfd6 Guido Trotter
    # now share it...
1352 b2dabfd6 Guido Trotter
    self.assertEqual(self.ls.acquire(None, shared=1), set())
1353 b2dabfd6 Guido Trotter
    # other sharers can go, adds still wait
1354 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(None, 1))
1355 4607c978 Iustin Pop
    self._waitThreads()
1356 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1357 4607c978 Iustin Pop
    self._addThread(target=self._doAddSet, args=(['nine']))
1358 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1359 b2dabfd6 Guido Trotter
    self.ls.release()
1360 4607c978 Iustin Pop
    self._waitThreads()
1361 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1362 4607c978 Iustin Pop
    self._setUpLS()
1363 b2dabfd6 Guido Trotter
1364 887c7aa6 Michael Hanselmann
  def testPriority(self):
1365 887c7aa6 Michael Hanselmann
    def _Acquire(prev, next, name, priority, success_fn):
1366 887c7aa6 Michael Hanselmann
      prev.wait()
1367 887c7aa6 Michael Hanselmann
      self.assert_(self.ls.acquire(name, shared=0,
1368 887c7aa6 Michael Hanselmann
                                   priority=priority,
1369 887c7aa6 Michael Hanselmann
                                   test_notify=lambda _: next.set()))
1370 887c7aa6 Michael Hanselmann
      try:
1371 887c7aa6 Michael Hanselmann
        success_fn()
1372 887c7aa6 Michael Hanselmann
      finally:
1373 887c7aa6 Michael Hanselmann
        self.ls.release()
1374 887c7aa6 Michael Hanselmann
1375 887c7aa6 Michael Hanselmann
    # Get all in exclusive mode
1376 887c7aa6 Michael Hanselmann
    self.assert_(self.ls.acquire(locking.ALL_SET, shared=0))
1377 887c7aa6 Michael Hanselmann
1378 887c7aa6 Michael Hanselmann
    done_two = Queue.Queue(0)
1379 887c7aa6 Michael Hanselmann
1380 887c7aa6 Michael Hanselmann
    first = threading.Event()
1381 887c7aa6 Michael Hanselmann
    prev = first
1382 887c7aa6 Michael Hanselmann
1383 887c7aa6 Michael Hanselmann
    acquires = [("one", prio, self.done) for prio in range(1, 33)]
1384 887c7aa6 Michael Hanselmann
    acquires.extend([("two", prio, done_two) for prio in range(1, 33)])
1385 887c7aa6 Michael Hanselmann
1386 887c7aa6 Michael Hanselmann
    # Use a deterministic random generator
1387 887c7aa6 Michael Hanselmann
    random.Random(741).shuffle(acquires)
1388 887c7aa6 Michael Hanselmann
1389 887c7aa6 Michael Hanselmann
    for (name, prio, done) in acquires:
1390 887c7aa6 Michael Hanselmann
      ev = threading.Event()
1391 887c7aa6 Michael Hanselmann
      self._addThread(target=_Acquire,
1392 887c7aa6 Michael Hanselmann
                      args=(prev, ev, name, prio,
1393 887c7aa6 Michael Hanselmann
                            compat.partial(done.put, "Prio%s" % prio)))
1394 887c7aa6 Michael Hanselmann
      prev = ev
1395 887c7aa6 Michael Hanselmann
1396 887c7aa6 Michael Hanselmann
    # Start acquires
1397 887c7aa6 Michael Hanselmann
    first.set()
1398 887c7aa6 Michael Hanselmann
1399 887c7aa6 Michael Hanselmann
    # Wait for last acquire to start
1400 887c7aa6 Michael Hanselmann
    prev.wait()
1401 887c7aa6 Michael Hanselmann
1402 887c7aa6 Michael Hanselmann
    # Let threads acquire locks
1403 887c7aa6 Michael Hanselmann
    self.ls.release()
1404 887c7aa6 Michael Hanselmann
1405 887c7aa6 Michael Hanselmann
    # Wait for threads to finish
1406 887c7aa6 Michael Hanselmann
    self._waitThreads()
1407 887c7aa6 Michael Hanselmann
1408 887c7aa6 Michael Hanselmann
    for i in range(1, 33):
1409 887c7aa6 Michael Hanselmann
      self.assertEqual(self.done.get_nowait(), "Prio%s" % i)
1410 887c7aa6 Michael Hanselmann
      self.assertEqual(done_two.get_nowait(), "Prio%s" % i)
1411 887c7aa6 Michael Hanselmann
1412 887c7aa6 Michael Hanselmann
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1413 887c7aa6 Michael Hanselmann
    self.assertRaises(Queue.Empty, done_two.get_nowait)
1414 887c7aa6 Michael Hanselmann
1415 aaae9bc0 Guido Trotter
1416 4607c978 Iustin Pop
class TestGanetiLockManager(_ThreadedTestCase):
1417 7ee7c0c7 Guido Trotter
1418 7ee7c0c7 Guido Trotter
  def setUp(self):
1419 4607c978 Iustin Pop
    _ThreadedTestCase.setUp(self)
1420 7ee7c0c7 Guido Trotter
    self.nodes=['n1', 'n2']
1421 7ee7c0c7 Guido Trotter
    self.instances=['i1', 'i2', 'i3']
1422 f9116d58 Guido Trotter
    self.GL = locking.GanetiLockManager(self.nodes, self.instances)
1423 7ee7c0c7 Guido Trotter
1424 7ee7c0c7 Guido Trotter
  def tearDown(self):
1425 7ee7c0c7 Guido Trotter
    # Don't try this at home...
1426 7ee7c0c7 Guido Trotter
    locking.GanetiLockManager._instance = None
1427 7ee7c0c7 Guido Trotter
1428 7ee7c0c7 Guido Trotter
  def testLockingConstants(self):
1429 7ee7c0c7 Guido Trotter
    # The locking library internally cheats by assuming its constants have some
1430 7ee7c0c7 Guido Trotter
    # relationships with each other. Check those hold true.
1431 b10b9d74 Guido Trotter
    # This relationship is also used in the Processor to recursively acquire
1432 b10b9d74 Guido Trotter
    # the right locks. Again, please don't break it.
1433 7ee7c0c7 Guido Trotter
    for i in range(len(locking.LEVELS)):
1434 7ee7c0c7 Guido Trotter
      self.assertEqual(i, locking.LEVELS[i])
1435 7ee7c0c7 Guido Trotter
1436 7ee7c0c7 Guido Trotter
  def testDoubleGLFails(self):
1437 f9116d58 Guido Trotter
    self.assertRaises(AssertionError, locking.GanetiLockManager, [], [])
1438 7ee7c0c7 Guido Trotter
1439 7ee7c0c7 Guido Trotter
  def testLockNames(self):
1440 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
1441 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set(self.nodes))
1442 cdb08f44 Michael Hanselmann
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE),
1443 cdb08f44 Michael Hanselmann
                     set(self.instances))
1444 7ee7c0c7 Guido Trotter
1445 7ee7c0c7 Guido Trotter
  def testInitAndResources(self):
1446 7ee7c0c7 Guido Trotter
    locking.GanetiLockManager._instance = None
1447 7f93570a Iustin Pop
    self.GL = locking.GanetiLockManager([], [])
1448 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
1449 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set())
1450 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE), set())
1451 7ee7c0c7 Guido Trotter
1452 7ee7c0c7 Guido Trotter
    locking.GanetiLockManager._instance = None
1453 7f93570a Iustin Pop
    self.GL = locking.GanetiLockManager(self.nodes, [])
1454 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
1455 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set(self.nodes))
1456 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE), set())
1457 7ee7c0c7 Guido Trotter
1458 7ee7c0c7 Guido Trotter
    locking.GanetiLockManager._instance = None
1459 7f93570a Iustin Pop
    self.GL = locking.GanetiLockManager([], self.instances)
1460 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
1461 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set())
1462 cdb08f44 Michael Hanselmann
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE),
1463 cdb08f44 Michael Hanselmann
                     set(self.instances))
1464 7ee7c0c7 Guido Trotter
1465 7ee7c0c7 Guido Trotter
  def testAcquireRelease(self):
1466 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
1467 7ee7c0c7 Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_CLUSTER), set(['BGL']))
1468 04e1bfaf Guido Trotter
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i1'])
1469 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_NODE, ['n1', 'n2'], shared=1)
1470 04e1bfaf Guido Trotter
    self.GL.release(locking.LEVEL_NODE, ['n2'])
1471 7ee7c0c7 Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_NODE), set(['n1']))
1472 7ee7c0c7 Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE), set(['i1']))
1473 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_NODE)
1474 04e1bfaf Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_NODE), set())
1475 04e1bfaf Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE), set(['i1']))
1476 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
1477 7ee7c0c7 Guido Trotter
    self.assertRaises(errors.LockError, self.GL.acquire,
1478 7ee7c0c7 Guido Trotter
                      locking.LEVEL_INSTANCE, ['i5'])
1479 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i3'], shared=1)
1480 7ee7c0c7 Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE), set(['i3']))
1481 7ee7c0c7 Guido Trotter
1482 90c942d1 Guido Trotter
  def testAcquireWholeSets(self):
1483 90c942d1 Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
1484 90c942d1 Guido Trotter
    self.assertEquals(self.GL.acquire(locking.LEVEL_INSTANCE, None),
1485 90c942d1 Guido Trotter
                      set(self.instances))
1486 90c942d1 Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE),
1487 90c942d1 Guido Trotter
                      set(self.instances))
1488 90c942d1 Guido Trotter
    self.assertEquals(self.GL.acquire(locking.LEVEL_NODE, None, shared=1),
1489 90c942d1 Guido Trotter
                      set(self.nodes))
1490 90c942d1 Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_NODE),
1491 90c942d1 Guido Trotter
                      set(self.nodes))
1492 90c942d1 Guido Trotter
    self.GL.release(locking.LEVEL_NODE)
1493 d4f6a91c Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
1494 d4f6a91c Guido Trotter
    self.GL.release(locking.LEVEL_CLUSTER)
1495 d4f6a91c Guido Trotter
1496 d4f6a91c Guido Trotter
  def testAcquireWholeAndPartial(self):
1497 d4f6a91c Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
1498 d4f6a91c Guido Trotter
    self.assertEquals(self.GL.acquire(locking.LEVEL_INSTANCE, None),
1499 d4f6a91c Guido Trotter
                      set(self.instances))
1500 d4f6a91c Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE),
1501 d4f6a91c Guido Trotter
                      set(self.instances))
1502 d4f6a91c Guido Trotter
    self.assertEquals(self.GL.acquire(locking.LEVEL_NODE, ['n2'], shared=1),
1503 d4f6a91c Guido Trotter
                      set(['n2']))
1504 d4f6a91c Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_NODE),
1505 d4f6a91c Guido Trotter
                      set(['n2']))
1506 d4f6a91c Guido Trotter
    self.GL.release(locking.LEVEL_NODE)
1507 90c942d1 Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
1508 90c942d1 Guido Trotter
    self.GL.release(locking.LEVEL_CLUSTER)
1509 90c942d1 Guido Trotter
1510 7ee7c0c7 Guido Trotter
  def testBGLDependency(self):
1511 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.acquire,
1512 7ee7c0c7 Guido Trotter
                      locking.LEVEL_NODE, ['n1', 'n2'])
1513 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.acquire,
1514 7ee7c0c7 Guido Trotter
                      locking.LEVEL_INSTANCE, ['i3'])
1515 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
1516 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_NODE, ['n1'])
1517 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.release,
1518 7ee7c0c7 Guido Trotter
                      locking.LEVEL_CLUSTER, ['BGL'])
1519 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.release,
1520 7ee7c0c7 Guido Trotter
                      locking.LEVEL_CLUSTER)
1521 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_NODE)
1522 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i1', 'i2'])
1523 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.release,
1524 7ee7c0c7 Guido Trotter
                      locking.LEVEL_CLUSTER, ['BGL'])
1525 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.release,
1526 7ee7c0c7 Guido Trotter
                      locking.LEVEL_CLUSTER)
1527 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
1528 7ee7c0c7 Guido Trotter
1529 7ee7c0c7 Guido Trotter
  def testWrongOrder(self):
1530 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
1531 04e1bfaf Guido Trotter
    self.GL.acquire(locking.LEVEL_NODE, ['n2'])
1532 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.acquire,
1533 7ee7c0c7 Guido Trotter
                      locking.LEVEL_NODE, ['n1'])
1534 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.acquire,
1535 7ee7c0c7 Guido Trotter
                      locking.LEVEL_INSTANCE, ['i2'])
1536 7ee7c0c7 Guido Trotter
1537 4badc36c Guido Trotter
  def testModifiableLevels(self):
1538 4badc36c Guido Trotter
    self.assertRaises(AssertionError, self.GL.add, locking.LEVEL_CLUSTER,
1539 4badc36c Guido Trotter
                      ['BGL2'])
1540 4badc36c Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'])
1541 4badc36c Guido Trotter
    self.GL.add(locking.LEVEL_INSTANCE, ['i4'])
1542 4badc36c Guido Trotter
    self.GL.remove(locking.LEVEL_INSTANCE, ['i3'])
1543 4badc36c Guido Trotter
    self.GL.remove(locking.LEVEL_INSTANCE, ['i1'])
1544 4badc36c Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE), set(['i2', 'i4']))
1545 4badc36c Guido Trotter
    self.GL.add(locking.LEVEL_NODE, ['n3'])
1546 4badc36c Guido Trotter
    self.GL.remove(locking.LEVEL_NODE, ['n1'])
1547 4badc36c Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set(['n2', 'n3']))
1548 4badc36c Guido Trotter
    self.assertRaises(AssertionError, self.GL.remove, locking.LEVEL_CLUSTER,
1549 4badc36c Guido Trotter
                      ['BGL2'])
1550 4badc36c Guido Trotter
1551 7ee7c0c7 Guido Trotter
  # Helper function to run as a thread that shared the BGL and then acquires
1552 7ee7c0c7 Guido Trotter
  # some locks at another level.
1553 7ee7c0c7 Guido Trotter
  def _doLock(self, level, names, shared):
1554 7ee7c0c7 Guido Trotter
    try:
1555 7ee7c0c7 Guido Trotter
      self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
1556 7ee7c0c7 Guido Trotter
      self.GL.acquire(level, names, shared=shared)
1557 7ee7c0c7 Guido Trotter
      self.done.put('DONE')
1558 7ee7c0c7 Guido Trotter
      self.GL.release(level)
1559 7ee7c0c7 Guido Trotter
      self.GL.release(locking.LEVEL_CLUSTER)
1560 7ee7c0c7 Guido Trotter
    except errors.LockError:
1561 7ee7c0c7 Guido Trotter
      self.done.put('ERR')
1562 7ee7c0c7 Guido Trotter
1563 4607c978 Iustin Pop
  @_Repeat
1564 7ee7c0c7 Guido Trotter
  def testConcurrency(self):
1565 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
1566 4607c978 Iustin Pop
    self._addThread(target=self._doLock,
1567 4607c978 Iustin Pop
                    args=(locking.LEVEL_INSTANCE, 'i1', 1))
1568 4607c978 Iustin Pop
    self._waitThreads()
1569 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1570 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i3'])
1571 4607c978 Iustin Pop
    self._addThread(target=self._doLock,
1572 4607c978 Iustin Pop
                    args=(locking.LEVEL_INSTANCE, 'i1', 1))
1573 4607c978 Iustin Pop
    self._waitThreads()
1574 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1575 4607c978 Iustin Pop
    self._addThread(target=self._doLock,
1576 4607c978 Iustin Pop
                    args=(locking.LEVEL_INSTANCE, 'i3', 1))
1577 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1578 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
1579 4607c978 Iustin Pop
    self._waitThreads()
1580 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1581 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i2'], shared=1)
1582 4607c978 Iustin Pop
    self._addThread(target=self._doLock,
1583 4607c978 Iustin Pop
                    args=(locking.LEVEL_INSTANCE, 'i2', 1))
1584 4607c978 Iustin Pop
    self._waitThreads()
1585 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1586 4607c978 Iustin Pop
    self._addThread(target=self._doLock,
1587 4607c978 Iustin Pop
                    args=(locking.LEVEL_INSTANCE, 'i2', 0))
1588 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1589 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
1590 4607c978 Iustin Pop
    self._waitThreads()
1591 7ee7c0c7 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
1592 4607c978 Iustin Pop
    self.GL.release(locking.LEVEL_CLUSTER, ['BGL'])
1593 7ee7c0c7 Guido Trotter
1594 7ee7c0c7 Guido Trotter
1595 19b9ba9a Michael Hanselmann
class TestLockMonitor(_ThreadedTestCase):
1596 19b9ba9a Michael Hanselmann
  def setUp(self):
1597 19b9ba9a Michael Hanselmann
    _ThreadedTestCase.setUp(self)
1598 19b9ba9a Michael Hanselmann
    self.lm = locking.LockMonitor()
1599 19b9ba9a Michael Hanselmann
1600 19b9ba9a Michael Hanselmann
  def testSingleThread(self):
1601 19b9ba9a Michael Hanselmann
    locks = []
1602 19b9ba9a Michael Hanselmann
1603 19b9ba9a Michael Hanselmann
    for i in range(100):
1604 19b9ba9a Michael Hanselmann
      name = "TestLock%s" % i
1605 19b9ba9a Michael Hanselmann
      locks.append(locking.SharedLock(name, monitor=self.lm))
1606 19b9ba9a Michael Hanselmann
1607 19b9ba9a Michael Hanselmann
    self.assertEqual(len(self.lm._locks), len(locks))
1608 19b9ba9a Michael Hanselmann
1609 c31825f7 Michael Hanselmann
    self.assertEqual(len(self.lm.QueryLocks(["name"], False)),
1610 c31825f7 Michael Hanselmann
                     100)
1611 c31825f7 Michael Hanselmann
1612 19b9ba9a Michael Hanselmann
    # Delete all locks
1613 19b9ba9a Michael Hanselmann
    del locks[:]
1614 19b9ba9a Michael Hanselmann
1615 19b9ba9a Michael Hanselmann
    # The garbage collector might needs some time
1616 19b9ba9a Michael Hanselmann
    def _CheckLocks():
1617 19b9ba9a Michael Hanselmann
      if self.lm._locks:
1618 19b9ba9a Michael Hanselmann
        raise utils.RetryAgain()
1619 19b9ba9a Michael Hanselmann
1620 19b9ba9a Michael Hanselmann
    utils.Retry(_CheckLocks, 0.1, 30.0)
1621 19b9ba9a Michael Hanselmann
1622 19b9ba9a Michael Hanselmann
    self.assertFalse(self.lm._locks)
1623 19b9ba9a Michael Hanselmann
1624 19b9ba9a Michael Hanselmann
  def testMultiThread(self):
1625 19b9ba9a Michael Hanselmann
    locks = []
1626 19b9ba9a Michael Hanselmann
1627 19b9ba9a Michael Hanselmann
    def _CreateLock(prev, next, name):
1628 19b9ba9a Michael Hanselmann
      prev.wait()
1629 19b9ba9a Michael Hanselmann
      locks.append(locking.SharedLock(name, monitor=self.lm))
1630 19b9ba9a Michael Hanselmann
      if next:
1631 19b9ba9a Michael Hanselmann
        next.set()
1632 19b9ba9a Michael Hanselmann
1633 19b9ba9a Michael Hanselmann
    expnames = []
1634 19b9ba9a Michael Hanselmann
1635 19b9ba9a Michael Hanselmann
    first = threading.Event()
1636 19b9ba9a Michael Hanselmann
    prev = first
1637 19b9ba9a Michael Hanselmann
1638 19b9ba9a Michael Hanselmann
    # Use a deterministic random generator
1639 19b9ba9a Michael Hanselmann
    for i in random.Random(4263).sample(range(100), 33):
1640 19b9ba9a Michael Hanselmann
      name = "MtTestLock%s" % i
1641 19b9ba9a Michael Hanselmann
      expnames.append(name)
1642 19b9ba9a Michael Hanselmann
1643 19b9ba9a Michael Hanselmann
      ev = threading.Event()
1644 19b9ba9a Michael Hanselmann
      self._addThread(target=_CreateLock, args=(prev, ev, name))
1645 19b9ba9a Michael Hanselmann
      prev = ev
1646 19b9ba9a Michael Hanselmann
1647 19b9ba9a Michael Hanselmann
    # Add locks
1648 19b9ba9a Michael Hanselmann
    first.set()
1649 19b9ba9a Michael Hanselmann
    self._waitThreads()
1650 19b9ba9a Michael Hanselmann
1651 19b9ba9a Michael Hanselmann
    # Check order in which locks were added
1652 19b9ba9a Michael Hanselmann
    self.assertEqual([i.name for i in locks], expnames)
1653 19b9ba9a Michael Hanselmann
1654 19b9ba9a Michael Hanselmann
    # Sync queries are not supported
1655 19b9ba9a Michael Hanselmann
    self.assertRaises(NotImplementedError, self.lm.QueryLocks, ["name"], True)
1656 19b9ba9a Michael Hanselmann
1657 19b9ba9a Michael Hanselmann
    # Check query result
1658 c31825f7 Michael Hanselmann
    self.assertEqual(self.lm.QueryLocks(["name", "mode", "owner", "pending"],
1659 c31825f7 Michael Hanselmann
                                        False),
1660 c31825f7 Michael Hanselmann
                     [[name, None, None, []]
1661 c31825f7 Michael Hanselmann
                      for name in utils.NiceSort(expnames)])
1662 19b9ba9a Michael Hanselmann
1663 19b9ba9a Michael Hanselmann
    # Test exclusive acquire
1664 19b9ba9a Michael Hanselmann
    for tlock in locks[::4]:
1665 19b9ba9a Michael Hanselmann
      tlock.acquire(shared=0)
1666 19b9ba9a Michael Hanselmann
      try:
1667 19b9ba9a Michael Hanselmann
        def _GetExpResult(name):
1668 19b9ba9a Michael Hanselmann
          if tlock.name == name:
1669 c31825f7 Michael Hanselmann
            return [name, "exclusive", [threading.currentThread().getName()],
1670 c31825f7 Michael Hanselmann
                    []]
1671 c31825f7 Michael Hanselmann
          return [name, None, None, []]
1672 19b9ba9a Michael Hanselmann
1673 c31825f7 Michael Hanselmann
        self.assertEqual(self.lm.QueryLocks(["name", "mode", "owner",
1674 c31825f7 Michael Hanselmann
                                             "pending"], False),
1675 19b9ba9a Michael Hanselmann
                         [_GetExpResult(name)
1676 19b9ba9a Michael Hanselmann
                          for name in utils.NiceSort(expnames)])
1677 19b9ba9a Michael Hanselmann
      finally:
1678 19b9ba9a Michael Hanselmann
        tlock.release()
1679 19b9ba9a Michael Hanselmann
1680 19b9ba9a Michael Hanselmann
    # Test shared acquire
1681 73c25d35 Michael Hanselmann
    def _Acquire(lock, shared, ev, notify):
1682 19b9ba9a Michael Hanselmann
      lock.acquire(shared=shared)
1683 19b9ba9a Michael Hanselmann
      try:
1684 73c25d35 Michael Hanselmann
        notify.set()
1685 19b9ba9a Michael Hanselmann
        ev.wait()
1686 19b9ba9a Michael Hanselmann
      finally:
1687 19b9ba9a Michael Hanselmann
        lock.release()
1688 19b9ba9a Michael Hanselmann
1689 19b9ba9a Michael Hanselmann
    for tlock1 in locks[::11]:
1690 19b9ba9a Michael Hanselmann
      for tlock2 in locks[::-15]:
1691 19b9ba9a Michael Hanselmann
        if tlock2 == tlock1:
1692 73c25d35 Michael Hanselmann
          # Avoid deadlocks
1693 19b9ba9a Michael Hanselmann
          continue
1694 19b9ba9a Michael Hanselmann
1695 19b9ba9a Michael Hanselmann
        for tlock3 in locks[::10]:
1696 73c25d35 Michael Hanselmann
          if tlock3 in (tlock2, tlock1):
1697 73c25d35 Michael Hanselmann
            # Avoid deadlocks
1698 19b9ba9a Michael Hanselmann
            continue
1699 19b9ba9a Michael Hanselmann
1700 73c25d35 Michael Hanselmann
          releaseev = threading.Event()
1701 19b9ba9a Michael Hanselmann
1702 19b9ba9a Michael Hanselmann
          # Acquire locks
1703 73c25d35 Michael Hanselmann
          acquireev = []
1704 19b9ba9a Michael Hanselmann
          tthreads1 = []
1705 19b9ba9a Michael Hanselmann
          for i in range(3):
1706 73c25d35 Michael Hanselmann
            ev = threading.Event()
1707 19b9ba9a Michael Hanselmann
            tthreads1.append(self._addThread(target=_Acquire,
1708 73c25d35 Michael Hanselmann
                                             args=(tlock1, 1, releaseev, ev)))
1709 73c25d35 Michael Hanselmann
            acquireev.append(ev)
1710 73c25d35 Michael Hanselmann
1711 73c25d35 Michael Hanselmann
          ev = threading.Event()
1712 73c25d35 Michael Hanselmann
          tthread2 = self._addThread(target=_Acquire,
1713 73c25d35 Michael Hanselmann
                                     args=(tlock2, 1, releaseev, ev))
1714 73c25d35 Michael Hanselmann
          acquireev.append(ev)
1715 73c25d35 Michael Hanselmann
1716 73c25d35 Michael Hanselmann
          ev = threading.Event()
1717 73c25d35 Michael Hanselmann
          tthread3 = self._addThread(target=_Acquire,
1718 73c25d35 Michael Hanselmann
                                     args=(tlock3, 0, releaseev, ev))
1719 73c25d35 Michael Hanselmann
          acquireev.append(ev)
1720 73c25d35 Michael Hanselmann
1721 73c25d35 Michael Hanselmann
          # Wait for all locks to be acquired
1722 73c25d35 Michael Hanselmann
          for i in acquireev:
1723 73c25d35 Michael Hanselmann
            i.wait()
1724 19b9ba9a Michael Hanselmann
1725 19b9ba9a Michael Hanselmann
          # Check query result
1726 19b9ba9a Michael Hanselmann
          for (name, mode, owner) in self.lm.QueryLocks(["name", "mode",
1727 19b9ba9a Michael Hanselmann
                                                         "owner"], False):
1728 19b9ba9a Michael Hanselmann
            if name == tlock1.name:
1729 19b9ba9a Michael Hanselmann
              self.assertEqual(mode, "shared")
1730 19b9ba9a Michael Hanselmann
              self.assertEqual(set(owner), set(i.getName() for i in tthreads1))
1731 19b9ba9a Michael Hanselmann
              continue
1732 19b9ba9a Michael Hanselmann
1733 19b9ba9a Michael Hanselmann
            if name == tlock2.name:
1734 19b9ba9a Michael Hanselmann
              self.assertEqual(mode, "shared")
1735 19b9ba9a Michael Hanselmann
              self.assertEqual(owner, [tthread2.getName()])
1736 19b9ba9a Michael Hanselmann
              continue
1737 19b9ba9a Michael Hanselmann
1738 19b9ba9a Michael Hanselmann
            if name == tlock3.name:
1739 19b9ba9a Michael Hanselmann
              self.assertEqual(mode, "exclusive")
1740 19b9ba9a Michael Hanselmann
              self.assertEqual(owner, [tthread3.getName()])
1741 19b9ba9a Michael Hanselmann
              continue
1742 19b9ba9a Michael Hanselmann
1743 19b9ba9a Michael Hanselmann
            self.assert_(name in expnames)
1744 19b9ba9a Michael Hanselmann
            self.assert_(mode is None)
1745 19b9ba9a Michael Hanselmann
            self.assert_(owner is None)
1746 19b9ba9a Michael Hanselmann
1747 19b9ba9a Michael Hanselmann
          # Release locks again
1748 73c25d35 Michael Hanselmann
          releaseev.set()
1749 19b9ba9a Michael Hanselmann
1750 19b9ba9a Michael Hanselmann
          self._waitThreads()
1751 19b9ba9a Michael Hanselmann
1752 19b9ba9a Michael Hanselmann
          self.assertEqual(self.lm.QueryLocks(["name", "mode", "owner"], False),
1753 19b9ba9a Michael Hanselmann
                           [[name, None, None]
1754 19b9ba9a Michael Hanselmann
                            for name in utils.NiceSort(expnames)])
1755 19b9ba9a Michael Hanselmann
1756 19b9ba9a Michael Hanselmann
  def testDelete(self):
1757 19b9ba9a Michael Hanselmann
    lock = locking.SharedLock("TestLock", monitor=self.lm)
1758 19b9ba9a Michael Hanselmann
1759 19b9ba9a Michael Hanselmann
    self.assertEqual(len(self.lm._locks), 1)
1760 19b9ba9a Michael Hanselmann
    self.assertEqual(self.lm.QueryLocks(["name", "mode", "owner"], False),
1761 19b9ba9a Michael Hanselmann
                     [[lock.name, None, None]])
1762 19b9ba9a Michael Hanselmann
1763 19b9ba9a Michael Hanselmann
    lock.delete()
1764 19b9ba9a Michael Hanselmann
1765 19b9ba9a Michael Hanselmann
    self.assertEqual(self.lm.QueryLocks(["name", "mode", "owner"], False),
1766 19b9ba9a Michael Hanselmann
                     [[lock.name, "deleted", None]])
1767 19b9ba9a Michael Hanselmann
    self.assertEqual(len(self.lm._locks), 1)
1768 19b9ba9a Michael Hanselmann
1769 c31825f7 Michael Hanselmann
  def testPending(self):
1770 c31825f7 Michael Hanselmann
    def _Acquire(lock, shared, prev, next):
1771 c31825f7 Michael Hanselmann
      prev.wait()
1772 c31825f7 Michael Hanselmann
1773 c31825f7 Michael Hanselmann
      lock.acquire(shared=shared, test_notify=next.set)
1774 c31825f7 Michael Hanselmann
      try:
1775 c31825f7 Michael Hanselmann
        pass
1776 c31825f7 Michael Hanselmann
      finally:
1777 c31825f7 Michael Hanselmann
        lock.release()
1778 c31825f7 Michael Hanselmann
1779 c31825f7 Michael Hanselmann
    lock = locking.SharedLock("ExcLock", monitor=self.lm)
1780 c31825f7 Michael Hanselmann
1781 c31825f7 Michael Hanselmann
    for shared in [0, 1]:
1782 c31825f7 Michael Hanselmann
      lock.acquire()
1783 c31825f7 Michael Hanselmann
      try:
1784 c31825f7 Michael Hanselmann
        self.assertEqual(len(self.lm._locks), 1)
1785 c31825f7 Michael Hanselmann
        self.assertEqual(self.lm.QueryLocks(["name", "mode", "owner"], False),
1786 c31825f7 Michael Hanselmann
                         [[lock.name, "exclusive",
1787 c31825f7 Michael Hanselmann
                           [threading.currentThread().getName()]]])
1788 c31825f7 Michael Hanselmann
1789 c31825f7 Michael Hanselmann
        threads = []
1790 c31825f7 Michael Hanselmann
1791 c31825f7 Michael Hanselmann
        first = threading.Event()
1792 c31825f7 Michael Hanselmann
        prev = first
1793 c31825f7 Michael Hanselmann
1794 c31825f7 Michael Hanselmann
        for i in range(5):
1795 c31825f7 Michael Hanselmann
          ev = threading.Event()
1796 c31825f7 Michael Hanselmann
          threads.append(self._addThread(target=_Acquire,
1797 c31825f7 Michael Hanselmann
                                          args=(lock, shared, prev, ev)))
1798 c31825f7 Michael Hanselmann
          prev = ev
1799 c31825f7 Michael Hanselmann
1800 c31825f7 Michael Hanselmann
        # Start acquires
1801 c31825f7 Michael Hanselmann
        first.set()
1802 c31825f7 Michael Hanselmann
1803 c31825f7 Michael Hanselmann
        # Wait for last acquire to start waiting
1804 c31825f7 Michael Hanselmann
        prev.wait()
1805 c31825f7 Michael Hanselmann
1806 c31825f7 Michael Hanselmann
        # NOTE: This works only because QueryLocks will acquire the
1807 c31825f7 Michael Hanselmann
        # lock-internal lock again and won't be able to get the information
1808 c31825f7 Michael Hanselmann
        # until it has the lock. By then the acquire should be registered in
1809 c31825f7 Michael Hanselmann
        # SharedLock.__pending (otherwise it's a bug).
1810 c31825f7 Michael Hanselmann
1811 c31825f7 Michael Hanselmann
        # All acquires are waiting now
1812 c31825f7 Michael Hanselmann
        if shared:
1813 c31825f7 Michael Hanselmann
          pending = [("shared", sorted([t.getName() for t in threads]))]
1814 c31825f7 Michael Hanselmann
        else:
1815 c31825f7 Michael Hanselmann
          pending = [("exclusive", [t.getName()]) for t in threads]
1816 c31825f7 Michael Hanselmann
1817 c31825f7 Michael Hanselmann
        self.assertEqual(self.lm.QueryLocks(["name", "mode", "owner",
1818 c31825f7 Michael Hanselmann
                                             "pending"], False),
1819 c31825f7 Michael Hanselmann
                         [[lock.name, "exclusive",
1820 c31825f7 Michael Hanselmann
                           [threading.currentThread().getName()],
1821 c31825f7 Michael Hanselmann
                           pending]])
1822 c31825f7 Michael Hanselmann
1823 c31825f7 Michael Hanselmann
        self.assertEqual(len(self.lm._locks), 1)
1824 c31825f7 Michael Hanselmann
      finally:
1825 c31825f7 Michael Hanselmann
        lock.release()
1826 c31825f7 Michael Hanselmann
1827 c31825f7 Michael Hanselmann
      self._waitThreads()
1828 c31825f7 Michael Hanselmann
1829 c31825f7 Michael Hanselmann
      # No pending acquires
1830 c31825f7 Michael Hanselmann
      self.assertEqual(self.lm.QueryLocks(["name", "mode", "owner", "pending"],
1831 c31825f7 Michael Hanselmann
                                          False),
1832 c31825f7 Michael Hanselmann
                       [[lock.name, None, None, []]])
1833 c31825f7 Michael Hanselmann
1834 c31825f7 Michael Hanselmann
      self.assertEqual(len(self.lm._locks), 1)
1835 c31825f7 Michael Hanselmann
1836 19b9ba9a Michael Hanselmann
1837 162c1c1f Guido Trotter
if __name__ == '__main__':
1838 25231ec5 Michael Hanselmann
  testutils.GanetiTestProgram()