4 # Copyright (C) 2006, 2007 Google Inc.
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful, but
12 # WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 # General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 """Script for unittesting the locking module"""
30 from ganeti import locking
31 from ganeti import errors
32 from threading import Thread
35 # This is used to test the ssynchronize decorator.
36 # Since it's passed as input to a decorator it must be declared as a global.
37 _decoratorlock = locking.SharedLock()
40 class TestSharedLock(unittest.TestCase):
41 """SharedLock tests"""
44 self.sl = locking.SharedLock()
45 # helper threads use the 'done' queue to tell the master they finished.
46 self.done = Queue.Queue(0)
48 def testSequenceAndOwnership(self):
49 self.assert_(not self.sl._is_owned())
50 self.sl.acquire(shared=1)
51 self.assert_(self.sl._is_owned())
52 self.assert_(self.sl._is_owned(shared=1))
53 self.assert_(not self.sl._is_owned(shared=0))
55 self.assert_(not self.sl._is_owned())
57 self.assert_(self.sl._is_owned())
58 self.assert_(not self.sl._is_owned(shared=1))
59 self.assert_(self.sl._is_owned(shared=0))
61 self.assert_(not self.sl._is_owned())
62 self.sl.acquire(shared=1)
63 self.assert_(self.sl._is_owned())
64 self.assert_(self.sl._is_owned(shared=1))
65 self.assert_(not self.sl._is_owned(shared=0))
67 self.assert_(not self.sl._is_owned())
69 def testBooleanValue(self):
70 # semaphores are supposed to return a true value on a successful acquire
71 self.assert_(self.sl.acquire(shared=1))
73 self.assert_(self.sl.acquire())
76 def testDoubleLockingStoE(self):
77 self.sl.acquire(shared=1)
78 self.assertRaises(AssertionError, self.sl.acquire)
80 def testDoubleLockingEtoS(self):
82 self.assertRaises(AssertionError, self.sl.acquire, shared=1)
84 def testDoubleLockingStoS(self):
85 self.sl.acquire(shared=1)
86 self.assertRaises(AssertionError, self.sl.acquire, shared=1)
88 def testDoubleLockingEtoE(self):
90 self.assertRaises(AssertionError, self.sl.acquire)
92 # helper functions: called in a separate thread they acquire the lock, send
93 # their identifier on the done queue, then release it.
94 def _doItSharer(self):
96 self.sl.acquire(shared=1)
99 except errors.LockError:
102 def _doItExclusive(self):
107 except errors.LockError:
110 def _doItDelete(self):
114 except errors.LockError:
117 def testSharersCanCoexist(self):
118 self.sl.acquire(shared=1)
119 Thread(target=self._doItSharer).start()
120 self.assert_(self.done.get(True, 1))
123 def testExclusiveBlocksExclusive(self):
125 Thread(target=self._doItExclusive).start()
126 # give it a bit of time to check that it's not actually doing anything
127 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
129 self.assert_(self.done.get(True, 1))
131 def testExclusiveBlocksDelete(self):
133 Thread(target=self._doItDelete).start()
134 # give it a bit of time to check that it's not actually doing anything
135 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
137 self.assert_(self.done.get(True, 1))
139 def testExclusiveBlocksSharer(self):
141 Thread(target=self._doItSharer).start()
143 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
145 self.assert_(self.done.get(True, 1))
147 def testSharerBlocksExclusive(self):
148 self.sl.acquire(shared=1)
149 Thread(target=self._doItExclusive).start()
151 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
153 self.assert_(self.done.get(True, 1))
155 def testSharerBlocksDelete(self):
156 self.sl.acquire(shared=1)
157 Thread(target=self._doItDelete).start()
159 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
161 self.assert_(self.done.get(True, 1))
163 def testWaitingExclusiveBlocksSharer(self):
164 self.sl.acquire(shared=1)
165 # the lock is acquired in shared mode...
166 Thread(target=self._doItExclusive).start()
167 # ...but now an exclusive is waiting...
169 Thread(target=self._doItSharer).start()
170 # ...so the sharer should be blocked as well
171 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
173 # The exclusive passed before
174 self.assertEqual(self.done.get(True, 1), 'EXC')
175 self.assertEqual(self.done.get(True, 1), 'SHR')
177 def testWaitingSharerBlocksExclusive(self):
179 # the lock is acquired in exclusive mode...
180 Thread(target=self._doItSharer).start()
181 # ...but now a sharer is waiting...
183 Thread(target=self._doItExclusive).start()
184 # ...the exclusive is waiting too...
185 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
187 # The sharer passed before
188 self.assertEqual(self.done.get(True, 1), 'SHR')
189 self.assertEqual(self.done.get(True, 1), 'EXC')
191 def testNoNonBlocking(self):
192 self.assertRaises(NotImplementedError, self.sl.acquire, blocking=0)
193 self.assertRaises(NotImplementedError, self.sl.delete, blocking=0)
195 self.sl.delete(blocking=0) # Fine, because the lock is already acquired
197 def testDelete(self):
199 self.assertRaises(errors.LockError, self.sl.acquire)
200 self.assertRaises(errors.LockError, self.sl.acquire, shared=1)
201 self.assertRaises(errors.LockError, self.sl.delete)
203 def testNoDeleteIfSharer(self):
204 self.sl.acquire(shared=1)
205 self.assertRaises(AssertionError, self.sl.delete)
207 def testDeletePendingSharersExclusiveDelete(self):
209 Thread(target=self._doItSharer).start()
210 Thread(target=self._doItSharer).start()
212 Thread(target=self._doItExclusive).start()
213 Thread(target=self._doItDelete).start()
216 # The two threads who were pending return both ERR
217 self.assertEqual(self.done.get(True, 1), 'ERR')
218 self.assertEqual(self.done.get(True, 1), 'ERR')
219 self.assertEqual(self.done.get(True, 1), 'ERR')
220 self.assertEqual(self.done.get(True, 1), 'ERR')
222 def testDeletePendingDeleteExclusiveSharers(self):
224 Thread(target=self._doItDelete).start()
225 Thread(target=self._doItExclusive).start()
227 Thread(target=self._doItSharer).start()
228 Thread(target=self._doItSharer).start()
231 # The two threads who were pending return both ERR
232 self.assertEqual(self.done.get(True, 1), 'ERR')
233 self.assertEqual(self.done.get(True, 1), 'ERR')
234 self.assertEqual(self.done.get(True, 1), 'ERR')
235 self.assertEqual(self.done.get(True, 1), 'ERR')
238 class TestSSynchronizedDecorator(unittest.TestCase):
239 """Shared Lock Synchronized decorator test"""
242 # helper threads use the 'done' queue to tell the master they finished.
243 self.done = Queue.Queue(0)
245 @locking.ssynchronized(_decoratorlock)
246 def _doItExclusive(self):
247 self.assert_(_decoratorlock._is_owned())
250 @locking.ssynchronized(_decoratorlock, shared=1)
251 def _doItSharer(self):
252 self.assert_(_decoratorlock._is_owned(shared=1))
255 def testDecoratedFunctions(self):
256 self._doItExclusive()
257 self.assert_(not _decoratorlock._is_owned())
259 self.assert_(not _decoratorlock._is_owned())
261 def testSharersCanCoexist(self):
262 _decoratorlock.acquire(shared=1)
263 Thread(target=self._doItSharer).start()
264 self.assert_(self.done.get(True, 1))
265 _decoratorlock.release()
267 def testExclusiveBlocksExclusive(self):
268 _decoratorlock.acquire()
269 Thread(target=self._doItExclusive).start()
270 # give it a bit of time to check that it's not actually doing anything
271 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
272 _decoratorlock.release()
273 self.assert_(self.done.get(True, 1))
275 def testExclusiveBlocksSharer(self):
276 _decoratorlock.acquire()
277 Thread(target=self._doItSharer).start()
279 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
280 _decoratorlock.release()
281 self.assert_(self.done.get(True, 1))
283 def testSharerBlocksExclusive(self):
284 _decoratorlock.acquire(shared=1)
285 Thread(target=self._doItExclusive).start()
287 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
288 _decoratorlock.release()
289 self.assert_(self.done.get(True, 1))
292 class TestLockSet(unittest.TestCase):
296 self.resources = ['one', 'two', 'three']
297 self.ls = locking.LockSet(members=self.resources)
298 # helper threads use the 'done' queue to tell the master they finished.
299 self.done = Queue.Queue(0)
301 def testResources(self):
302 self.assertEquals(self.ls._names(), set(self.resources))
303 newls = locking.LockSet()
304 self.assertEquals(newls._names(), set())
306 def testAcquireRelease(self):
307 self.assert_(self.ls.acquire('one'))
308 self.assertEquals(self.ls._list_owned(), set(['one']))
310 self.assertEquals(self.ls._list_owned(), set())
311 self.assertEquals(self.ls.acquire(['one']), set(['one']))
312 self.assertEquals(self.ls._list_owned(), set(['one']))
314 self.assertEquals(self.ls._list_owned(), set())
315 self.ls.acquire(['one', 'two', 'three'])
316 self.assertEquals(self.ls._list_owned(), set(['one', 'two', 'three']))
317 self.ls.release('one')
318 self.assertEquals(self.ls._list_owned(), set(['two', 'three']))
319 self.ls.release(['three'])
320 self.assertEquals(self.ls._list_owned(), set(['two']))
322 self.assertEquals(self.ls._list_owned(), set())
323 self.assertEquals(self.ls.acquire(['one', 'three']), set(['one', 'three']))
324 self.assertEquals(self.ls._list_owned(), set(['one', 'three']))
326 self.assertEquals(self.ls._list_owned(), set())
328 def testNoDoubleAcquire(self):
329 self.ls.acquire('one')
330 self.assertRaises(AssertionError, self.ls.acquire, 'one')
331 self.assertRaises(AssertionError, self.ls.acquire, ['two'])
332 self.assertRaises(AssertionError, self.ls.acquire, ['two', 'three'])
334 self.ls.acquire(['one', 'three'])
335 self.ls.release('one')
336 self.assertRaises(AssertionError, self.ls.acquire, ['two'])
337 self.ls.release('three')
339 def testNoWrongRelease(self):
340 self.assertRaises(AssertionError, self.ls.release)
341 self.ls.acquire('one')
342 self.assertRaises(AssertionError, self.ls.release, 'two')
344 def testAddRemove(self):
346 self.assertEquals(self.ls._list_owned(), set())
347 self.assert_('four' in self.ls._names())
348 self.ls.add(['five', 'six', 'seven'], acquired=1)
349 self.assert_('five' in self.ls._names())
350 self.assert_('six' in self.ls._names())
351 self.assert_('seven' in self.ls._names())
352 self.assertEquals(self.ls._list_owned(), set(['five', 'six', 'seven']))
353 self.assertEquals(self.ls.remove(['five', 'six']), ['five', 'six'])
354 self.assert_('five' not in self.ls._names())
355 self.assert_('six' not in self.ls._names())
356 self.assertEquals(self.ls._list_owned(), set(['seven']))
357 self.ls.add('eight', acquired=1, shared=1)
358 self.assert_('eight' in self.ls._names())
359 self.assertEquals(self.ls._list_owned(), set(['seven', 'eight']))
360 self.ls.remove('seven')
361 self.assert_('seven' not in self.ls._names())
362 self.assertEquals(self.ls._list_owned(), set(['eight']))
364 self.ls.remove(['two'])
365 self.assert_('two' not in self.ls._names())
366 self.ls.acquire('three')
367 self.assertEquals(self.ls.remove(['three']), ['three'])
368 self.assert_('three' not in self.ls._names())
369 self.assertEquals(self.ls.remove('three'), [])
370 self.assertEquals(self.ls.remove(['one', 'three', 'six']), ['one'])
371 self.assert_('one' not in self.ls._names())
373 def testRemoveNonBlocking(self):
374 self.assertRaises(NotImplementedError, self.ls.remove, 'one', blocking=0)
375 self.ls.acquire('one')
376 self.assertEquals(self.ls.remove('one', blocking=0), ['one'])
377 self.ls.acquire(['two', 'three'])
378 self.assertEquals(self.ls.remove(['two', 'three'], blocking=0),
381 def testNoDoubleAdd(self):
382 self.assertRaises(errors.LockError, self.ls.add, 'two')
384 self.assertRaises(errors.LockError, self.ls.add, 'four')
386 def testNoWrongRemoves(self):
387 self.ls.acquire(['one', 'three'], shared=1)
388 # Cannot remove 'two' while holding something which is not a superset
389 self.assertRaises(AssertionError, self.ls.remove, 'two')
390 # Cannot remove 'three' as we are sharing it
391 self.assertRaises(AssertionError, self.ls.remove, 'three')
393 def testAcquireSetLock(self):
394 # acquire the set-lock exclusively
395 self.assertEquals(self.ls.acquire(None), set(['one', 'two', 'three']))
396 # I can still add/remove elements...
397 self.assertEquals(self.ls.remove(['two', 'three']), ['two', 'three'])
398 self.assert_(self.ls.add('six'))
401 self.assertEquals(self.ls.acquire(None, shared=1), set(['one', 'six']))
402 # adding new elements is not possible
403 self.assertRaises(AssertionError, self.ls.add, 'five')
406 def testEmptyAcquire(self):
407 # Acquire an empty list of locks...
408 self.assertEquals(self.ls.acquire([]), set())
409 self.assertEquals(self.ls._list_owned(), set())
410 # New locks can still be addded
411 self.assert_(self.ls.add('six'))
412 # "re-acquiring" is not an issue, since we had really acquired nothing
413 self.assertEquals(self.ls.acquire([], shared=1), set())
414 self.assertEquals(self.ls._list_owned(), set())
415 # We haven't really acquired anything, so we cannot release
416 self.assertRaises(AssertionError, self.ls.release)
418 def _doLockSet(self, set, shared):
420 self.ls.acquire(set, shared=shared)
421 self.done.put('DONE')
423 except errors.LockError:
426 def _doAddSet(self, set):
428 self.ls.add(set, acquired=1)
429 self.done.put('DONE')
431 except errors.LockError:
434 def _doRemoveSet(self, set):
435 self.done.put(self.ls.remove(set))
437 def testConcurrentSharedAcquire(self):
438 self.ls.acquire(['one', 'two'], shared=1)
439 Thread(target=self._doLockSet, args=(['one', 'two'], 1)).start()
440 self.assertEqual(self.done.get(True, 1), 'DONE')
441 Thread(target=self._doLockSet, args=(['one', 'two', 'three'], 1)).start()
442 self.assertEqual(self.done.get(True, 1), 'DONE')
443 Thread(target=self._doLockSet, args=('three', 1)).start()
444 self.assertEqual(self.done.get(True, 1), 'DONE')
445 Thread(target=self._doLockSet, args=(['one', 'two'], 0)).start()
446 Thread(target=self._doLockSet, args=(['two', 'three'], 0)).start()
447 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
449 self.assertEqual(self.done.get(True, 1), 'DONE')
450 self.assertEqual(self.done.get(True, 1), 'DONE')
452 def testConcurrentExclusiveAcquire(self):
453 self.ls.acquire(['one', 'two'])
454 Thread(target=self._doLockSet, args=('three', 1)).start()
455 self.assertEqual(self.done.get(True, 1), 'DONE')
456 Thread(target=self._doLockSet, args=('three', 0)).start()
457 self.assertEqual(self.done.get(True, 1), 'DONE')
458 Thread(target=self._doLockSet, args=(['one', 'two'], 0)).start()
459 Thread(target=self._doLockSet, args=(['one', 'two'], 1)).start()
460 Thread(target=self._doLockSet, args=('one', 0)).start()
461 Thread(target=self._doLockSet, args=('one', 1)).start()
462 Thread(target=self._doLockSet, args=(['two', 'three'], 0)).start()
463 Thread(target=self._doLockSet, args=(['two', 'three'], 1)).start()
464 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
466 self.assertEqual(self.done.get(True, 1), 'DONE')
467 self.assertEqual(self.done.get(True, 1), 'DONE')
468 self.assertEqual(self.done.get(True, 1), 'DONE')
469 self.assertEqual(self.done.get(True, 1), 'DONE')
470 self.assertEqual(self.done.get(True, 1), 'DONE')
471 self.assertEqual(self.done.get(True, 1), 'DONE')
473 def testConcurrentRemove(self):
475 self.ls.acquire(['one', 'two', 'four'])
476 Thread(target=self._doLockSet, args=(['one', 'four'], 0)).start()
477 Thread(target=self._doLockSet, args=(['one', 'four'], 1)).start()
478 Thread(target=self._doLockSet, args=(['one', 'two'], 0)).start()
479 Thread(target=self._doLockSet, args=(['one', 'two'], 1)).start()
480 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
481 self.ls.remove('one')
483 self.assertEqual(self.done.get(True, 1), 'ERR')
484 self.assertEqual(self.done.get(True, 1), 'ERR')
485 self.assertEqual(self.done.get(True, 1), 'ERR')
486 self.assertEqual(self.done.get(True, 1), 'ERR')
487 self.ls.add(['five', 'six'], acquired=1)
488 Thread(target=self._doLockSet, args=(['three', 'six'], 1)).start()
489 Thread(target=self._doLockSet, args=(['three', 'six'], 0)).start()
490 Thread(target=self._doLockSet, args=(['four', 'six'], 1)).start()
491 Thread(target=self._doLockSet, args=(['four', 'six'], 0)).start()
492 self.ls.remove('five')
494 self.assertEqual(self.done.get(True, 1), 'DONE')
495 self.assertEqual(self.done.get(True, 1), 'DONE')
496 self.assertEqual(self.done.get(True, 1), 'DONE')
497 self.assertEqual(self.done.get(True, 1), 'DONE')
498 self.ls.acquire(['three', 'four'])
499 Thread(target=self._doRemoveSet, args=(['four', 'six'], )).start()
500 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
501 self.ls.remove('four')
502 self.assertEqual(self.done.get(True, 1), ['six'])
503 Thread(target=self._doRemoveSet, args=(['two'])).start()
504 self.assertEqual(self.done.get(True, 1), ['two'])
507 def testConcurrentSharedSetLock(self):
508 # share the set-lock...
509 self.ls.acquire(None, shared=1)
510 # ...another thread can share it too
511 Thread(target=self._doLockSet, args=(None, 1)).start()
512 self.assertEqual(self.done.get(True, 1), 'DONE')
513 # ...or just share some elements
514 Thread(target=self._doLockSet, args=(['one', 'three'], 1)).start()
515 self.assertEqual(self.done.get(True, 1), 'DONE')
516 # ...but not add new ones or remove any
517 Thread(target=self._doAddSet, args=(['nine'])).start()
518 Thread(target=self._doRemoveSet, args=(['two'], )).start()
519 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
520 # this just releases the set-lock
522 self.assertEqual(self.done.get(True, 1), 'DONE')
523 # release the lock on the actual elements so remove() can proceed too
525 self.assertEqual(self.done.get(True, 1), ['two'])
527 def testConcurrentExclusiveSetLock(self):
528 # acquire the set-lock...
529 self.ls.acquire(None, shared=0)
530 # ...no one can do anything else
531 Thread(target=self._doLockSet, args=(None, 1)).start()
532 Thread(target=self._doLockSet, args=(None, 0)).start()
533 Thread(target=self._doLockSet, args=(['three'], 0)).start()
534 Thread(target=self._doLockSet, args=(['two'], 1)).start()
535 Thread(target=self._doAddSet, args=(['nine'])).start()
536 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
538 self.assertEqual(self.done.get(True, 1), 'DONE')
539 self.assertEqual(self.done.get(True, 1), 'DONE')
540 self.assertEqual(self.done.get(True, 1), 'DONE')
541 self.assertEqual(self.done.get(True, 1), 'DONE')
542 self.assertEqual(self.done.get(True, 1), 'DONE')
544 def testEmptyLockSet(self):
546 self.assertEqual(self.ls.acquire(None), set(['one', 'two', 'three']))
548 self.ls.remove(['one', 'two', 'three'])
549 # and adds/locks by another thread still wait
550 Thread(target=self._doAddSet, args=(['nine'])).start()
551 Thread(target=self._doLockSet, args=(None, 1)).start()
552 Thread(target=self._doLockSet, args=(None, 0)).start()
553 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
555 self.assertEqual(self.done.get(True, 1), 'DONE')
556 self.assertEqual(self.done.get(True, 1), 'DONE')
557 self.assertEqual(self.done.get(True, 1), 'DONE')
559 self.assertEqual(self.ls.remove(['nine']), ['nine'])
561 self.assertEqual(self.ls.acquire(None, shared=1), set())
562 # other sharers can go, adds still wait
563 Thread(target=self._doLockSet, args=(None, 1)).start()
564 self.assertEqual(self.done.get(True, 1), 'DONE')
565 Thread(target=self._doAddSet, args=(['nine'])).start()
566 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
568 self.assertEqual(self.done.get(True, 1), 'DONE')
571 class TestGanetiLockManager(unittest.TestCase):
574 self.nodes=['n1', 'n2']
575 self.instances=['i1', 'i2', 'i3']
576 self.GL = locking.GanetiLockManager(nodes=self.nodes,
577 instances=self.instances)
578 self.done = Queue.Queue(0)
581 # Don't try this at home...
582 locking.GanetiLockManager._instance = None
584 def testLockingConstants(self):
585 # The locking library internally cheats by assuming its constants have some
586 # relationships with each other. Check those hold true.
587 # This relationship is also used in the Processor to recursively acquire
588 # the right locks. Again, please don't break it.
589 for i in range(len(locking.LEVELS)):
590 self.assertEqual(i, locking.LEVELS[i])
592 def testDoubleGLFails(self):
593 self.assertRaises(AssertionError, locking.GanetiLockManager)
595 def testLockNames(self):
596 self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
597 self.assertEqual(self.GL._names(locking.LEVEL_NODE), set(self.nodes))
598 self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE),
601 def testInitAndResources(self):
602 locking.GanetiLockManager._instance = None
603 self.GL = locking.GanetiLockManager()
604 self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
605 self.assertEqual(self.GL._names(locking.LEVEL_NODE), set())
606 self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE), set())
608 locking.GanetiLockManager._instance = None
609 self.GL = locking.GanetiLockManager(nodes=self.nodes)
610 self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
611 self.assertEqual(self.GL._names(locking.LEVEL_NODE), set(self.nodes))
612 self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE), set())
614 locking.GanetiLockManager._instance = None
615 self.GL = locking.GanetiLockManager(instances=self.instances)
616 self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
617 self.assertEqual(self.GL._names(locking.LEVEL_NODE), set())
618 self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE),
621 def testAcquireRelease(self):
622 self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
623 self.assertEquals(self.GL._list_owned(locking.LEVEL_CLUSTER), set(['BGL']))
624 self.GL.acquire(locking.LEVEL_NODE, ['n1', 'n2'], shared=1)
625 self.GL.release(locking.LEVEL_NODE)
626 self.GL.acquire(locking.LEVEL_NODE, ['n1'])
627 self.assertEquals(self.GL._list_owned(locking.LEVEL_NODE), set(['n1']))
628 self.GL.acquire(locking.LEVEL_INSTANCE, ['i1', 'i2'])
629 self.GL.release(locking.LEVEL_INSTANCE, ['i2'])
630 self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE), set(['i1']))
631 self.GL.release(locking.LEVEL_NODE)
632 self.GL.release(locking.LEVEL_INSTANCE)
633 self.assertRaises(errors.LockError, self.GL.acquire,
634 locking.LEVEL_INSTANCE, ['i5'])
635 self.GL.acquire(locking.LEVEL_INSTANCE, ['i3'], shared=1)
636 self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE), set(['i3']))
638 def testBGLDependency(self):
639 self.assertRaises(AssertionError, self.GL.acquire,
640 locking.LEVEL_NODE, ['n1', 'n2'])
641 self.assertRaises(AssertionError, self.GL.acquire,
642 locking.LEVEL_INSTANCE, ['i3'])
643 self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
644 self.GL.acquire(locking.LEVEL_NODE, ['n1'])
645 self.assertRaises(AssertionError, self.GL.release,
646 locking.LEVEL_CLUSTER, ['BGL'])
647 self.assertRaises(AssertionError, self.GL.release,
648 locking.LEVEL_CLUSTER)
649 self.GL.release(locking.LEVEL_NODE)
650 self.GL.acquire(locking.LEVEL_INSTANCE, ['i1', 'i2'])
651 self.assertRaises(AssertionError, self.GL.release,
652 locking.LEVEL_CLUSTER, ['BGL'])
653 self.assertRaises(AssertionError, self.GL.release,
654 locking.LEVEL_CLUSTER)
655 self.GL.release(locking.LEVEL_INSTANCE)
657 def testWrongOrder(self):
658 self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
659 self.GL.acquire(locking.LEVEL_INSTANCE, ['i3'])
660 self.assertRaises(AssertionError, self.GL.acquire,
661 locking.LEVEL_NODE, ['n1'])
662 self.assertRaises(AssertionError, self.GL.acquire,
663 locking.LEVEL_INSTANCE, ['i2'])
665 # Helper function to run as a thread that shared the BGL and then acquires
666 # some locks at another level.
667 def _doLock(self, level, names, shared):
669 self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
670 self.GL.acquire(level, names, shared=shared)
671 self.done.put('DONE')
672 self.GL.release(level)
673 self.GL.release(locking.LEVEL_CLUSTER)
674 except errors.LockError:
677 def testConcurrency(self):
678 self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
679 Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i1', 1)).start()
680 self.assertEqual(self.done.get(True, 1), 'DONE')
681 self.GL.acquire(locking.LEVEL_NODE, ['n1'])
682 self.GL.acquire(locking.LEVEL_INSTANCE, ['i3'])
683 Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i1', 1)).start()
684 self.assertEqual(self.done.get(True, 1), 'DONE')
685 Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i3', 1)).start()
686 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
687 self.GL.release(locking.LEVEL_INSTANCE)
688 self.assertEqual(self.done.get(True, 1), 'DONE')
689 self.GL.acquire(locking.LEVEL_INSTANCE, ['i2'], shared=1)
690 Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i2', 1)).start()
691 self.assertEqual(self.done.get(True, 1), 'DONE')
692 Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i2', 0)).start()
693 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
694 self.GL.release(locking.LEVEL_INSTANCE)
695 self.assertEqual(self.done.get(True, 1), 'DONE')
698 if __name__ == '__main__':
700 #suite = unittest.TestLoader().loadTestsFromTestCase(TestSharedLock)
701 #unittest.TextTestRunner(verbosity=2).run(suite)