Statistics
| Branch: | Tag: | Revision:

root / test / ganeti.locking_unittest.py @ 84e344d4

History | View | Annotate | Download (37.2 kB)

1 162c1c1f Guido Trotter
#!/usr/bin/python
2 162c1c1f Guido Trotter
#
3 162c1c1f Guido Trotter
4 162c1c1f Guido Trotter
# Copyright (C) 2006, 2007 Google Inc.
5 162c1c1f Guido Trotter
#
6 162c1c1f Guido Trotter
# This program is free software; you can redistribute it and/or modify
7 162c1c1f Guido Trotter
# it under the terms of the GNU General Public License as published by
8 162c1c1f Guido Trotter
# the Free Software Foundation; either version 2 of the License, or
9 162c1c1f Guido Trotter
# (at your option) any later version.
10 162c1c1f Guido Trotter
#
11 162c1c1f Guido Trotter
# This program is distributed in the hope that it will be useful, but
12 162c1c1f Guido Trotter
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 162c1c1f Guido Trotter
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 162c1c1f Guido Trotter
# General Public License for more details.
15 162c1c1f Guido Trotter
#
16 162c1c1f Guido Trotter
# You should have received a copy of the GNU General Public License
17 162c1c1f Guido Trotter
# along with this program; if not, write to the Free Software
18 162c1c1f Guido Trotter
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 162c1c1f Guido Trotter
# 0.0510-1301, USA.
20 162c1c1f Guido Trotter
21 162c1c1f Guido Trotter
22 162c1c1f Guido Trotter
"""Script for unittesting the locking module"""
23 162c1c1f Guido Trotter
24 162c1c1f Guido Trotter
25 162c1c1f Guido Trotter
import os
26 162c1c1f Guido Trotter
import unittest
27 162c1c1f Guido Trotter
import time
28 162c1c1f Guido Trotter
import Queue
29 84e344d4 Michael Hanselmann
import threading
30 162c1c1f Guido Trotter
31 162c1c1f Guido Trotter
from ganeti import locking
32 a95fd5d7 Guido Trotter
from ganeti import errors
33 162c1c1f Guido Trotter
34 162c1c1f Guido Trotter
35 42a999d1 Guido Trotter
# This is used to test the ssynchronize decorator.
36 42a999d1 Guido Trotter
# Since it's passed as input to a decorator it must be declared as a global.
37 42a999d1 Guido Trotter
_decoratorlock = locking.SharedLock()
38 42a999d1 Guido Trotter
39 4607c978 Iustin Pop
#: List for looping tests
40 4607c978 Iustin Pop
ITERATIONS = range(8)
41 4607c978 Iustin Pop
42 84e344d4 Michael Hanselmann
43 4607c978 Iustin Pop
def _Repeat(fn):
44 4607c978 Iustin Pop
  """Decorator for executing a function many times"""
45 4607c978 Iustin Pop
  def wrapper(*args, **kwargs):
46 4607c978 Iustin Pop
    for i in ITERATIONS:
47 4607c978 Iustin Pop
      fn(*args, **kwargs)
48 4607c978 Iustin Pop
  return wrapper
49 4607c978 Iustin Pop
50 84e344d4 Michael Hanselmann
51 4607c978 Iustin Pop
class _ThreadedTestCase(unittest.TestCase):
52 4607c978 Iustin Pop
  """Test class that supports adding/waiting on threads"""
53 4607c978 Iustin Pop
  def setUp(self):
54 4607c978 Iustin Pop
    unittest.TestCase.setUp(self)
55 4607c978 Iustin Pop
    self.threads = []
56 4607c978 Iustin Pop
57 4607c978 Iustin Pop
  def _addThread(self, *args, **kwargs):
58 4607c978 Iustin Pop
    """Create and remember a new thread"""
59 84e344d4 Michael Hanselmann
    t = threading.Thread(*args, **kwargs)
60 4607c978 Iustin Pop
    self.threads.append(t)
61 4607c978 Iustin Pop
    t.start()
62 4607c978 Iustin Pop
    return t
63 4607c978 Iustin Pop
64 4607c978 Iustin Pop
  def _waitThreads(self):
65 4607c978 Iustin Pop
    """Wait for all our threads to finish"""
66 4607c978 Iustin Pop
    for t in self.threads:
67 4607c978 Iustin Pop
      t.join(60)
68 4607c978 Iustin Pop
      self.failIf(t.isAlive())
69 4607c978 Iustin Pop
    self.threads = []
70 42a999d1 Guido Trotter
71 4607c978 Iustin Pop
72 4607c978 Iustin Pop
class TestSharedLock(_ThreadedTestCase):
73 d6646186 Guido Trotter
  """SharedLock tests"""
74 162c1c1f Guido Trotter
75 162c1c1f Guido Trotter
  def setUp(self):
76 4607c978 Iustin Pop
    _ThreadedTestCase.setUp(self)
77 162c1c1f Guido Trotter
    self.sl = locking.SharedLock()
78 162c1c1f Guido Trotter
    # helper threads use the 'done' queue to tell the master they finished.
79 162c1c1f Guido Trotter
    self.done = Queue.Queue(0)
80 162c1c1f Guido Trotter
81 162c1c1f Guido Trotter
  def testSequenceAndOwnership(self):
82 162c1c1f Guido Trotter
    self.assert_(not self.sl._is_owned())
83 162c1c1f Guido Trotter
    self.sl.acquire(shared=1)
84 162c1c1f Guido Trotter
    self.assert_(self.sl._is_owned())
85 162c1c1f Guido Trotter
    self.assert_(self.sl._is_owned(shared=1))
86 162c1c1f Guido Trotter
    self.assert_(not self.sl._is_owned(shared=0))
87 162c1c1f Guido Trotter
    self.sl.release()
88 162c1c1f Guido Trotter
    self.assert_(not self.sl._is_owned())
89 162c1c1f Guido Trotter
    self.sl.acquire()
90 162c1c1f Guido Trotter
    self.assert_(self.sl._is_owned())
91 162c1c1f Guido Trotter
    self.assert_(not self.sl._is_owned(shared=1))
92 162c1c1f Guido Trotter
    self.assert_(self.sl._is_owned(shared=0))
93 162c1c1f Guido Trotter
    self.sl.release()
94 162c1c1f Guido Trotter
    self.assert_(not self.sl._is_owned())
95 162c1c1f Guido Trotter
    self.sl.acquire(shared=1)
96 162c1c1f Guido Trotter
    self.assert_(self.sl._is_owned())
97 162c1c1f Guido Trotter
    self.assert_(self.sl._is_owned(shared=1))
98 162c1c1f Guido Trotter
    self.assert_(not self.sl._is_owned(shared=0))
99 162c1c1f Guido Trotter
    self.sl.release()
100 162c1c1f Guido Trotter
    self.assert_(not self.sl._is_owned())
101 162c1c1f Guido Trotter
102 162c1c1f Guido Trotter
  def testBooleanValue(self):
103 162c1c1f Guido Trotter
    # semaphores are supposed to return a true value on a successful acquire
104 162c1c1f Guido Trotter
    self.assert_(self.sl.acquire(shared=1))
105 162c1c1f Guido Trotter
    self.sl.release()
106 162c1c1f Guido Trotter
    self.assert_(self.sl.acquire())
107 162c1c1f Guido Trotter
    self.sl.release()
108 162c1c1f Guido Trotter
109 162c1c1f Guido Trotter
  def testDoubleLockingStoE(self):
110 162c1c1f Guido Trotter
    self.sl.acquire(shared=1)
111 162c1c1f Guido Trotter
    self.assertRaises(AssertionError, self.sl.acquire)
112 162c1c1f Guido Trotter
113 162c1c1f Guido Trotter
  def testDoubleLockingEtoS(self):
114 162c1c1f Guido Trotter
    self.sl.acquire()
115 162c1c1f Guido Trotter
    self.assertRaises(AssertionError, self.sl.acquire, shared=1)
116 162c1c1f Guido Trotter
117 162c1c1f Guido Trotter
  def testDoubleLockingStoS(self):
118 162c1c1f Guido Trotter
    self.sl.acquire(shared=1)
119 162c1c1f Guido Trotter
    self.assertRaises(AssertionError, self.sl.acquire, shared=1)
120 162c1c1f Guido Trotter
121 162c1c1f Guido Trotter
  def testDoubleLockingEtoE(self):
122 162c1c1f Guido Trotter
    self.sl.acquire()
123 162c1c1f Guido Trotter
    self.assertRaises(AssertionError, self.sl.acquire)
124 162c1c1f Guido Trotter
125 162c1c1f Guido Trotter
  # helper functions: called in a separate thread they acquire the lock, send
126 162c1c1f Guido Trotter
  # their identifier on the done queue, then release it.
127 162c1c1f Guido Trotter
  def _doItSharer(self):
128 a95fd5d7 Guido Trotter
    try:
129 a95fd5d7 Guido Trotter
      self.sl.acquire(shared=1)
130 a95fd5d7 Guido Trotter
      self.done.put('SHR')
