Statistics
| Branch: | Tag: | Revision:

root / test / ganeti.locking_unittest.py @ 44b4eddc

History | View | Annotate | Download (76.1 kB)

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