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()
39 #: List for looping tests
43 """Decorator for executing a function many times"""
44 def wrapper(*args, **kwargs):
49 class _ThreadedTestCase(unittest.TestCase):
50 """Test class that supports adding/waiting on threads"""
52 unittest.TestCase.setUp(self)
55 def _addThread(self, *args, **kwargs):
56 """Create and remember a new thread"""
57 t = Thread(*args, **kwargs)
58 self.threads.append(t)
62 def _waitThreads(self):
63 """Wait for all our threads to finish"""
64 for t in self.threads:
66 self.failIf(t.isAlive())
70 class TestSharedLock(_ThreadedTestCase):
71 """SharedLock tests"""
74 _ThreadedTestCase.setUp(self)
75 self.sl = locking.SharedLock()
76 # helper threads use the 'done' queue to tell the master they finished.
77 self.done = Queue.Queue(0)
79 def testSequenceAndOwnership(self):
80 self.assert_(not self.sl._is_owned())
81 self.sl.acquire(shared=1)
82 self.assert_(self.sl._is_owned())
83 self.assert_(self.sl._is_owned(shared=1))
84 self.assert_(not self.sl._is_owned(shared=0))
86 self.assert_(not self.sl._is_owned())
88 self.assert_(self.sl._is_owned())
89 self.assert_(not self.sl._is_owned(shared=1))
90 self.assert_(self.sl._is_owned(shared=0))
92 self.assert_(not self.sl._is_owned())
93 self.sl.acquire(shared=1)
94 self.assert_(self.sl._is_owned())
95 self.assert_(self.sl._is_owned(shared=1))
96 self.assert_(not self.sl._is_owned(shared=0))
98 self.assert_(not self.sl._is_owned())
100 def testBooleanValue(self):
101 # semaphores are supposed to return a true value on a successful acquire
102 self.assert_(self.sl.acquire(shared=1))
104 self.assert_(self.sl.acquire())
107 def testDoubleLockingStoE(self):
108 self.sl.acquire(shared=1)
109 self.assertRaises(AssertionError, self.sl.acquire)
111 def testDoubleLockingEtoS(self):
113 self.assertRaises(AssertionError, self.sl.acquire, shared=1)
115 def testDoubleLockingStoS(self):
116 self.sl.acquire(shared=1)
117 self.assertRaises(AssertionError, self.sl.acquire, shared=1)
119 def testDoubleLockingEtoE(self):
121 self.assertRaises(AssertionError, self.sl.acquire)
123 # helper functions: called in a separate thread they acquire the lock, send
124 # their identifier on the done queue, then release it.
125 def _doItSharer(self):
127 self.sl.acquire(shared=1)
130 except errors.LockError:
133 def _doItExclusive(self):
138 except errors.LockError:
141 def _doItDelete(self):
145 except errors.LockError:
148 def testSharersCanCoexist(self):
149 self.sl.acquire(shared=1)
150 Thread(target=self._doItSharer).start()
151 self.assert_(self.done.get(True, 1))
155 def testExclusiveBlocksExclusive(self):
157 self._addThread(target=self._doItExclusive)
158 self.assertRaises(Queue.Empty, self.done.get_nowait)
161 self.failUnlessEqual(self.done.get_nowait(), 'EXC')
164 def testExclusiveBlocksDelete(self):
166 self._addThread(target=self._doItDelete)
167 self.assertRaises(Queue.Empty, self.done.get_nowait)
170 self.failUnlessEqual(self.done.get_nowait(), 'DEL')
171 self.sl = locking.SharedLock()
174 def testExclusiveBlocksSharer(self):
176 self._addThread(target=self._doItSharer)
177 self.assertRaises(Queue.Empty, self.done.get_nowait)
180 self.failUnlessEqual(self.done.get_nowait(), 'SHR')
183 def testSharerBlocksExclusive(self):
184 self.sl.acquire(shared=1)
185 self._addThread(target=self._doItExclusive)
186 self.assertRaises(Queue.Empty, self.done.get_nowait)
189 self.failUnlessEqual(self.done.get_nowait(), 'EXC')
192 def testSharerBlocksDelete(self):
193 self.sl.acquire(shared=1)
194 self._addThread(target=self._doItDelete)
195 self.assertRaises(Queue.Empty, self.done.get_nowait)
198 self.failUnlessEqual(self.done.get_nowait(), 'DEL')
199 self.sl = locking.SharedLock()
202 def testWaitingExclusiveBlocksSharer(self):
203 self.sl.acquire(shared=1)
204 # the lock is acquired in shared mode...
205 self._addThread(target=self._doItExclusive)
206 # ...but now an exclusive is waiting...
207 self._addThread(target=self._doItSharer)
208 # ...so the sharer should be blocked as well
209 self.assertRaises(Queue.Empty, self.done.get_nowait)
212 # The exclusive passed before
213 self.failUnlessEqual(self.done.get_nowait(), 'EXC')
214 self.failUnlessEqual(self.done.get_nowait(), 'SHR')
217 def testWaitingSharerBlocksExclusive(self):
219 # the lock is acquired in exclusive mode...
220 self._addThread(target=self._doItSharer)
221 # ...but now a sharer is waiting...
222 self._addThread(target=self._doItExclusive)
223 # ...the exclusive is waiting too...
224 self.assertRaises(Queue.Empty, self.done.get_nowait)
227 # The sharer passed before
228 self.assertEqual(self.done.get_nowait(), 'SHR')
229 self.assertEqual(self.done.get_nowait(), 'EXC')
231 def testNoNonBlocking(self):
232 self.assertRaises(NotImplementedError, self.sl.acquire, blocking=0)
233 self.assertRaises(NotImplementedError, self.sl.delete, blocking=0)
235 self.sl.delete(blocking=0) # Fine, because the lock is already acquired
237 def testDelete(self):
239 self.assertRaises(errors.LockError, self.sl.acquire)
240 self.assertRaises(errors.LockError, self.sl.acquire, shared=1)
241 self.assertRaises(errors.LockError, self.sl.delete)
243 def testNoDeleteIfSharer(self):
244 self.sl.acquire(shared=1)
245 self.assertRaises(AssertionError, self.sl.delete)
248 def testDeletePendingSharersExclusiveDelete(self):
250 self._addThread(target=self._doItSharer)
251 self._addThread(target=self._doItSharer)
252 self._addThread(target=self._doItExclusive)
253 self._addThread(target=self._doItDelete)
256 # The threads who were pending return ERR
258 self.assertEqual(self.done.get_nowait(), 'ERR')
259 self.sl = locking.SharedLock()
262 def testDeletePendingDeleteExclusiveSharers(self):
264 self._addThread(target=self._doItDelete)
265 self._addThread(target=self._doItExclusive)
266 self._addThread(target=self._doItSharer)
267 self._addThread(target=self._doItSharer)
270 # The two threads who were pending return both ERR
271 self.assertEqual(self.done.get_nowait(), 'ERR')
272 self.assertEqual(self.done.get_nowait(), 'ERR')
273 self.assertEqual(self.done.get_nowait(), 'ERR')
274 self.assertEqual(self.done.get_nowait(), 'ERR')
275 self.sl = locking.SharedLock()
278 class TestSSynchronizedDecorator(_ThreadedTestCase):
279 """Shared Lock Synchronized decorator test"""
282 _ThreadedTestCase.setUp(self)
283 # helper threads use the 'done' queue to tell the master they finished.
284 self.done = Queue.Queue(0)
286 @locking.ssynchronized(_decoratorlock)
287 def _doItExclusive(self):
288 self.assert_(_decoratorlock._is_owned())
291 @locking.ssynchronized(_decoratorlock, shared=1)
292 def _doItSharer(self):
293 self.assert_(_decoratorlock._is_owned(shared=1))
296 def testDecoratedFunctions(self):
297 self._doItExclusive()
298 self.assert_(not _decoratorlock._is_owned())
300 self.assert_(not _decoratorlock._is_owned())
302 def testSharersCanCoexist(self):
303 _decoratorlock.acquire(shared=1)
304 Thread(target=self._doItSharer).start()
305 self.assert_(self.done.get(True, 1))
306 _decoratorlock.release()
309 def testExclusiveBlocksExclusive(self):
310 _decoratorlock.acquire()
311 self._addThread(target=self._doItExclusive)
312 # give it a bit of time to check that it's not actually doing anything
313 self.assertRaises(Queue.Empty, self.done.get_nowait)
314 _decoratorlock.release()
316 self.failUnlessEqual(self.done.get_nowait(), 'EXC')
319 def testExclusiveBlocksSharer(self):
320 _decoratorlock.acquire()
321 self._addThread(target=self._doItSharer)
322 self.assertRaises(Queue.Empty, self.done.get_nowait)
323 _decoratorlock.release()
325 self.failUnlessEqual(self.done.get_nowait(), 'SHR')
328 def testSharerBlocksExclusive(self):
329 _decoratorlock.acquire(shared=1)
330 self._addThread(target=self._doItExclusive)
331 self.assertRaises(Queue.Empty, self.done.get_nowait)
332 _decoratorlock.release()
334 self.failUnlessEqual(self.done.get_nowait(), 'EXC')
337 class TestLockSet(_ThreadedTestCase):
341 _ThreadedTestCase.setUp(self)
343 # helper threads use the 'done' queue to tell the master they finished.
344 self.done = Queue.Queue(0)
347 """Helper to (re)initialize the lock set"""
348 self.resources = ['one', 'two', 'three']
349 self.ls = locking.LockSet(members=self.resources)
352 def testResources(self):
353 self.assertEquals(self.ls._names(), set(self.resources))
354 newls = locking.LockSet()
355 self.assertEquals(newls._names(), set())
357 def testAcquireRelease(self):
358 self.assert_(self.ls.acquire('one'))
359 self.assertEquals(self.ls._list_owned(), set(['one']))
361 self.assertEquals(self.ls._list_owned(), set())
362 self.assertEquals(self.ls.acquire(['one']), set(['one']))
363 self.assertEquals(self.ls._list_owned(), set(['one']))
365 self.assertEquals(self.ls._list_owned(), set())
366 self.ls.acquire(['one', 'two', 'three'])
367 self.assertEquals(self.ls._list_owned(), set(['one', 'two', 'three']))
368 self.ls.release('one')
369 self.assertEquals(self.ls._list_owned(), set(['two', 'three']))
370 self.ls.release(['three'])
371 self.assertEquals(self.ls._list_owned(), set(['two']))
373 self.assertEquals(self.ls._list_owned(), set())
374 self.assertEquals(self.ls.acquire(['one', 'three']), set(['one', 'three']))
375 self.assertEquals(self.ls._list_owned(), set(['one', 'three']))
377 self.assertEquals(self.ls._list_owned(), set())
379 def testNoDoubleAcquire(self):
380 self.ls.acquire('one')
381 self.assertRaises(AssertionError, self.ls.acquire, 'one')
382 self.assertRaises(AssertionError, self.ls.acquire, ['two'])
383 self.assertRaises(AssertionError, self.ls.acquire, ['two', 'three'])
385 self.ls.acquire(['one', 'three'])
386 self.ls.release('one')
387 self.assertRaises(AssertionError, self.ls.acquire, ['two'])
388 self.ls.release('three')
390 def testNoWrongRelease(self):
391 self.assertRaises(AssertionError, self.ls.release)
392 self.ls.acquire('one')
393 self.assertRaises(AssertionError, self.ls.release, 'two')
395 def testAddRemove(self):
397 self.assertEquals(self.ls._list_owned(), set())
398 self.assert_('four' in self.ls._names())
399 self.ls.add(['five', 'six', 'seven'], acquired=1)
400 self.assert_('five' in self.ls._names())
401 self.assert_('six' in self.ls._names())
402 self.assert_('seven' in self.ls._names())
403 self.assertEquals(self.ls._list_owned(), set(['five', 'six', 'seven']))
404 self.assertEquals(self.ls.remove(['five', 'six']), ['five', 'six'])
405 self.assert_('five' not in self.ls._names())
406 self.assert_('six' not in self.ls._names())
407 self.assertEquals(self.ls._list_owned(), set(['seven']))
408 self.assertRaises(AssertionError, self.ls.add, 'eight', acquired=1)
409 self.ls.remove('seven')
410 self.assert_('seven' not in self.ls._names())
411 self.assertEquals(self.ls._list_owned(), set([]))
412 self.ls.acquire(None, shared=1)
413 self.assertRaises(AssertionError, self.ls.add, 'eight')
415 self.ls.acquire(None)
416 self.ls.add('eight', acquired=1)
417 self.assert_('eight' in self.ls._names())
418 self.assert_('eight' in self.ls._list_owned())
420 self.assert_('nine' in self.ls._names())
421 self.assert_('nine' not in self.ls._list_owned())
423 self.ls.remove(['two'])
424 self.assert_('two' not in self.ls._names())
425 self.ls.acquire('three')
426 self.assertEquals(self.ls.remove(['three']), ['three'])
427 self.assert_('three' not in self.ls._names())
428 self.assertEquals(self.ls.remove('three'), [])
429 self.assertEquals(self.ls.remove(['one', 'three', 'six']), ['one'])
430 self.assert_('one' not in self.ls._names())
432 def testRemoveNonBlocking(self):
433 self.assertRaises(NotImplementedError, self.ls.remove, 'one', blocking=0)
434 self.ls.acquire('one')
435 self.assertEquals(self.ls.remove('one', blocking=0), ['one'])
436 self.ls.acquire(['two', 'three'])
437 self.assertEquals(self.ls.remove(['two', 'three'], blocking=0),
440 def testNoDoubleAdd(self):
441 self.assertRaises(errors.LockError, self.ls.add, 'two')
443 self.assertRaises(errors.LockError, self.ls.add, 'four')
445 def testNoWrongRemoves(self):
446 self.ls.acquire(['one', 'three'], shared=1)
447 # Cannot remove 'two' while holding something which is not a superset
448 self.assertRaises(AssertionError, self.ls.remove, 'two')
449 # Cannot remove 'three' as we are sharing it
450 self.assertRaises(AssertionError, self.ls.remove, 'three')
452 def testAcquireSetLock(self):
453 # acquire the set-lock exclusively
454 self.assertEquals(self.ls.acquire(None), set(['one', 'two', 'three']))
455 self.assertEquals(self.ls._list_owned(), set(['one', 'two', 'three']))
456 self.assertEquals(self.ls._is_owned(), True)
457 self.assertEquals(self.ls._names(), set(['one', 'two', 'three']))
458 # I can still add/remove elements...
459 self.assertEquals(self.ls.remove(['two', 'three']), ['two', 'three'])
460 self.assert_(self.ls.add('six'))
463 self.assertEquals(self.ls.acquire(None, shared=1), set(['one', 'six']))
464 # adding new elements is not possible
465 self.assertRaises(AssertionError, self.ls.add, 'five')
468 def testAcquireWithRepetitions(self):
469 self.assertEquals(self.ls.acquire(['two', 'two', 'three'], shared=1),
470 set(['two', 'two', 'three']))
471 self.ls.release(['two', 'two'])
472 self.assertEquals(self.ls._list_owned(), set(['three']))
474 def testEmptyAcquire(self):
475 # Acquire an empty list of locks...
476 self.assertEquals(self.ls.acquire([]), set())
477 self.assertEquals(self.ls._list_owned(), set())
478 # New locks can still be addded
479 self.assert_(self.ls.add('six'))
480 # "re-acquiring" is not an issue, since we had really acquired nothing
481 self.assertEquals(self.ls.acquire([], shared=1), set())
482 self.assertEquals(self.ls._list_owned(), set())
483 # We haven't really acquired anything, so we cannot release
484 self.assertRaises(AssertionError, self.ls.release)
486 def _doLockSet(self, set, shared):
488 self.ls.acquire(set, shared=shared)
489 self.done.put('DONE')
491 except errors.LockError:
494 def _doAddSet(self, set):
496 self.ls.add(set, acquired=1)
497 self.done.put('DONE')
499 except errors.LockError:
502 def _doRemoveSet(self, set):
503 self.done.put(self.ls.remove(set))
506 def testConcurrentSharedAcquire(self):
507 self.ls.acquire(['one', 'two'], shared=1)
508 self._addThread(target=self._doLockSet, args=(['one', 'two'], 1))
510 self.assertEqual(self.done.get_nowait(), 'DONE')
511 self._addThread(target=self._doLockSet, args=(['one', 'two', 'three'], 1))
513 self.assertEqual(self.done.get_nowait(), 'DONE')
514 self._addThread(target=self._doLockSet, args=('three', 1))
516 self.assertEqual(self.done.get_nowait(), 'DONE')
517 self._addThread(target=self._doLockSet, args=(['one', 'two'], 0))
518 self._addThread(target=self._doLockSet, args=(['two', 'three'], 0))
519 self.assertRaises(Queue.Empty, self.done.get_nowait)
522 self.assertEqual(self.done.get_nowait(), 'DONE')
523 self.assertEqual(self.done.get_nowait(), 'DONE')
526 def testConcurrentExclusiveAcquire(self):
527 self.ls.acquire(['one', 'two'])
528 self._addThread(target=self._doLockSet, args=('three', 1))
530 self.assertEqual(self.done.get_nowait(), 'DONE')
531 self._addThread(target=self._doLockSet, args=('three', 0))
533 self.assertEqual(self.done.get_nowait(), 'DONE')
534 self._addThread(target=self._doLockSet, args=(['one', 'two'], 0))
535 self._addThread(target=self._doLockSet, args=(['one', 'two'], 1))
536 self._addThread(target=self._doLockSet, args=('one', 0))
537 self._addThread(target=self._doLockSet, args=('one', 1))
538 self._addThread(target=self._doLockSet, args=(['two', 'three'], 0))
539 self._addThread(target=self._doLockSet, args=(['two', 'three'], 1))
540 self.assertRaises(Queue.Empty, self.done.get_nowait)
544 self.failUnlessEqual(self.done.get_nowait(), 'DONE')
547 def testConcurrentRemove(self):
549 self.ls.acquire(['one', 'two', 'four'])
550 self._addThread(target=self._doLockSet, args=(['one', 'four'], 0))
551 self._addThread(target=self._doLockSet, args=(['one', 'four'], 1))
552 self._addThread(target=self._doLockSet, args=(['one', 'two'], 0))
553 self._addThread(target=self._doLockSet, args=(['one', 'two'], 1))
554 self.assertRaises(Queue.Empty, self.done.get_nowait)
555 self.ls.remove('one')
559 self.failUnlessEqual(self.done.get_nowait(), 'ERR')
560 self.ls.add(['five', 'six'], acquired=1)
561 self._addThread(target=self._doLockSet, args=(['three', 'six'], 1))
562 self._addThread(target=self._doLockSet, args=(['three', 'six'], 0))
563 self._addThread(target=self._doLockSet, args=(['four', 'six'], 1))
564 self._addThread(target=self._doLockSet, args=(['four', 'six'], 0))
565 self.ls.remove('five')
569 self.failUnlessEqual(self.done.get_nowait(), 'DONE')
570 self.ls.acquire(['three', 'four'])
571 self._addThread(target=self._doRemoveSet, args=(['four', 'six'], ))
572 self.assertRaises(Queue.Empty, self.done.get_nowait)
573 self.ls.remove('four')
575 self.assertEqual(self.done.get_nowait(), ['six'])
576 self._addThread(target=self._doRemoveSet, args=(['two']))
578 self.assertEqual(self.done.get_nowait(), ['two'])
584 def testConcurrentSharedSetLock(self):
585 # share the set-lock...
586 self.ls.acquire(None, shared=1)
587 # ...another thread can share it too
588 self._addThread(target=self._doLockSet, args=(None, 1))
590 self.assertEqual(self.done.get_nowait(), 'DONE')
591 # ...or just share some elements
592 self._addThread(target=self._doLockSet, args=(['one', 'three'], 1))
594 self.assertEqual(self.done.get_nowait(), 'DONE')
595 # ...but not add new ones or remove any
596 t = self._addThread(target=self._doAddSet, args=(['nine']))
597 self._addThread(target=self._doRemoveSet, args=(['two'], ))
598 self.assertRaises(Queue.Empty, self.done.get_nowait)
599 # this just releases the set-lock
602 self.assertEqual(self.done.get_nowait(), 'DONE')
603 # release the lock on the actual elements so remove() can proceed too
606 self.failUnlessEqual(self.done.get_nowait(), ['two'])
611 def testConcurrentExclusiveSetLock(self):
612 # acquire the set-lock...
613 self.ls.acquire(None, shared=0)
614 # ...no one can do anything else
615 self._addThread(target=self._doLockSet, args=(None, 1))
616 self._addThread(target=self._doLockSet, args=(None, 0))
617 self._addThread(target=self._doLockSet, args=(['three'], 0))
618 self._addThread(target=self._doLockSet, args=(['two'], 1))
619 self._addThread(target=self._doAddSet, args=(['nine']))
620 self.assertRaises(Queue.Empty, self.done.get_nowait)
624 self.assertEqual(self.done.get(True, 1), 'DONE')
629 def testConcurrentSetLockAdd(self):
630 self.ls.acquire('one')
631 # Another thread wants the whole SetLock
632 self._addThread(target=self._doLockSet, args=(None, 0))
633 self._addThread(target=self._doLockSet, args=(None, 1))
634 self.assertRaises(Queue.Empty, self.done.get_nowait)
635 self.assertRaises(AssertionError, self.ls.add, 'four')
638 self.assertEqual(self.done.get_nowait(), 'DONE')
639 self.assertEqual(self.done.get_nowait(), 'DONE')
640 self.ls.acquire(None)
641 self._addThread(target=self._doLockSet, args=(None, 0))
642 self._addThread(target=self._doLockSet, args=(None, 1))
643 self.assertRaises(Queue.Empty, self.done.get_nowait)
645 self.ls.add('five', acquired=1)
646 self.ls.add('six', acquired=1, shared=1)
647 self.assertEquals(self.ls._list_owned(),
648 set(['one', 'two', 'three', 'five', 'six']))
649 self.assertEquals(self.ls._is_owned(), True)
650 self.assertEquals(self.ls._names(),
651 set(['one', 'two', 'three', 'four', 'five', 'six']))
654 self.assertEqual(self.done.get_nowait(), 'DONE')
655 self.assertEqual(self.done.get_nowait(), 'DONE')
659 def testEmptyLockSet(self):
661 self.assertEqual(self.ls.acquire(None), set(['one', 'two', 'three']))
663 self.ls.remove(['one', 'two', 'three'])
664 # and adds/locks by another thread still wait
665 self._addThread(target=self._doAddSet, args=(['nine']))
666 self._addThread(target=self._doLockSet, args=(None, 1))
667 self._addThread(target=self._doLockSet, args=(None, 0))
668 self.assertRaises(Queue.Empty, self.done.get_nowait)
672 self.assertEqual(self.done.get_nowait(), 'DONE')
674 self.assertEqual(self.ls.remove(['nine']), ['nine'])
676 self.assertEqual(self.ls.acquire(None, shared=1), set())
677 # other sharers can go, adds still wait
678 self._addThread(target=self._doLockSet, args=(None, 1))
680 self.assertEqual(self.done.get_nowait(), 'DONE')
681 self._addThread(target=self._doAddSet, args=(['nine']))
682 self.assertRaises(Queue.Empty, self.done.get_nowait)
685 self.assertEqual(self.done.get_nowait(), 'DONE')
689 class TestGanetiLockManager(_ThreadedTestCase):
692 _ThreadedTestCase.setUp(self)
693 self.nodes=['n1', 'n2']
694 self.instances=['i1', 'i2', 'i3']
695 self.GL = locking.GanetiLockManager(nodes=self.nodes,
696 instances=self.instances)
697 self.done = Queue.Queue(0)
700 # Don't try this at home...
701 locking.GanetiLockManager._instance = None
703 def testLockingConstants(self):
704 # The locking library internally cheats by assuming its constants have some
705 # relationships with each other. Check those hold true.
706 # This relationship is also used in the Processor to recursively acquire
707 # the right locks. Again, please don't break it.
708 for i in range(len(locking.LEVELS)):
709 self.assertEqual(i, locking.LEVELS[i])
711 def testDoubleGLFails(self):
712 self.assertRaises(AssertionError, locking.GanetiLockManager)
714 def testLockNames(self):
715 self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
716 self.assertEqual(self.GL._names(locking.LEVEL_NODE), set(self.nodes))
717 self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE),
720 def testInitAndResources(self):
721 locking.GanetiLockManager._instance = None
722 self.GL = locking.GanetiLockManager()
723 self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
724 self.assertEqual(self.GL._names(locking.LEVEL_NODE), set())
725 self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE), set())
727 locking.GanetiLockManager._instance = None
728 self.GL = locking.GanetiLockManager(nodes=self.nodes)
729 self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
730 self.assertEqual(self.GL._names(locking.LEVEL_NODE), set(self.nodes))
731 self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE), set())
733 locking.GanetiLockManager._instance = None
734 self.GL = locking.GanetiLockManager(instances=self.instances)
735 self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
736 self.assertEqual(self.GL._names(locking.LEVEL_NODE), set())
737 self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE),
740 def testAcquireRelease(self):
741 self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
742 self.assertEquals(self.GL._list_owned(locking.LEVEL_CLUSTER), set(['BGL']))
743 self.GL.acquire(locking.LEVEL_INSTANCE, ['i1'])
744 self.GL.acquire(locking.LEVEL_NODE, ['n1', 'n2'], shared=1)
745 self.GL.release(locking.LEVEL_NODE, ['n2'])
746 self.assertEquals(self.GL._list_owned(locking.LEVEL_NODE), set(['n1']))
747 self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE), set(['i1']))
748 self.GL.release(locking.LEVEL_NODE)
749 self.assertEquals(self.GL._list_owned(locking.LEVEL_NODE), set())
750 self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE), set(['i1']))
751 self.GL.release(locking.LEVEL_INSTANCE)
752 self.assertRaises(errors.LockError, self.GL.acquire,
753 locking.LEVEL_INSTANCE, ['i5'])
754 self.GL.acquire(locking.LEVEL_INSTANCE, ['i3'], shared=1)
755 self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE), set(['i3']))
757 def testAcquireWholeSets(self):
758 self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
759 self.assertEquals(self.GL.acquire(locking.LEVEL_INSTANCE, None),
761 self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE),
763 self.assertEquals(self.GL.acquire(locking.LEVEL_NODE, None, shared=1),
765 self.assertEquals(self.GL._list_owned(locking.LEVEL_NODE),
767 self.GL.release(locking.LEVEL_NODE)
768 self.GL.release(locking.LEVEL_INSTANCE)
769 self.GL.release(locking.LEVEL_CLUSTER)
771 def testAcquireWholeAndPartial(self):
772 self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
773 self.assertEquals(self.GL.acquire(locking.LEVEL_INSTANCE, None),
775 self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE),
777 self.assertEquals(self.GL.acquire(locking.LEVEL_NODE, ['n2'], shared=1),
779 self.assertEquals(self.GL._list_owned(locking.LEVEL_NODE),
781 self.GL.release(locking.LEVEL_NODE)
782 self.GL.release(locking.LEVEL_INSTANCE)
783 self.GL.release(locking.LEVEL_CLUSTER)
785 def testBGLDependency(self):
786 self.assertRaises(AssertionError, self.GL.acquire,
787 locking.LEVEL_NODE, ['n1', 'n2'])
788 self.assertRaises(AssertionError, self.GL.acquire,
789 locking.LEVEL_INSTANCE, ['i3'])
790 self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
791 self.GL.acquire(locking.LEVEL_NODE, ['n1'])
792 self.assertRaises(AssertionError, self.GL.release,
793 locking.LEVEL_CLUSTER, ['BGL'])
794 self.assertRaises(AssertionError, self.GL.release,
795 locking.LEVEL_CLUSTER)
796 self.GL.release(locking.LEVEL_NODE)
797 self.GL.acquire(locking.LEVEL_INSTANCE, ['i1', 'i2'])
798 self.assertRaises(AssertionError, self.GL.release,
799 locking.LEVEL_CLUSTER, ['BGL'])
800 self.assertRaises(AssertionError, self.GL.release,
801 locking.LEVEL_CLUSTER)
802 self.GL.release(locking.LEVEL_INSTANCE)
804 def testWrongOrder(self):
805 self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
806 self.GL.acquire(locking.LEVEL_NODE, ['n2'])
807 self.assertRaises(AssertionError, self.GL.acquire,
808 locking.LEVEL_NODE, ['n1'])
809 self.assertRaises(AssertionError, self.GL.acquire,
810 locking.LEVEL_INSTANCE, ['i2'])
812 # Helper function to run as a thread that shared the BGL and then acquires
813 # some locks at another level.
814 def _doLock(self, level, names, shared):
816 self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
817 self.GL.acquire(level, names, shared=shared)
818 self.done.put('DONE')
819 self.GL.release(level)
820 self.GL.release(locking.LEVEL_CLUSTER)
821 except errors.LockError:
825 def testConcurrency(self):
826 self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
827 self._addThread(target=self._doLock,
828 args=(locking.LEVEL_INSTANCE, 'i1', 1))
830 self.assertEqual(self.done.get_nowait(), 'DONE')
831 self.GL.acquire(locking.LEVEL_INSTANCE, ['i3'])
832 self._addThread(target=self._doLock,
833 args=(locking.LEVEL_INSTANCE, 'i1', 1))
835 self.assertEqual(self.done.get_nowait(), 'DONE')
836 self._addThread(target=self._doLock,
837 args=(locking.LEVEL_INSTANCE, 'i3', 1))
838 self.assertRaises(Queue.Empty, self.done.get_nowait)
839 self.GL.release(locking.LEVEL_INSTANCE)
841 self.assertEqual(self.done.get_nowait(), 'DONE')
842 self.GL.acquire(locking.LEVEL_INSTANCE, ['i2'], shared=1)
843 self._addThread(target=self._doLock,
844 args=(locking.LEVEL_INSTANCE, 'i2', 1))
846 self.assertEqual(self.done.get_nowait(), 'DONE')
847 self._addThread(target=self._doLock,
848 args=(locking.LEVEL_INSTANCE, 'i2', 0))
849 self.assertRaises(Queue.Empty, self.done.get_nowait)
850 self.GL.release(locking.LEVEL_INSTANCE)
852 self.assertEqual(self.done.get(True, 1), 'DONE')
853 self.GL.release(locking.LEVEL_CLUSTER, ['BGL'])
856 if __name__ == '__main__':
858 #suite = unittest.TestLoader().loadTestsFromTestCase(TestSharedLock)
859 #unittest.TextTestRunner(verbosity=2).run(suite)