131 a95fd5d7 Guido Trotter
      self.sl.release()
132 a95fd5d7 Guido Trotter
    except errors.LockError:
133 a95fd5d7 Guido Trotter
      self.done.put('ERR')
134 162c1c1f Guido Trotter
135 162c1c1f Guido Trotter
  def _doItExclusive(self):
136 a95fd5d7 Guido Trotter
    try:
137 a95fd5d7 Guido Trotter
      self.sl.acquire()
138 a95fd5d7 Guido Trotter
      self.done.put('EXC')
139 a95fd5d7 Guido Trotter
      self.sl.release()
140 a95fd5d7 Guido Trotter
    except errors.LockError:
141 a95fd5d7 Guido Trotter
      self.done.put('ERR')
142 a95fd5d7 Guido Trotter
143 a95fd5d7 Guido Trotter
  def _doItDelete(self):
144 a95fd5d7 Guido Trotter
    try:
145 4354ab03 Guido Trotter
      self.sl.delete()
146 a95fd5d7 Guido Trotter
      self.done.put('DEL')
147 a95fd5d7 Guido Trotter
    except errors.LockError:
148 a95fd5d7 Guido Trotter
      self.done.put('ERR')
149 162c1c1f Guido Trotter
150 162c1c1f Guido Trotter
  def testSharersCanCoexist(self):
151 162c1c1f Guido Trotter
    self.sl.acquire(shared=1)
152 84e344d4 Michael Hanselmann
    threading.Thread(target=self._doItSharer).start()
153 162c1c1f Guido Trotter
    self.assert_(self.done.get(True, 1))
154 162c1c1f Guido Trotter
    self.sl.release()
155 162c1c1f Guido Trotter
156 4607c978 Iustin Pop
  @_Repeat
157 162c1c1f Guido Trotter
  def testExclusiveBlocksExclusive(self):
158 162c1c1f Guido Trotter
    self.sl.acquire()
159 4607c978 Iustin Pop
    self._addThread(target=self._doItExclusive)
160 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
161 162c1c1f Guido Trotter
    self.sl.release()
162 4607c978 Iustin Pop
    self._waitThreads()
163 4607c978 Iustin Pop
    self.failUnlessEqual(self.done.get_nowait(), 'EXC')
164 162c1c1f Guido Trotter
165 4607c978 Iustin Pop
  @_Repeat
166 a95fd5d7 Guido Trotter
  def testExclusiveBlocksDelete(self):
167 a95fd5d7 Guido Trotter
    self.sl.acquire()
168 4607c978 Iustin Pop
    self._addThread(target=self._doItDelete)
169 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
170 a95fd5d7 Guido Trotter
    self.sl.release()
171 4607c978 Iustin Pop
    self._waitThreads()
172 4607c978 Iustin Pop
    self.failUnlessEqual(self.done.get_nowait(), 'DEL')
173 4607c978 Iustin Pop
    self.sl = locking.SharedLock()
174 a95fd5d7 Guido Trotter
175 4607c978 Iustin Pop
  @_Repeat
176 162c1c1f Guido Trotter
  def testExclusiveBlocksSharer(self):
177 162c1c1f Guido Trotter
    self.sl.acquire()
178 4607c978 Iustin Pop
    self._addThread(target=self._doItSharer)
179 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
180 162c1c1f Guido Trotter
    self.sl.release()
181 4607c978 Iustin Pop
    self._waitThreads()
182 4607c978 Iustin Pop
    self.failUnlessEqual(self.done.get_nowait(), 'SHR')
183 162c1c1f Guido Trotter
184 4607c978 Iustin Pop
  @_Repeat
185 162c1c1f Guido Trotter
  def testSharerBlocksExclusive(self):
186 162c1c1f Guido Trotter
    self.sl.acquire(shared=1)
187 4607c978 Iustin Pop
    self._addThread(target=self._doItExclusive)
188 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
189 162c1c1f Guido Trotter
    self.sl.release()
190 4607c978 Iustin Pop
    self._waitThreads()
191 4607c978 Iustin Pop
    self.failUnlessEqual(self.done.get_nowait(), 'EXC')
192 162c1c1f Guido Trotter
193 4607c978 Iustin Pop
  @_Repeat
194 a95fd5d7 Guido Trotter
  def testSharerBlocksDelete(self):
195 a95fd5d7 Guido Trotter
    self.sl.acquire(shared=1)
196 4607c978 Iustin Pop
    self._addThread(target=self._doItDelete)
197 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
198 a95fd5d7 Guido Trotter
    self.sl.release()
199 4607c978 Iustin Pop
    self._waitThreads()
200 4607c978 Iustin Pop
    self.failUnlessEqual(self.done.get_nowait(), 'DEL')
201 4607c978 Iustin Pop
    self.sl = locking.SharedLock()
202 a95fd5d7 Guido Trotter
203 4607c978 Iustin Pop
  @_Repeat
204 162c1c1f Guido Trotter
  def testWaitingExclusiveBlocksSharer(self):
205 e6416152 Iustin Pop
    """SKIPPED testWaitingExclusiveBlockSharer"""
206 e6416152 Iustin Pop
    return
207 e6416152 Iustin Pop
208 162c1c1f Guido Trotter
    self.sl.acquire(shared=1)
209 162c1c1f Guido Trotter
    # the lock is acquired in shared mode...
210 4607c978 Iustin Pop
    self._addThread(target=self._doItExclusive)
211 162c1c1f Guido Trotter
    # ...but now an exclusive is waiting...
212 4607c978 Iustin Pop
    self._addThread(target=self._doItSharer)
213 162c1c1f Guido Trotter
    # ...so the sharer should be blocked as well
214 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
215 162c1c1f Guido Trotter
    self.sl.release()
216 4607c978 Iustin Pop
    self._waitThreads()
217 162c1c1f Guido Trotter
    # The exclusive passed before
218 4607c978 Iustin Pop
    self.failUnlessEqual(self.done.get_nowait(), 'EXC')
219 4607c978 Iustin Pop
    self.failUnlessEqual(self.done.get_nowait(), 'SHR')
220 162c1c1f Guido Trotter
221 4607c978 Iustin Pop
  @_Repeat
222 162c1c1f Guido Trotter
  def testWaitingSharerBlocksExclusive(self):
223 a143be68 Iustin Pop
    """SKIPPED testWaitingSharerBlocksExclusive"""
224 a143be68 Iustin Pop
    return
225 a143be68 Iustin Pop
226 162c1c1f Guido Trotter
    self.sl.acquire()
227 162c1c1f Guido Trotter
    # the lock is acquired in exclusive mode...
228 4607c978 Iustin Pop
    self._addThread(target=self._doItSharer)
229 162c1c1f Guido Trotter
    # ...but now a sharer is waiting...
230 4607c978 Iustin Pop
    self._addThread(target=self._doItExclusive)
231 162c1c1f Guido Trotter
    # ...the exclusive is waiting too...
232 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
233 162c1c1f Guido Trotter
    self.sl.release()
234 4607c978 Iustin Pop
    self._waitThreads()
235 162c1c1f Guido Trotter
    # The sharer passed before
236 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'SHR')
237 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'EXC')
238 162c1c1f Guido Trotter
239 a95fd5d7 Guido Trotter
  def testDelete(self):
240 a95fd5d7 Guido Trotter
    self.sl.delete()
241 a95fd5d7 Guido Trotter
    self.assertRaises(errors.LockError, self.sl.acquire)
242 84152b96 Guido Trotter
    self.assertRaises(errors.LockError, self.sl.acquire, shared=1)
243 a95fd5d7 Guido Trotter
    self.assertRaises(errors.LockError, self.sl.delete)
244 a95fd5d7 Guido Trotter
245 84152b96 Guido Trotter
  def testNoDeleteIfSharer(self):
246 84152b96 Guido Trotter
    self.sl.acquire(shared=1)
247 84152b96 Guido Trotter
    self.assertRaises(AssertionError, self.sl.delete)
248 84152b96 Guido Trotter
249 4607c978 Iustin Pop
  @_Repeat
250 a95fd5d7 Guido Trotter
  def testDeletePendingSharersExclusiveDelete(self):
251 a95fd5d7 Guido Trotter
    self.sl.acquire()
252 4607c978 Iustin Pop
    self._addThread(target=self._doItSharer)
253 4607c978 Iustin Pop
    self._addThread(target=self._doItSharer)
254 4607c978 Iustin Pop
    self._addThread(target=self._doItExclusive)
255 4607c978 Iustin Pop
    self._addThread(target=self._doItDelete)
256 a95fd5d7 Guido Trotter
    self.sl.delete()
257 4607c978 Iustin Pop
    self._waitThreads()
258 4607c978 Iustin Pop
    # The threads who were pending return ERR
259 4607c978 Iustin Pop
    for _ in range(4):
260 4607c978 Iustin Pop
      self.assertEqual(self.done.get_nowait(), 'ERR')
261 4607c978 Iustin Pop
    self.sl = locking.SharedLock()
262 a95fd5d7 Guido Trotter
263 4607c978 Iustin Pop
  @_Repeat
