Statistics
| Branch: | Tag: | Revision:

root / test / ganeti.locking_unittest.py @ 819ca990

History | View | Annotate | Download (61.2 kB)

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