Statistics
| Branch: | Tag: | Revision:

root / test / ganeti.locking_unittest.py @ d357f531

History | View | Annotate | Download (46.2 kB)

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