264 a95fd5d7 Guido Trotter
  def testDeletePendingDeleteExclusiveSharers(self):
265 a95fd5d7 Guido Trotter
    self.sl.acquire()
266 4607c978 Iustin Pop
    self._addThread(target=self._doItDelete)
267 4607c978 Iustin Pop
    self._addThread(target=self._doItExclusive)
268 4607c978 Iustin Pop
    self._addThread(target=self._doItSharer)
269 4607c978 Iustin Pop
    self._addThread(target=self._doItSharer)
270 a95fd5d7 Guido Trotter
    self.sl.delete()
271 4607c978 Iustin Pop
    self._waitThreads()
272 a95fd5d7 Guido Trotter
    # The two threads who were pending return both ERR
273 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'ERR')
274 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'ERR')
275 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'ERR')
276 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'ERR')
277 4607c978 Iustin Pop
    self.sl = locking.SharedLock()
278 a95fd5d7 Guido Trotter
279 84e344d4 Michael Hanselmann
  @_Repeat
280 84e344d4 Michael Hanselmann
  def testExclusiveAcquireTimeout(self):
281 84e344d4 Michael Hanselmann
    def _LockExclusive(wait):
282 84e344d4 Michael Hanselmann
      self.sl.acquire(shared=0)
283 84e344d4 Michael Hanselmann
      self.done.put("A: start sleep")
284 84e344d4 Michael Hanselmann
      time.sleep(wait)
285 84e344d4 Michael Hanselmann
      self.done.put("A: end sleep")
286 84e344d4 Michael Hanselmann
      self.sl.release()
287 84e344d4 Michael Hanselmann
288 84e344d4 Michael Hanselmann
    for shared in [0, 1]:
289 84e344d4 Michael Hanselmann
      # Start thread to hold lock for 20 ms
290 84e344d4 Michael Hanselmann
      self._addThread(target=_LockExclusive, args=(20.0 / 1000.0, ))
291 84e344d4 Michael Hanselmann
292 84e344d4 Michael Hanselmann
      # Wait up to 100 ms to get lock
293 84e344d4 Michael Hanselmann
      self.failUnless(self.sl.acquire(shared=shared, timeout=0.1))
294 84e344d4 Michael Hanselmann
      self.done.put("got 2nd")
295 84e344d4 Michael Hanselmann
      self.sl.release()
296 84e344d4 Michael Hanselmann
297 84e344d4 Michael Hanselmann
      self._waitThreads()
298 84e344d4 Michael Hanselmann
299 84e344d4 Michael Hanselmann
      self.assertEqual(self.done.get_nowait(), "A: start sleep")
300 84e344d4 Michael Hanselmann
      self.assertEqual(self.done.get_nowait(), "A: end sleep")
301 84e344d4 Michael Hanselmann
      self.assertEqual(self.done.get_nowait(), "got 2nd")
302 84e344d4 Michael Hanselmann
      self.assertRaises(Queue.Empty, self.done.get_nowait)
303 84e344d4 Michael Hanselmann
304 84e344d4 Michael Hanselmann
  @_Repeat
305 84e344d4 Michael Hanselmann
  def testAcquireExpiringTimeout(self):
306 84e344d4 Michael Hanselmann
    def _AcquireWithTimeout(shared, timeout):
307 84e344d4 Michael Hanselmann
      if not self.sl.acquire(shared=shared, timeout=timeout):
308 84e344d4 Michael Hanselmann
        self.done.put("timeout")
309 84e344d4 Michael Hanselmann
310 84e344d4 Michael Hanselmann
    for shared in [0, 1]:
311 84e344d4 Michael Hanselmann
      # Lock exclusively
312 84e344d4 Michael Hanselmann
      self.sl.acquire()
313 84e344d4 Michael Hanselmann
314 84e344d4 Michael Hanselmann
      # Start shared acquires with timeout between 0 and 20 ms
315 84e344d4 Michael Hanselmann
      for i in xrange(11):
316 84e344d4 Michael Hanselmann
        self._addThread(target=_AcquireWithTimeout,
317 84e344d4 Michael Hanselmann
                        args=(shared, i * 2.0 / 1000.0))
318 84e344d4 Michael Hanselmann
319 84e344d4 Michael Hanselmann
      # Wait for threads to finish (makes sure the acquire timeout expires
320 84e344d4 Michael Hanselmann
      # before releasing the lock)
321 84e344d4 Michael Hanselmann
      self._waitThreads()
322 84e344d4 Michael Hanselmann
323 84e344d4 Michael Hanselmann
      # Release lock
324 84e344d4 Michael Hanselmann
      self.sl.release()
325 84e344d4 Michael Hanselmann
326 84e344d4 Michael Hanselmann
      for _ in xrange(11):
327 84e344d4 Michael Hanselmann
        self.assertEqual(self.done.get_nowait(), "timeout")
328 84e344d4 Michael Hanselmann
329 84e344d4 Michael Hanselmann
      self.assertRaises(Queue.Empty, self.done.get_nowait)
330 84e344d4 Michael Hanselmann
331 84e344d4 Michael Hanselmann
  @_Repeat
332 84e344d4 Michael Hanselmann
  def testSharedSkipExclusiveAcquires(self):
333 84e344d4 Michael Hanselmann
    # Tests whether shared acquires jump in front of exclusive acquires in the
334 84e344d4 Michael Hanselmann
    # queue.
335 84e344d4 Michael Hanselmann
336 84e344d4 Michael Hanselmann
    # Get exclusive lock while we fill the queue
337 84e344d4 Michael Hanselmann
    self.sl.acquire()
338 84e344d4 Michael Hanselmann
339 84e344d4 Michael Hanselmann
    def _Acquire(shared, name):
340 84e344d4 Michael Hanselmann
      if not self.sl.acquire(shared=shared):
341 84e344d4 Michael Hanselmann
        return
342 84e344d4 Michael Hanselmann
343 84e344d4 Michael Hanselmann
      self.done.put(name)
344 84e344d4 Michael Hanselmann
      self.sl.release()
345 84e344d4 Michael Hanselmann
346 84e344d4 Michael Hanselmann
    # Start shared acquires
347 84e344d4 Michael Hanselmann
    for _ in xrange(5):
348 84e344d4 Michael Hanselmann
      self._addThread(target=_Acquire, args=(1, "shared A"))
349 84e344d4 Michael Hanselmann
350 84e344d4 Michael Hanselmann
    # Start exclusive acquires
351 84e344d4 Michael Hanselmann
    for _ in xrange(3):
352 84e344d4 Michael Hanselmann
      self._addThread(target=_Acquire, args=(0, "exclusive B"))
353 84e344d4 Michael Hanselmann
354 84e344d4 Michael Hanselmann
    # More shared acquires
355 84e344d4 Michael Hanselmann
    for _ in xrange(5):
356 84e344d4 Michael Hanselmann
      self._addThread(target=_Acquire, args=(1, "shared C"))
357 84e344d4 Michael Hanselmann
358 84e344d4 Michael Hanselmann
    # More exclusive acquires
359 84e344d4 Michael Hanselmann
    for _ in xrange(3):
360 84e344d4 Michael Hanselmann
      self._addThread(target=_Acquire, args=(0, "exclusive D"))
361 84e344d4 Michael Hanselmann
362 84e344d4 Michael Hanselmann
    # Expect 6 pending exclusive acquires and 1 for all shared acquires
363 84e344d4 Michael Hanselmann
    # together
364 84e344d4 Michael Hanselmann
    self.assertEqual(self.sl._count_pending(), 7)
365 84e344d4 Michael Hanselmann
366 84e344d4 Michael Hanselmann
    # Release exclusive lock and wait
367 84e344d4 Michael Hanselmann
    self.sl.release()
368 84e344d4 Michael Hanselmann
369 84e344d4 Michael Hanselmann
    self._waitThreads()
370 84e344d4 Michael Hanselmann
371 84e344d4 Michael Hanselmann
    # Check sequence
372 84e344d4 Michael Hanselmann
    for _ in xrange(10):
373 84e344d4 Michael Hanselmann
      # Shared locks aren't guaranteed to be notified in order, but they'll be
374 84e344d4 Michael Hanselmann
      # first
375 84e344d4 Michael Hanselmann
      self.assert_(self.done.get_nowait() in ("shared A", "shared C"))
376 84e344d4 Michael Hanselmann
377 84e344d4 Michael Hanselmann
    for _ in xrange(3):
378 84e344d4 Michael Hanselmann
      self.assertEqual(self.done.get_nowait(), "exclusive B")
379 84e344d4 Michael Hanselmann
380 84e344d4 Michael Hanselmann
    for _ in xrange(3):
381 84e344d4 Michael Hanselmann
      self.assertEqual(self.done.get_nowait(), "exclusive D")
382 84e344d4 Michael Hanselmann
383 84e344d4 Michael Hanselmann
    self.assertRaises(Queue.Empty, self.done.get_nowait)
384 84e344d4 Michael Hanselmann
385 84e344d4 Michael Hanselmann
  @_Repeat
