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 testAcquireWithRepetitions(self):
407 self.assertEquals(self.ls.acquire(['two', 'two', 'three'], shared=1),
408 set(['two', 'two', 'three']))
409 self.ls.release(['two', 'two'])
410 self.assertEquals(self.ls._list_owned(), set(['three']))
412 def testEmptyAcquire(self):
413 # Acquire an empty list of locks...
414 self.assertEquals(self.ls.acquire([]), set())
415 self.assertEquals(self.ls._list_owned(), set())
416 # New locks can still be addded
417 self.assert_(self.ls.add('six'))
418 # "re-acquiring" is not an issue, since we had really acquired nothing
419 self.assertEquals(self.ls.acquire([], shared=1), set())
420 self.assertEquals(self.ls._list_owned(), set())
421 # We haven't really acquired anything, so we cannot release
422 self.assertRaises(AssertionError, self.ls.release)
424 def _doLockSet(self, set, shared):
426 self.ls.acquire(set, shared=shared)
427 self.done.put('DONE')
429 except errors.LockError:
432 def _doAddSet(self, set):
434 self.ls.add(set, acquired=1)
435 self.done.put('DONE')
437 except errors.LockError:
440 def _doRemoveSet(self, set):
441 self.done.put(self.ls.remove(set))
443 def testConcurrentSharedAcquire(self):
444 self.ls.acquire(['one', 'two'], shared=1)
445 Thread(target=self._doLockSet, args=(['one', 'two'], 1)).start()
446 self.assertEqual(self.done.get(True, 1), 'DONE')
447 Thread(target=self._doLockSet, args=(['one', 'two', 'three'], 1)).start()
448 self.assertEqual(self.done.get(True, 1), 'DONE')
449 Thread(target=self._doLockSet, args=('three', 1)).start()
450 self.assertEqual(self.done.get(True, 1), 'DONE')
451 Thread(target=self._doLockSet, args=(['one', 'two'], 0)).start()
452 Thread(target=self._doLockSet, args=(['two', 'three'], 0)).start()
453 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
455 self.assertEqual(self.done.get(True, 1), 'DONE')
456 self.assertEqual(self.done.get(True, 1), 'DONE')
458 def testConcurrentExclusiveAcquire(self):
459 self.ls.acquire(['one', 'two'])
460 Thread(target=self._doLockSet, args=('three', 1)).start()
461 self.assertEqual(self.done.get(True, 1), 'DONE')
462 Thread(target=self._doLockSet, args=('three', 0)).start()
463 self.assertEqual(self.done.get(True, 1), 'DONE')
464 Thread(target=self._doLockSet, args=(['one', 'two'], 0)).start()
465 Thread(target=self._doLockSet, args=(['one', 'two'], 1)).start()
466 Thread(target=self._doLockSet, args=('one', 0)).start()
467 Thread(target=self._doLockSet, args=('one', 1)).start()
468 Thread(target=self._doLockSet, args=(['two', 'three'], 0)).start()
469 Thread(target=self._doLockSet, args=(['two', 'three'], 1)).start()
470 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
472 self.assertEqual(self.done.get(True, 1), 'DONE')
473 self.assertEqual(self.done.get(True, 1), 'DONE')
474 self.assertEqual(self.done.get(True, 1), 'DONE')
475 self.assertEqual(self.done.get(True, 1), 'DONE')
476 self.assertEqual(self.done.get(True, 1), 'DONE')
477 self.assertEqual(self.done.get(True, 1), 'DONE')
479 def testConcurrentRemove(self):
481 self.ls.acquire(['one', 'two', 'four'])
482 Thread(target=self._doLockSet, args=(['one', 'four'], 0)).start()
483 Thread(target=self._doLockSet, args=(['one', 'four'], 1)).start()
484 Thread(target=self._doLockSet, args=(['one', 'two'], 0)).start()
485 Thread(target=self._doLockSet, args=(['one', 'two'], 1)).start()
486 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
487 self.ls.remove('one')
489 self.assertEqual(self.done.get(True, 1), 'ERR')
490 self.assertEqual(self.done.get(True, 1), 'ERR')
491 self.assertEqual(self.done.get(True, 1), 'ERR')
492 self.assertEqual(self.done.get(True, 1), 'ERR')
493 self.ls.add(['five', 'six'], acquired=1)
494 Thread(target=self._doLockSet, args=(['three', 'six'], 1)).start()
495 Thread(target=self._doLockSet, args=(['three', 'six'], 0)).start()
496 Thread(target=self._doLockSet, args=(['four', 'six'], 1)).start()
497 Thread(target=self._doLockSet, args=(['four', 'six'], 0)).start()
498 self.ls.remove('five')
500 self.assertEqual(self.done.get(True, 1), 'DONE')
501 self.assertEqual(self.done.get(True, 1), 'DONE')
502 self.assertEqual(self.done.get(True, 1), 'DONE')
503 self.assertEqual(self.done.get(True, 1), 'DONE')
504 self.ls.acquire(['three', 'four'])
505 Thread(target=self._doRemoveSet, args=(['four', 'six'], )).start()
506 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
507 self.ls.remove('four')
508 self.assertEqual(self.done.get(True, 1), ['six'])
509 Thread(target=self._doRemoveSet, args=(['two'])).start()
510 self.assertEqual(self.done.get(True, 1), ['two'])
513 def testConcurrentSharedSetLock(self):
514 # share the set-lock...
515 self.ls.acquire(None, shared=1)
516 # ...another thread can share it too
517 Thread(target=self._doLockSet, args=(None, 1)).start()
518 self.assertEqual(self.done.get(True, 1), 'DONE')
519 # ...or just share some elements
520 Thread(target=self._doLockSet, args=(['one', 'three'], 1)).start()
521 self.assertEqual(self.done.get(True, 1), 'DONE')
522 # ...but not add new ones or remove any
523 Thread(target=self._doAddSet, args=(['nine'])).start()
524 Thread(target=self._doRemoveSet, args=(['two'], )).start()
525 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
526 # this just releases the set-lock
528 self.assertEqual(self.done.get(True, 1), 'DONE')
529 # release the lock on the actual elements so remove() can proceed too
531 self.assertEqual(self.done.get(True, 1), ['two'])
533 def testConcurrentExclusiveSetLock(self):
534 # acquire the set-lock...
535 self.ls.acquire(None, shared=0)
536 # ...no one can do anything else
537 Thread(target=self._doLockSet, args=(None, 1)).start()
538 Thread(target=self._doLockSet, args=(None, 0)).start()
539 Thread(target=self._doLockSet, args=(['three'], 0)).start()
540 Thread(target=self._doLockSet, args=(['two'], 1)).start()
541 Thread(target=self._doAddSet, args=(['nine'])).start()
542 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
544 self.assertEqual(self.done.get(True, 1), 'DONE')
545 self.assertEqual(self.done.get(True, 1), 'DONE')
546 self.assertEqual(self.done.get(True, 1), 'DONE')
547 self.assertEqual(self.done.get(True, 1), 'DONE')
548 self.assertEqual(self.done.get(True, 1), 'DONE')
550 def testEmptyLockSet(self):
552 self.assertEqual(self.ls.acquire(None), set(['one', 'two', 'three']))
554 self.ls.remove(['one', 'two', 'three'])
555 # and adds/locks by another thread still wait
556 Thread(target=self._doAddSet, args=(['nine'])).start()
557 Thread(target=self._doLockSet, args=(None, 1)).start()
558 Thread(target=self._doLockSet, args=(None, 0)).start()
559 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
561 self.assertEqual(self.done.get(True, 1), 'DONE')
562 self.assertEqual(self.done.get(True, 1), 'DONE')
563 self.assertEqual(self.done.get(True, 1), 'DONE')
565 self.assertEqual(self.ls.remove(['nine']), ['nine'])
567 self.assertEqual(self.ls.acquire(None, shared=1), set())
568 # other sharers can go, adds still wait
569 Thread(target=self._doLockSet, args=(None, 1)).start()
570 self.assertEqual(self.done.get(True, 1), 'DONE')
571 Thread(target=self._doAddSet, args=(['nine'])).start()
572 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
574 self.assertEqual(self.done.get(True, 1), 'DONE')
577 class TestGanetiLockManager(unittest.TestCase):
580 self.nodes=['n1', 'n2']
581 self.instances=['i1', 'i2', 'i3']
582 self.GL = locking.GanetiLockManager(nodes=self.nodes,
583 instances=self.instances)
584 self.done = Queue.Queue(0)
587 # Don't try this at home...
588 locking.GanetiLockManager._instance = None
590 def testLockingConstants(self):
591 # The locking library internally cheats by assuming its constants have some
592 # relationships with each other. Check those hold true.
593 # This relationship is also used in the Processor to recursively acquire
594 # the right locks. Again, please don't break it.
595 for i in range(len(locking.LEVELS)):
596 self.assertEqual(i, locking.LEVELS[i])
598 def testDoubleGLFails(self):
599 self.assertRaises(AssertionError, locking.GanetiLockManager)
601 def testLockNames(self):
602 self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
603 self.assertEqual(self.GL._names(locking.LEVEL_NODE), set(self.nodes))
604 self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE),
607 def testInitAndResources(self):
608 locking.GanetiLockManager._instance = None
609 self.GL = locking.GanetiLockManager()
610 self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
611 self.assertEqual(self.GL._names(locking.LEVEL_NODE), set())
612 self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE), set())
614 locking.GanetiLockManager._instance = None
615 self.GL = locking.GanetiLockManager(nodes=self.nodes)
616 self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
617 self.assertEqual(self.GL._names(locking.LEVEL_NODE), set(self.nodes))
618 self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE), set())
620 locking.GanetiLockManager._instance = None
621 self.GL = locking.GanetiLockManager(instances=self.instances)
622 self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
623 self.assertEqual(self.GL._names(locking.LEVEL_NODE), set())
624 self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE),
627 def testAcquireRelease(self):
628 self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
629 self.assertEquals(self.GL._list_owned(locking.LEVEL_CLUSTER), set(['BGL']))
630 self.GL.acquire(locking.LEVEL_INSTANCE, ['i1'])
631 self.GL.acquire(locking.LEVEL_NODE, ['n1', 'n2'], shared=1)
632 self.GL.release(locking.LEVEL_NODE, ['n2'])
633 self.assertEquals(self.GL._list_owned(locking.LEVEL_NODE), set(['n1']))
634 self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE), set(['i1']))
635 self.GL.release(locking.LEVEL_NODE)
636 self.assertEquals(self.GL._list_owned(locking.LEVEL_NODE), set())
637 self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE), set(['i1']))
638 self.GL.release(locking.LEVEL_INSTANCE)
639 self.assertRaises(errors.LockError, self.GL.acquire,
640 locking.LEVEL_INSTANCE, ['i5'])
641 self.GL.acquire(locking.LEVEL_INSTANCE, ['i3'], shared=1)
642 self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE), set(['i3']))
644 def testAcquireWholeSets(self):
645 self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
646 self.assertEquals(self.GL.acquire(locking.LEVEL_INSTANCE, None),
648 self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE),
650 self.assertEquals(self.GL.acquire(locking.LEVEL_NODE, None, shared=1),
652 self.assertEquals(self.GL._list_owned(locking.LEVEL_NODE),
654 self.GL.release(locking.LEVEL_NODE)
655 self.GL.release(locking.LEVEL_INSTANCE)
656 self.GL.release(locking.LEVEL_CLUSTER)
658 def testAcquireWholeAndPartial(self):
659 self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
660 self.assertEquals(self.GL.acquire(locking.LEVEL_INSTANCE, None),
662 self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE),
664 self.assertEquals(self.GL.acquire(locking.LEVEL_NODE, ['n2'], shared=1),
666 self.assertEquals(self.GL._list_owned(locking.LEVEL_NODE),
668 self.GL.release(locking.LEVEL_NODE)
669 self.GL.release(locking.LEVEL_INSTANCE)
670 self.GL.release(locking.LEVEL_CLUSTER)
672 def testBGLDependency(self):
673 self.assertRaises(AssertionError, self.GL.acquire,
674 locking.LEVEL_NODE, ['n1', 'n2'])
675 self.assertRaises(AssertionError, self.GL.acquire,
676 locking.LEVEL_INSTANCE, ['i3'])
677 self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
678 self.GL.acquire(locking.LEVEL_NODE, ['n1'])
679 self.assertRaises(AssertionError, self.GL.release,
680 locking.LEVEL_CLUSTER, ['BGL'])
681 self.assertRaises(AssertionError, self.GL.release,
682 locking.LEVEL_CLUSTER)
683 self.GL.release(locking.LEVEL_NODE)
684 self.GL.acquire(locking.LEVEL_INSTANCE, ['i1', 'i2'])
685 self.assertRaises(AssertionError, self.GL.release,
686 locking.LEVEL_CLUSTER, ['BGL'])
687 self.assertRaises(AssertionError, self.GL.release,
688 locking.LEVEL_CLUSTER)
689 self.GL.release(locking.LEVEL_INSTANCE)
691 def testWrongOrder(self):
692 self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
693 self.GL.acquire(locking.LEVEL_NODE, ['n2'])
694 self.assertRaises(AssertionError, self.GL.acquire,
695 locking.LEVEL_NODE, ['n1'])
696 self.assertRaises(AssertionError, self.GL.acquire,
697 locking.LEVEL_INSTANCE, ['i2'])
699 # Helper function to run as a thread that shared the BGL and then acquires
700 # some locks at another level.
701 def _doLock(self, level, names, shared):
703 self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
704 self.GL.acquire(level, names, shared=shared)
705 self.done.put('DONE')
706 self.GL.release(level)
707 self.GL.release(locking.LEVEL_CLUSTER)
708 except errors.LockError:
711 def testConcurrency(self):
712 self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
713 Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i1', 1)).start()
714 self.assertEqual(self.done.get(True, 1), 'DONE')
715 self.GL.acquire(locking.LEVEL_INSTANCE, ['i3'])
716 Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i1', 1)).start()
717 self.assertEqual(self.done.get(True, 1), 'DONE')
718 Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i3', 1)).start()
719 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
720 self.GL.release(locking.LEVEL_INSTANCE)
721 self.assertEqual(self.done.get(True, 1), 'DONE')
722 self.GL.acquire(locking.LEVEL_INSTANCE, ['i2'], shared=1)
723 Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i2', 1)).start()
724 self.assertEqual(self.done.get(True, 1), 'DONE')
725 Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i2', 0)).start()
726 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
727 self.GL.release(locking.LEVEL_INSTANCE)
728 self.assertEqual(self.done.get(True, 1), 'DONE')
731 if __name__ == '__main__':
733 #suite = unittest.TestLoader().loadTestsFromTestCase(TestSharedLock)
734 #unittest.TextTestRunner(verbosity=2).run(suite)