Statistics
| Branch: | Tag: | Revision:

root / test / ganeti.locking_unittest.py @ 19b9ba9a

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