386 84e344d4 Michael Hanselmann
  def testMixedAcquireTimeout(self):
387 84e344d4 Michael Hanselmann
    sync = threading.Condition()
388 84e344d4 Michael Hanselmann
389 84e344d4 Michael Hanselmann
    def _AcquireShared(ev):
390 84e344d4 Michael Hanselmann
      if not self.sl.acquire(shared=1, timeout=None):
391 84e344d4 Michael Hanselmann
        return
392 84e344d4 Michael Hanselmann
393 84e344d4 Michael Hanselmann
      self.done.put("shared")
394 84e344d4 Michael Hanselmann
395 84e344d4 Michael Hanselmann
      # Notify main thread
396 84e344d4 Michael Hanselmann
      ev.set()
397 84e344d4 Michael Hanselmann
398 84e344d4 Michael Hanselmann
      # Wait for notification
399 84e344d4 Michael Hanselmann
      sync.acquire()
400 84e344d4 Michael Hanselmann
      try:
401 84e344d4 Michael Hanselmann
        sync.wait()
402 84e344d4 Michael Hanselmann
      finally:
403 84e344d4 Michael Hanselmann
        sync.release()
404 84e344d4 Michael Hanselmann
405 84e344d4 Michael Hanselmann
      # Release lock
406 84e344d4 Michael Hanselmann
      self.sl.release()
407 84e344d4 Michael Hanselmann
408 84e344d4 Michael Hanselmann
    acquires = []
409 84e344d4 Michael Hanselmann
    for _ in xrange(3):
410 84e344d4 Michael Hanselmann
      ev = threading.Event()
411 84e344d4 Michael Hanselmann
      self._addThread(target=_AcquireShared, args=(ev, ))
412 84e344d4 Michael Hanselmann
      acquires.append(ev)
413 84e344d4 Michael Hanselmann
414 84e344d4 Michael Hanselmann
    # Wait for all acquires to finish
415 84e344d4 Michael Hanselmann
    for i in acquires:
416 84e344d4 Michael Hanselmann
      i.wait()
417 84e344d4 Michael Hanselmann
418 84e344d4 Michael Hanselmann
    self.assertEqual(self.sl._count_pending(), 0)
419 84e344d4 Michael Hanselmann
420 84e344d4 Michael Hanselmann
    # Try to get exclusive lock
421 84e344d4 Michael Hanselmann
    self.failIf(self.sl.acquire(shared=0, timeout=0.02))
422 84e344d4 Michael Hanselmann
423 84e344d4 Michael Hanselmann
    # Acquire exclusive without timeout
424 84e344d4 Michael Hanselmann
    exclsync = threading.Condition()
425 84e344d4 Michael Hanselmann
    exclev = threading.Event()
426 84e344d4 Michael Hanselmann
427 84e344d4 Michael Hanselmann
    def _AcquireExclusive():
428 84e344d4 Michael Hanselmann
      if not self.sl.acquire(shared=0):
429 84e344d4 Michael Hanselmann
        return
430 84e344d4 Michael Hanselmann
431 84e344d4 Michael Hanselmann
      self.done.put("exclusive")
432 84e344d4 Michael Hanselmann
433 84e344d4 Michael Hanselmann
      # Notify main thread
434 84e344d4 Michael Hanselmann
      exclev.set()
435 84e344d4 Michael Hanselmann
436 84e344d4 Michael Hanselmann
      exclsync.acquire()
437 84e344d4 Michael Hanselmann
      try:
438 84e344d4 Michael Hanselmann
        exclsync.wait()
439 84e344d4 Michael Hanselmann
      finally:
440 84e344d4 Michael Hanselmann
        exclsync.release()
441 84e344d4 Michael Hanselmann
442 84e344d4 Michael Hanselmann
      self.sl.release()
443 84e344d4 Michael Hanselmann
444 84e344d4 Michael Hanselmann
    self._addThread(target=_AcquireExclusive)
445 84e344d4 Michael Hanselmann
446 84e344d4 Michael Hanselmann
    # Try to get exclusive lock
447 84e344d4 Michael Hanselmann
    self.failIf(self.sl.acquire(shared=0, timeout=0.02))
448 84e344d4 Michael Hanselmann
449 84e344d4 Michael Hanselmann
    # Make all shared holders release their locks
450 84e344d4 Michael Hanselmann
    sync.acquire()
451 84e344d4 Michael Hanselmann
    try:
452 84e344d4 Michael Hanselmann
      sync.notifyAll()
453 84e344d4 Michael Hanselmann
    finally:
454 84e344d4 Michael Hanselmann
      sync.release()
455 84e344d4 Michael Hanselmann
456 84e344d4 Michael Hanselmann
    # Wait for exclusive acquire to succeed
457 84e344d4 Michael Hanselmann
    exclev.wait()
458 84e344d4 Michael Hanselmann
459 84e344d4 Michael Hanselmann
    self.assertEqual(self.sl._count_pending(), 0)
460 84e344d4 Michael Hanselmann
461 84e344d4 Michael Hanselmann
    # Try to get exclusive lock
462 84e344d4 Michael Hanselmann
    self.failIf(self.sl.acquire(shared=0, timeout=0.02))
463 84e344d4 Michael Hanselmann
464 84e344d4 Michael Hanselmann
    def _AcquireSharedSimple():
465 84e344d4 Michael Hanselmann
      if self.sl.acquire(shared=1, timeout=None):
466 84e344d4 Michael Hanselmann
        self.done.put("shared2")
467 84e344d4 Michael Hanselmann
        self.sl.release()
468 84e344d4 Michael Hanselmann
469 84e344d4 Michael Hanselmann
    for _ in xrange(10):
470 84e344d4 Michael Hanselmann
      self._addThread(target=_AcquireSharedSimple)
471 84e344d4 Michael Hanselmann
472 84e344d4 Michael Hanselmann
    # Tell exclusive lock to release
473 84e344d4 Michael Hanselmann
    exclsync.acquire()
474 84e344d4 Michael Hanselmann
    try:
475 84e344d4 Michael Hanselmann
      exclsync.notifyAll()
476 84e344d4 Michael Hanselmann
    finally:
477 84e344d4 Michael Hanselmann
      exclsync.release()
478 84e344d4 Michael Hanselmann
479 84e344d4 Michael Hanselmann
    # Wait for everything to finish
480 84e344d4 Michael Hanselmann
    self._waitThreads()
481 84e344d4 Michael Hanselmann
482 84e344d4 Michael Hanselmann
    self.assertEqual(self.sl._count_pending(), 0)
483 84e344d4 Michael Hanselmann
484 84e344d4 Michael Hanselmann
    # Check sequence
485 84e344d4 Michael Hanselmann
    for _ in xrange(3):
486 84e344d4 Michael Hanselmann
      self.assertEqual(self.done.get_nowait(), "shared")
487 84e344d4 Michael Hanselmann
488 84e344d4 Michael Hanselmann
    self.assertEqual(self.done.get_nowait(), "exclusive")
489 84e344d4 Michael Hanselmann
490 84e344d4 Michael Hanselmann
    for _ in xrange(10):
491 84e344d4 Michael Hanselmann
      self.assertEqual(self.done.get_nowait(), "shared2")
492 84e344d4 Michael Hanselmann
493 84e344d4 Michael Hanselmann
    self.assertRaises(Queue.Empty, self.done.get_nowait)
494 84e344d4 Michael Hanselmann
495 162c1c1f Guido Trotter
496 4607c978 Iustin Pop
class TestSSynchronizedDecorator(_ThreadedTestCase):
497 42a999d1 Guido Trotter
  """Shared Lock Synchronized decorator test"""
498 42a999d1 Guido Trotter
499 42a999d1 Guido Trotter
  def setUp(self):
500 4607c978 Iustin Pop
    _ThreadedTestCase.setUp(self)
501 42a999d1 Guido Trotter
    # helper threads use the 'done' queue to tell the master they finished.
502 42a999d1 Guido Trotter
    self.done = Queue.Queue(0)
503 42a999d1 Guido Trotter
504 42a999d1 Guido Trotter
  @locking.ssynchronized(_decoratorlock)
505 42a999d1 Guido Trotter
  def _doItExclusive(self):
506 42a999d1 Guido Trotter
    self.assert_(_decoratorlock._is_owned())
507 42a999d1 Guido Trotter
    self.done.put('EXC')
508 42a999d1 Guido Trotter
509 42a999d1 Guido Trotter
  @locking.ssynchronized(_decoratorlock, shared=1)
510 42a999d1 Guido Trotter
  def _doItSharer(self):
511 42a999d1 Guido Trotter
    self.assert_(_decoratorlock._is_owned(shared=1))
512 42a999d1 Guido Trotter
    self.done.put('SHR')
513 42a999d1 Guido Trotter
514 42a999d1 Guido Trotter
  def testDecoratedFunctions(self):
515 42a999d1 Guido Trotter
    self._doItExclusive()
516 42a999d1 Guido Trotter
    self.assert_(not _decoratorlock._is_owned())
517 42a999d1 Guido Trotter
    self._doItSharer()
