Statistics
| Branch: | Tag: | Revision:

root / test / ganeti.locking_unittest.py @ 26082b7e

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