Statistics
| Branch: | Tag: | Revision:

root / test / ganeti.locking_unittest.py @ 6760e4ed

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