518 42a999d1 Guido Trotter
    self.assert_(not _decoratorlock._is_owned())
519 42a999d1 Guido Trotter
520 42a999d1 Guido Trotter
  def testSharersCanCoexist(self):
521 42a999d1 Guido Trotter
    _decoratorlock.acquire(shared=1)
522 84e344d4 Michael Hanselmann
    threading.Thread(target=self._doItSharer).start()
523 42a999d1 Guido Trotter
    self.assert_(self.done.get(True, 1))
524 42a999d1 Guido Trotter
    _decoratorlock.release()
525 42a999d1 Guido Trotter
526 4607c978 Iustin Pop
  @_Repeat
527 42a999d1 Guido Trotter
  def testExclusiveBlocksExclusive(self):
528 42a999d1 Guido Trotter
    _decoratorlock.acquire()
529 4607c978 Iustin Pop
    self._addThread(target=self._doItExclusive)
530 42a999d1 Guido Trotter
    # give it a bit of time to check that it's not actually doing anything
531 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
532 42a999d1 Guido Trotter
    _decoratorlock.release()
533 4607c978 Iustin Pop
    self._waitThreads()
534 4607c978 Iustin Pop
    self.failUnlessEqual(self.done.get_nowait(), 'EXC')
535 42a999d1 Guido Trotter
536 4607c978 Iustin Pop
  @_Repeat
537 42a999d1 Guido Trotter
  def testExclusiveBlocksSharer(self):
538 42a999d1 Guido Trotter
    _decoratorlock.acquire()
539 4607c978 Iustin Pop
    self._addThread(target=self._doItSharer)
540 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
541 42a999d1 Guido Trotter
    _decoratorlock.release()
542 4607c978 Iustin Pop
    self._waitThreads()
543 4607c978 Iustin Pop
    self.failUnlessEqual(self.done.get_nowait(), 'SHR')
544 42a999d1 Guido Trotter
545 4607c978 Iustin Pop
  @_Repeat
546 42a999d1 Guido Trotter
  def testSharerBlocksExclusive(self):
547 42a999d1 Guido Trotter
    _decoratorlock.acquire(shared=1)
548 4607c978 Iustin Pop
    self._addThread(target=self._doItExclusive)
549 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
550 42a999d1 Guido Trotter
    _decoratorlock.release()
551 4607c978 Iustin Pop
    self._waitThreads()
552 4607c978 Iustin Pop
    self.failUnlessEqual(self.done.get_nowait(), 'EXC')
553 42a999d1 Guido Trotter
554 42a999d1 Guido Trotter
555 4607c978 Iustin Pop
class TestLockSet(_ThreadedTestCase):
556 aaae9bc0 Guido Trotter
  """LockSet tests"""
557 aaae9bc0 Guido Trotter
558 aaae9bc0 Guido Trotter
  def setUp(self):
559 4607c978 Iustin Pop
    _ThreadedTestCase.setUp(self)
560 4607c978 Iustin Pop
    self._setUpLS()
561 aaae9bc0 Guido Trotter
    # helper threads use the 'done' queue to tell the master they finished.
562 aaae9bc0 Guido Trotter
    self.done = Queue.Queue(0)
563 aaae9bc0 Guido Trotter
564 4607c978 Iustin Pop
  def _setUpLS(self):
565 4607c978 Iustin Pop
    """Helper to (re)initialize the lock set"""
566 4607c978 Iustin Pop
    self.resources = ['one', 'two', 'three']
567 4607c978 Iustin Pop
    self.ls = locking.LockSet(members=self.resources)
568 4607c978 Iustin Pop
569 aaae9bc0 Guido Trotter
  def testResources(self):
570 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._names(), set(self.resources))
571 aaae9bc0 Guido Trotter
    newls = locking.LockSet()
572 aaae9bc0 Guido Trotter
    self.assertEquals(newls._names(), set())
573 aaae9bc0 Guido Trotter
574 aaae9bc0 Guido Trotter
  def testAcquireRelease(self):
575 0cc00929 Guido Trotter
    self.assert_(self.ls.acquire('one'))
576 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['one']))
577 aaae9bc0 Guido Trotter
    self.ls.release()
578 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set())
579 0cc00929 Guido Trotter
    self.assertEquals(self.ls.acquire(['one']), set(['one']))
580 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['one']))
581 aaae9bc0 Guido Trotter
    self.ls.release()
582 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set())
583 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'two', 'three'])
584 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['one', 'two', 'three']))
585 aaae9bc0 Guido Trotter
    self.ls.release('one')
586 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['two', 'three']))
587 aaae9bc0 Guido Trotter
    self.ls.release(['three'])
588 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['two']))
589 aaae9bc0 Guido Trotter
    self.ls.release()
590 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set())
591 0cc00929 Guido Trotter
    self.assertEquals(self.ls.acquire(['one', 'three']), set(['one', 'three']))
592 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['one', 'three']))
593 aaae9bc0 Guido Trotter
    self.ls.release()
594 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set())
595 aaae9bc0 Guido Trotter
596 aaae9bc0 Guido Trotter
  def testNoDoubleAcquire(self):
597 aaae9bc0 Guido Trotter
    self.ls.acquire('one')
598 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.acquire, 'one')
599 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.acquire, ['two'])
600 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.acquire, ['two', 'three'])
601 aaae9bc0 Guido Trotter
    self.ls.release()
602 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'three'])
603 aaae9bc0 Guido Trotter
    self.ls.release('one')
604 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.acquire, ['two'])
605 aaae9bc0 Guido Trotter
    self.ls.release('three')
606 aaae9bc0 Guido Trotter
607 aaae9bc0 Guido Trotter
  def testNoWrongRelease(self):
608 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.release)
609 aaae9bc0 Guido Trotter
    self.ls.acquire('one')
610 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.release, 'two')
611 aaae9bc0 Guido Trotter
612 aaae9bc0 Guido Trotter
  def testAddRemove(self):
613 aaae9bc0 Guido Trotter
    self.ls.add('four')
614 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set())
615 aaae9bc0 Guido Trotter
    self.assert_('four' in self.ls._names())
616 aaae9bc0 Guido Trotter
    self.ls.add(['five', 'six', 'seven'], acquired=1)
617 aaae9bc0 Guido Trotter
    self.assert_('five' in self.ls._names())
618 aaae9bc0 Guido Trotter
    self.assert_('six' in self.ls._names())
619 aaae9bc0 Guido Trotter
    self.assert_('seven' in self.ls._names())
620 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['five', 'six', 'seven']))
621 3f404fc5 Guido Trotter
    self.assertEquals(self.ls.remove(['five', 'six']), ['five', 'six'])
622 aaae9bc0 Guido Trotter
    self.assert_('five' not in self.ls._names())
623 aaae9bc0 Guido Trotter
    self.assert_('six' not in self.ls._names())
624 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['seven']))
625 d2aff862 Guido Trotter
    self.assertRaises(AssertionError, self.ls.add, 'eight', acquired=1)
626 aaae9bc0 Guido Trotter
    self.ls.remove('seven')
627 aaae9bc0 Guido Trotter
    self.assert_('seven' not in self.ls._names())
628 d2aff862 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set([]))
629 d2aff862 Guido Trotter
    self.ls.acquire(None, shared=1)
630 d2aff862 Guido Trotter
    self.assertRaises(AssertionError, self.ls.add, 'eight')
631 d2aff862 Guido Trotter
    self.ls.release()
632 d2aff862 Guido Trotter
    self.ls.acquire(None)
633 d2aff862 Guido Trotter
    self.ls.add('eight', acquired=1)
634 d2aff862 Guido Trotter
    self.assert_('eight' in self.ls._names())
635 d2aff862 Guido Trotter
    self.assert_('eight' in self.ls._list_owned())
636 d2aff862 Guido Trotter
    self.ls.add('nine')
637 d2aff862 Guido Trotter
    self.assert_('nine' in self.ls._names())
638 d2aff862 Guido Trotter
    self.assert_('nine' not in self.ls._list_owned())
639 aaae9bc0 Guido Trotter
    self.ls.release()
640 aaae9bc0 Guido Trotter
    self.ls.remove(['two'])
641 aaae9bc0 Guido Trotter
    self.assert_('two' not in self.ls._names())
642 aaae9bc0 Guido Trotter
    self.ls.acquire('three')
643 3f404fc5 Guido Trotter
    self.assertEquals(self.ls.remove(['three']), ['three'])
644 aaae9bc0 Guido Trotter
    self.assert_('three' not in self.ls._names())
645 3f404fc5 Guido Trotter
    self.assertEquals(self.ls.remove('three'), [])
646 3f404fc5 Guido Trotter
    self.assertEquals(self.ls.remove(['one', 'three', 'six']), ['one'])
647 aaae9bc0 Guido Trotter
    self.assert_('one' not in self.ls._names())
648 aaae9bc0 Guido Trotter
649 aaae9bc0 Guido Trotter
  def testRemoveNonBlocking(self):
650 aaae9bc0 Guido Trotter
    self.assertRaises(NotImplementedError, self.ls.remove, 'one', blocking=0)
651 aaae9bc0 Guido Trotter
    self.ls.acquire('one')
652 3f404fc5 Guido Trotter
    self.assertEquals(self.ls.remove('one', blocking=0), ['one'])
653 aaae9bc0 Guido Trotter
    self.ls.acquire(['two', 'three'])
654 3f404fc5 Guido Trotter
    self.assertEquals(self.ls.remove(['two', 'three'], blocking=0),
655 3f404fc5 Guido Trotter
                      ['two', 'three'])
656 aaae9bc0 Guido Trotter
657 aaae9bc0 Guido Trotter
  def testNoDoubleAdd(self):
658 aaae9bc0 Guido Trotter
    self.assertRaises(errors.LockError, self.ls.add, 'two')
659 aaae9bc0 Guido Trotter
    self.ls.add('four')
660 aaae9bc0 Guido Trotter
    self.assertRaises(errors.LockError, self.ls.add, 'four')
661 aaae9bc0 Guido Trotter
662 aaae9bc0 Guido Trotter
  def testNoWrongRemoves(self):
663 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'three'], shared=1)
664 aaae9bc0 Guido Trotter
    # Cannot remove 'two' while holding something which is not a superset
665 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.remove, 'two')
666 aaae9bc0 Guido Trotter
    # Cannot remove 'three' as we are sharing it
667 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.remove, 'three')
668 aaae9bc0 Guido Trotter
669 3b7ed473 Guido Trotter
  def testAcquireSetLock(self):
670 3b7ed473 Guido Trotter
    # acquire the set-lock exclusively
671 3b7ed473 Guido Trotter
    self.assertEquals(self.ls.acquire(None), set(['one', 'two', 'three']))
672 d4803c24 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['one', 'two', 'three']))
673 d4803c24 Guido Trotter
    self.assertEquals(self.ls._is_owned(), True)
674 d4803c24 Guido Trotter
    self.assertEquals(self.ls._names(), set(['one', 'two', 'three']))
675 3b7ed473 Guido Trotter
    # I can still add/remove elements...
676 3b7ed473 Guido Trotter
    self.assertEquals(self.ls.remove(['two', 'three']), ['two', 'three'])
677 3b7ed473 Guido Trotter
    self.assert_(self.ls.add('six'))
678 3b7ed473 Guido Trotter
    self.ls.release()
679 3b7ed473 Guido Trotter
    # share the set-lock
680 3b7ed473 Guido Trotter
    self.assertEquals(self.ls.acquire(None, shared=1), set(['one', 'six']))
681 3b7ed473 Guido Trotter
    # adding new elements is not possible
682 3b7ed473 Guido Trotter
    self.assertRaises(AssertionError, self.ls.add, 'five')
683 3b7ed473 Guido Trotter
    self.ls.release()
684 3b7ed473 Guido Trotter
685 d4f6a91c Guido Trotter
  def testAcquireWithRepetitions(self):
686 d4f6a91c Guido Trotter
    self.assertEquals(self.ls.acquire(['two', 'two', 'three'], shared=1),
687 d4f6a91c Guido Trotter
                      set(['two', 'two', 'three']))
688 d4f6a91c Guido Trotter
    self.ls.release(['two', 'two'])
689 d4f6a91c Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['three']))
690 d4f6a91c Guido Trotter
691 2e1d6d96 Guido Trotter
  def testEmptyAcquire(self):
692 2e1d6d96 Guido Trotter
    # Acquire an empty list of locks...
693 2e1d6d96 Guido Trotter
    self.assertEquals(self.ls.acquire([]), set())
694 2e1d6d96 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set())
695 2e1d6d96 Guido Trotter
    # New locks can still be addded
696 2e1d6d96 Guido Trotter
    self.assert_(self.ls.add('six'))
697 2e1d6d96 Guido Trotter
    # "re-acquiring" is not an issue, since we had really acquired nothing
698 2e1d6d96 Guido Trotter
    self.assertEquals(self.ls.acquire([], shared=1), set())
699 2e1d6d96 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set())
700 2e1d6d96 Guido Trotter
    # We haven't really acquired anything, so we cannot release
701 2e1d6d96 Guido Trotter
    self.assertRaises(AssertionError, self.ls.release)
702 2e1d6d96 Guido Trotter
703 84e344d4 Michael Hanselmann
  def _doLockSet(self, names, shared):
704 aaae9bc0 Guido Trotter
    try:
705 84e344d4 Michael Hanselmann
      self.ls.acquire(names, shared=shared)
706 aaae9bc0 Guido Trotter
      self.done.put('DONE')
707 aaae9bc0 Guido Trotter
      self.ls.release()
708 aaae9bc0 Guido Trotter
    except errors.LockError:
709 aaae9bc0 Guido Trotter
      self.done.put('ERR')
710 aaae9bc0 Guido Trotter
711 84e344d4 Michael Hanselmann
  def _doAddSet(self, names):
712 3b7ed473 Guido Trotter
    try:
713 84e344d4 Michael Hanselmann
      self.ls.add(names, acquired=1)
714 3b7ed473 Guido Trotter
      self.done.put('DONE')
715 3b7ed473 Guido Trotter
      self.ls.release()
716 3b7ed473 Guido Trotter
    except errors.LockError:
717 3b7ed473 Guido Trotter
      self.done.put('ERR')
718 3b7ed473 Guido Trotter
719 84e344d4 Michael Hanselmann
  def _doRemoveSet(self, names):
720 84e344d4 Michael Hanselmann
    self.done.put(self.ls.remove(names))
721 aaae9bc0 Guido Trotter
722 4607c978 Iustin Pop
  @_Repeat
723 aaae9bc0 Guido Trotter
  def testConcurrentSharedAcquire(self):
724 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'two'], shared=1)
725 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['one', 'two'], 1))
726 4607c978 Iustin Pop
    self._waitThreads()
727 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
728 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['one', 'two', 'three'], 1))
729 4607c978 Iustin Pop
    self._waitThreads()
730 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
731 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=('three', 1))
732 4607c978 Iustin Pop
    self._waitThreads()
733 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
734 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['one', 'two'], 0))
735 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['two', 'three'], 0))
736 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
737 aaae9bc0 Guido Trotter
    self.ls.release()
738 4607c978 Iustin Pop
    self._waitThreads()
739 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
740 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
741 aaae9bc0 Guido Trotter
742 4607c978 Iustin Pop
  @_Repeat
743 aaae9bc0 Guido Trotter
  def testConcurrentExclusiveAcquire(self):
744 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'two'])
745 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=('three', 1))
746 4607c978 Iustin Pop
    self._waitThreads()
747 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
748 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=('three', 0))
749 4607c978 Iustin Pop
    self._waitThreads()
750 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
751 84e344d4 Michael Hanselmann
    self.assertRaises(Queue.Empty, self.done.get_nowait)
752 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['one', 'two'], 0))
753 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['one', 'two'], 1))
754 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=('one', 0))
755 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=('one', 1))
756 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['two', 'three'], 0))
757 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['two', 'three'], 1))
758 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
759 aaae9bc0 Guido Trotter
    self.ls.release()
760 4607c978 Iustin Pop
    self._waitThreads()
761 4607c978 Iustin Pop
    for _ in range(6):
762 4607c978 Iustin Pop
      self.failUnlessEqual(self.done.get_nowait(), 'DONE')
763 aaae9bc0 Guido Trotter
764 4607c978 Iustin Pop
  @_Repeat
765 aaae9bc0 Guido Trotter
  def testConcurrentRemove(self):
766 aaae9bc0 Guido Trotter
    self.ls.add('four')
767 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'two', 'four'])
768 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['one', 'four'], 0))
769 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['one', 'four'], 1))
770 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['one', 'two'], 0))
771 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['one', 'two'], 1))
772 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
773 aaae9bc0 Guido Trotter
    self.ls.remove('one')
774 aaae9bc0 Guido Trotter
    self.ls.release()
775 4607c978 Iustin Pop
    self._waitThreads()
776 4607c978 Iustin Pop
    for i in range(4):
777 4607c978 Iustin Pop
      self.failUnlessEqual(self.done.get_nowait(), 'ERR')
778 aaae9bc0 Guido Trotter
    self.ls.add(['five', 'six'], acquired=1)
779 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['three', 'six'], 1))
780 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['three', 'six'], 0))
781 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['four', 'six'], 1))
782 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['four', 'six'], 0))
783 aaae9bc0 Guido Trotter
    self.ls.remove('five')
784 aaae9bc0 Guido Trotter
    self.ls.release()
785 4607c978 Iustin Pop
    self._waitThreads()
786 4607c978 Iustin Pop
    for i in range(4):
787 4607c978 Iustin Pop
      self.failUnlessEqual(self.done.get_nowait(), 'DONE')
788 aaae9bc0 Guido Trotter
    self.ls.acquire(['three', 'four'])
789 4607c978 Iustin Pop
    self._addThread(target=self._doRemoveSet, args=(['four', 'six'], ))
790 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
791 aaae9bc0 Guido Trotter
    self.ls.remove('four')
792 4607c978 Iustin Pop
    self._waitThreads()
793 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), ['six'])
794 4607c978 Iustin Pop
    self._addThread(target=self._doRemoveSet, args=(['two']))
795 4607c978 Iustin Pop
    self._waitThreads()
796 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), ['two'])
797 aaae9bc0 Guido Trotter
    self.ls.release()
798 4607c978 Iustin Pop
    # reset lockset
799 4607c978 Iustin Pop
    self._setUpLS()
800 aaae9bc0 Guido Trotter
801 4607c978 Iustin Pop
  @_Repeat
802 3b7ed473 Guido Trotter
  def testConcurrentSharedSetLock(self):
803 3b7ed473 Guido Trotter
    # share the set-lock...
804 3b7ed473 Guido Trotter
    self.ls.acquire(None, shared=1)
805 3b7ed473 Guido Trotter
    # ...another thread can share it too
806 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(None, 1))
807 4607c978 Iustin Pop
    self._waitThreads()
808 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
809 3b7ed473 Guido Trotter
    # ...or just share some elements
810 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['one', 'three'], 1))
811 4607c978 Iustin Pop
    self._waitThreads()
812 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
813 3b7ed473 Guido Trotter
    # ...but not add new ones or remove any
814 4607c978 Iustin Pop
    t = self._addThread(target=self._doAddSet, args=(['nine']))
815 4607c978 Iustin Pop
    self._addThread(target=self._doRemoveSet, args=(['two'], ))
816 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
817 3b7ed473 Guido Trotter
    # this just releases the set-lock
818 3b7ed473 Guido Trotter
    self.ls.release([])
819 4607c978 Iustin Pop
    t.join(60)
820 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
821 3b7ed473 Guido Trotter
    # release the lock on the actual elements so remove() can proceed too
822 3b7ed473 Guido Trotter
    self.ls.release()
823 4607c978 Iustin Pop
    self._waitThreads()
824 4607c978 Iustin Pop
    self.failUnlessEqual(self.done.get_nowait(), ['two'])
825 4607c978 Iustin Pop
    # reset lockset
826 4607c978 Iustin Pop
    self._setUpLS()
827 3b7ed473 Guido Trotter
828 4607c978 Iustin Pop
  @_Repeat
829 3b7ed473 Guido Trotter
  def testConcurrentExclusiveSetLock(self):
830 3b7ed473 Guido Trotter
    # acquire the set-lock...
831 3b7ed473 Guido Trotter
    self.ls.acquire(None, shared=0)
832 3b7ed473 Guido Trotter
    # ...no one can do anything else
833 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(None, 1))
834 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(None, 0))
835 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['three'], 0))
836 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(['two'], 1))
837 4607c978 Iustin Pop
    self._addThread(target=self._doAddSet, args=(['nine']))
838 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
839 3b7ed473 Guido Trotter
    self.ls.release()
840 4607c978 Iustin Pop
    self._waitThreads()
841 4607c978 Iustin Pop
    for _ in range(5):
842 4607c978 Iustin Pop
      self.assertEqual(self.done.get(True, 1), 'DONE')
843 4607c978 Iustin Pop
    # cleanup
844 4607c978 Iustin Pop
    self._setUpLS()
845 3b7ed473 Guido Trotter
846 4607c978 Iustin Pop
  @_Repeat
847 d2aff862 Guido Trotter
  def testConcurrentSetLockAdd(self):
848 d2aff862 Guido Trotter
    self.ls.acquire('one')
849 d2aff862 Guido Trotter
    # Another thread wants the whole SetLock
850 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(None, 0))
851 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(None, 1))
852 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
853 d2aff862 Guido Trotter
    self.assertRaises(AssertionError, self.ls.add, 'four')
854 d2aff862 Guido Trotter
    self.ls.release()
855 4607c978 Iustin Pop
    self._waitThreads()
856 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
857 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
858 d2aff862 Guido Trotter
    self.ls.acquire(None)
859 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(None, 0))
860 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(None, 1))
861 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
862 d2aff862 Guido Trotter
    self.ls.add('four')
863 d2aff862 Guido Trotter
    self.ls.add('five', acquired=1)
864 d2aff862 Guido Trotter
    self.ls.add('six', acquired=1, shared=1)
865 d2aff862 Guido Trotter
    self.assertEquals(self.ls._list_owned(),
866 d2aff862 Guido Trotter
      set(['one', 'two', 'three', 'five', 'six']))
867 d2aff862 Guido Trotter
    self.assertEquals(self.ls._is_owned(), True)
868 d2aff862 Guido Trotter
    self.assertEquals(self.ls._names(),
869 d2aff862 Guido Trotter
      set(['one', 'two', 'three', 'four', 'five', 'six']))
870 d2aff862 Guido Trotter
    self.ls.release()
871 4607c978 Iustin Pop
    self._waitThreads()
872 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
873 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
874 4607c978 Iustin Pop
    self._setUpLS()
875 d2aff862 Guido Trotter
876 4607c978 Iustin Pop
  @_Repeat
877 b2dabfd6 Guido Trotter
  def testEmptyLockSet(self):
878 b2dabfd6 Guido Trotter
    # get the set-lock
879 b2dabfd6 Guido Trotter
    self.assertEqual(self.ls.acquire(None), set(['one', 'two', 'three']))
880 b2dabfd6 Guido Trotter
    # now empty it...
881 b2dabfd6 Guido Trotter
    self.ls.remove(['one', 'two', 'three'])
882 b2dabfd6 Guido Trotter
    # and adds/locks by another thread still wait
883 4607c978 Iustin Pop
    self._addThread(target=self._doAddSet, args=(['nine']))
884 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(None, 1))
885 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(None, 0))
886 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
887 b2dabfd6 Guido Trotter
    self.ls.release()
888 4607c978 Iustin Pop
    self._waitThreads()
889 4607c978 Iustin Pop
    for _ in range(3):
890 4607c978 Iustin Pop
      self.assertEqual(self.done.get_nowait(), 'DONE')
891 b2dabfd6 Guido Trotter
    # empty it again...
892 b2dabfd6 Guido Trotter
    self.assertEqual(self.ls.remove(['nine']), ['nine'])
893 b2dabfd6 Guido Trotter
    # now share it...
894 b2dabfd6 Guido Trotter
    self.assertEqual(self.ls.acquire(None, shared=1), set())
895 b2dabfd6 Guido Trotter
    # other sharers can go, adds still wait
896 4607c978 Iustin Pop
    self._addThread(target=self._doLockSet, args=(None, 1))
897 4607c978 Iustin Pop
    self._waitThreads()
898 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
899 4607c978 Iustin Pop
    self._addThread(target=self._doAddSet, args=(['nine']))
900 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
901 b2dabfd6 Guido Trotter
    self.ls.release()
902 4607c978 Iustin Pop
    self._waitThreads()
903 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
904 4607c978 Iustin Pop
    self._setUpLS()
905 b2dabfd6 Guido Trotter
906 aaae9bc0 Guido Trotter
907 4607c978 Iustin Pop
class TestGanetiLockManager(_ThreadedTestCase):
908 7ee7c0c7 Guido Trotter
909 7ee7c0c7 Guido Trotter
  def setUp(self):
910 4607c978 Iustin Pop
    _ThreadedTestCase.setUp(self)
911 7ee7c0c7 Guido Trotter
    self.nodes=['n1', 'n2']
912 7ee7c0c7 Guido Trotter
    self.instances=['i1', 'i2', 'i3']
913 7ee7c0c7 Guido Trotter
    self.GL = locking.GanetiLockManager(nodes=self.nodes,
914 7ee7c0c7 Guido Trotter
                                        instances=self.instances)
915 7ee7c0c7 Guido Trotter
    self.done = Queue.Queue(0)
916 7ee7c0c7 Guido Trotter
917 7ee7c0c7 Guido Trotter
  def tearDown(self):
918 7ee7c0c7 Guido Trotter
    # Don't try this at home...
919 7ee7c0c7 Guido Trotter
    locking.GanetiLockManager._instance = None
920 7ee7c0c7 Guido Trotter
921 7ee7c0c7 Guido Trotter
  def testLockingConstants(self):
922 7ee7c0c7 Guido Trotter
    # The locking library internally cheats by assuming its constants have some
923 7ee7c0c7 Guido Trotter
    # relationships with each other. Check those hold true.
924 b10b9d74 Guido Trotter
    # This relationship is also used in the Processor to recursively acquire
925 b10b9d74 Guido Trotter
    # the right locks. Again, please don't break it.
926 7ee7c0c7 Guido Trotter
    for i in range(len(locking.LEVELS)):
927 7ee7c0c7 Guido Trotter
      self.assertEqual(i, locking.LEVELS[i])
928 7ee7c0c7 Guido Trotter
929 7ee7c0c7 Guido Trotter
  def testDoubleGLFails(self):
930 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, locking.GanetiLockManager)
931 7ee7c0c7 Guido Trotter
932 7ee7c0c7 Guido Trotter
  def testLockNames(self):
933 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
934 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set(self.nodes))
935 cdb08f44 Michael Hanselmann
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE),
936 cdb08f44 Michael Hanselmann
                     set(self.instances))
937 7ee7c0c7 Guido Trotter
938 7ee7c0c7 Guido Trotter
  def testInitAndResources(self):
939 7ee7c0c7 Guido Trotter
    locking.GanetiLockManager._instance = None
940 7ee7c0c7 Guido Trotter
    self.GL = locking.GanetiLockManager()
941 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
942 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set())
943 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE), set())
944 7ee7c0c7 Guido Trotter
945 7ee7c0c7 Guido Trotter
    locking.GanetiLockManager._instance = None
946 7ee7c0c7 Guido Trotter
    self.GL = locking.GanetiLockManager(nodes=self.nodes)
947 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
948 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set(self.nodes))
949 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE), set())
950 7ee7c0c7 Guido Trotter
951 7ee7c0c7 Guido Trotter
    locking.GanetiLockManager._instance = None
952 7ee7c0c7 Guido Trotter
    self.GL = locking.GanetiLockManager(instances=self.instances)
953 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
954 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set())
955 cdb08f44 Michael Hanselmann
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE),
956 cdb08f44 Michael Hanselmann
                     set(self.instances))
957 7ee7c0c7 Guido Trotter
958 7ee7c0c7 Guido Trotter
  def testAcquireRelease(self):
959 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
960 7ee7c0c7 Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_CLUSTER), set(['BGL']))
961 04e1bfaf Guido Trotter
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i1'])
962 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_NODE, ['n1', 'n2'], shared=1)
963 04e1bfaf Guido Trotter
    self.GL.release(locking.LEVEL_NODE, ['n2'])
964 7ee7c0c7 Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_NODE), set(['n1']))
965 7ee7c0c7 Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE), set(['i1']))
966 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_NODE)
967 04e1bfaf Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_NODE), set())
968 04e1bfaf Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE), set(['i1']))
969 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
970 7ee7c0c7 Guido Trotter
    self.assertRaises(errors.LockError, self.GL.acquire,
971 7ee7c0c7 Guido Trotter
                      locking.LEVEL_INSTANCE, ['i5'])
972 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i3'], shared=1)
973 7ee7c0c7 Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE), set(['i3']))
974 7ee7c0c7 Guido Trotter
975 90c942d1 Guido Trotter
  def testAcquireWholeSets(self):
976 90c942d1 Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
977 90c942d1 Guido Trotter
    self.assertEquals(self.GL.acquire(locking.LEVEL_INSTANCE, None),
978 90c942d1 Guido Trotter
                      set(self.instances))
979 90c942d1 Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE),
980 90c942d1 Guido Trotter
                      set(self.instances))
981 90c942d1 Guido Trotter
    self.assertEquals(self.GL.acquire(locking.LEVEL_NODE, None, shared=1),
982 90c942d1 Guido Trotter
                      set(self.nodes))
983 90c942d1 Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_NODE),
984 90c942d1 Guido Trotter
                      set(self.nodes))
985 90c942d1 Guido Trotter
    self.GL.release(locking.LEVEL_NODE)
986 d4f6a91c Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
987 d4f6a91c Guido Trotter
    self.GL.release(locking.LEVEL_CLUSTER)
988 d4f6a91c Guido Trotter
989 d4f6a91c Guido Trotter
  def testAcquireWholeAndPartial(self):
990 d4f6a91c Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
991 d4f6a91c Guido Trotter
    self.assertEquals(self.GL.acquire(locking.LEVEL_INSTANCE, None),
992 d4f6a91c Guido Trotter
                      set(self.instances))
993 d4f6a91c Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE),
994 d4f6a91c Guido Trotter
                      set(self.instances))
995 d4f6a91c Guido Trotter
    self.assertEquals(self.GL.acquire(locking.LEVEL_NODE, ['n2'], shared=1),
996 d4f6a91c Guido Trotter
                      set(['n2']))
997 d4f6a91c Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_NODE),
998 d4f6a91c Guido Trotter
                      set(['n2']))
999 d4f6a91c Guido Trotter
    self.GL.release(locking.LEVEL_NODE)
1000 90c942d1 Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
1001 90c942d1 Guido Trotter
    self.GL.release(locking.LEVEL_CLUSTER)
1002 90c942d1 Guido Trotter
1003 7ee7c0c7 Guido Trotter
  def testBGLDependency(self):
1004 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.acquire,
1005 7ee7c0c7 Guido Trotter
                      locking.LEVEL_NODE, ['n1', 'n2'])
1006 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.acquire,
1007 7ee7c0c7 Guido Trotter
                      locking.LEVEL_INSTANCE, ['i3'])
1008 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
1009 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_NODE, ['n1'])
1010 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.release,
1011 7ee7c0c7 Guido Trotter
                      locking.LEVEL_CLUSTER, ['BGL'])
1012 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.release,
1013 7ee7c0c7 Guido Trotter
                      locking.LEVEL_CLUSTER)
1014 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_NODE)
1015 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i1', 'i2'])
1016 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.release,
1017 7ee7c0c7 Guido Trotter
                      locking.LEVEL_CLUSTER, ['BGL'])
1018 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.release,
1019 7ee7c0c7 Guido Trotter
                      locking.LEVEL_CLUSTER)
1020 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
1021 7ee7c0c7 Guido Trotter
1022 7ee7c0c7 Guido Trotter
  def testWrongOrder(self):
1023 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
1024 04e1bfaf Guido Trotter
    self.GL.acquire(locking.LEVEL_NODE, ['n2'])
1025 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.acquire,
1026 7ee7c0c7 Guido Trotter
                      locking.LEVEL_NODE, ['n1'])
1027 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.acquire,
1028 7ee7c0c7 Guido Trotter
                      locking.LEVEL_INSTANCE, ['i2'])
1029 7ee7c0c7 Guido Trotter
1030 7ee7c0c7 Guido Trotter
  # Helper function to run as a thread that shared the BGL and then acquires
1031 7ee7c0c7 Guido Trotter
  # some locks at another level.
1032 7ee7c0c7 Guido Trotter
  def _doLock(self, level, names, shared):
1033 7ee7c0c7 Guido Trotter
    try:
1034 7ee7c0c7 Guido Trotter
      self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
1035 7ee7c0c7 Guido Trotter
      self.GL.acquire(level, names, shared=shared)
1036 7ee7c0c7 Guido Trotter
      self.done.put('DONE')
1037 7ee7c0c7 Guido Trotter
      self.GL.release(level)
1038 7ee7c0c7 Guido Trotter
      self.GL.release(locking.LEVEL_CLUSTER)
1039 7ee7c0c7 Guido Trotter
    except errors.LockError:
1040 7ee7c0c7 Guido Trotter
      self.done.put('ERR')
1041 7ee7c0c7 Guido Trotter
1042 4607c978 Iustin Pop
  @_Repeat
1043 7ee7c0c7 Guido Trotter
  def testConcurrency(self):
1044 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
1045 4607c978 Iustin Pop
    self._addThread(target=self._doLock,
1046 4607c978 Iustin Pop
                    args=(locking.LEVEL_INSTANCE, 'i1', 1))
1047 4607c978 Iustin Pop
    self._waitThreads()
1048 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1049 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i3'])
1050 4607c978 Iustin Pop
    self._addThread(target=self._doLock,
1051 4607c978 Iustin Pop
                    args=(locking.LEVEL_INSTANCE, 'i1', 1))
1052 4607c978 Iustin Pop
    self._waitThreads()
1053 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1054 4607c978 Iustin Pop
    self._addThread(target=self._doLock,
1055 4607c978 Iustin Pop
                    args=(locking.LEVEL_INSTANCE, 'i3', 1))
1056 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1057 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
1058 4607c978 Iustin Pop
    self._waitThreads()
1059 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1060 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i2'], shared=1)
1061 4607c978 Iustin Pop
    self._addThread(target=self._doLock,
1062 4607c978 Iustin Pop
                    args=(locking.LEVEL_INSTANCE, 'i2', 1))
1063 4607c978 Iustin Pop
    self._waitThreads()
1064 4607c978 Iustin Pop
    self.assertEqual(self.done.get_nowait(), 'DONE')
1065 4607c978 Iustin Pop
    self._addThread(target=self._doLock,
1066 4607c978 Iustin Pop
                    args=(locking.LEVEL_INSTANCE, 'i2', 0))
1067 4607c978 Iustin Pop
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1068 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
1069 4607c978 Iustin Pop
    self._waitThreads()
1070 7ee7c0c7 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
1071 4607c978 Iustin Pop
    self.GL.release(locking.LEVEL_CLUSTER, ['BGL'])
1072 7ee7c0c7 Guido Trotter
1073 7ee7c0c7 Guido Trotter
1074 162c1c1f Guido Trotter
if __name__ == '__main__':
1075 162c1c1f Guido Trotter
  unittest.main()
1076 162c1c1f Guido Trotter
  #suite = unittest.TestLoader().loadTestsFromTestCase(TestSharedLock)
1077 162c1c1f Guido Trotter
  #unittest.TextTestRunner(verbosity=2).run(suite)