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 _doLockSet(self, set, shared):
408 self.ls.acquire(set, shared=shared)
409 self.done.put('DONE')
411 except errors.LockError:
414 def _doAddSet(self, set):
416 self.ls.add(set, acquired=1)
417 self.done.put('DONE')
419 except errors.LockError:
422 def _doRemoveSet(self, set):
423 self.done.put(self.ls.remove(set))
425 def testConcurrentSharedAcquire(self):
426 self.ls.acquire(['one', 'two'], shared=1)
427 Thread(target=self._doLockSet, args=(['one', 'two'], 1)).start()
428 self.assertEqual(self.done.get(True, 1), 'DONE')
429 Thread(target=self._doLockSet, args=(['one', 'two', 'three'], 1)).start()
430 self.assertEqual(self.done.get(True, 1), 'DONE')
431 Thread(target=self._doLockSet, args=('three', 1)).start()
432 self.assertEqual(self.done.get(True, 1), 'DONE')
433 Thread(target=self._doLockSet, args=(['one', 'two'], 0)).start()
434 Thread(target=self._doLockSet, args=(['two', 'three'], 0)).start()
435 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
437 self.assertEqual(self.done.get(True, 1), 'DONE')
438 self.assertEqual(self.done.get(True, 1), 'DONE')
440 def testConcurrentExclusiveAcquire(self):
441 self.ls.acquire(['one', 'two'])
442 Thread(target=self._doLockSet, args=('three', 1)).start()
443 self.assertEqual(self.done.get(True, 1), 'DONE')
444 Thread(target=self._doLockSet, args=('three', 0)).start()
445 self.assertEqual(self.done.get(True, 1), 'DONE')
446 Thread(target=self._doLockSet, args=(['one', 'two'], 0)).start()
447 Thread(target=self._doLockSet, args=(['one', 'two'], 1)).start()
448 Thread(target=self._doLockSet, args=('one', 0)).start()
449 Thread(target=self._doLockSet, args=('one', 1)).start()
450 Thread(target=self._doLockSet, args=(['two', 'three'], 0)).start()
451 Thread(target=self._doLockSet, args=(['two', 'three'], 1)).start()
452 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
454 self.assertEqual(self.done.get(True, 1), 'DONE')
455 self.assertEqual(self.done.get(True, 1), 'DONE')
456 self.assertEqual(self.done.get(True, 1), 'DONE')
457 self.assertEqual(self.done.get(True, 1), 'DONE')
458 self.assertEqual(self.done.get(True, 1), 'DONE')
459 self.assertEqual(self.done.get(True, 1), 'DONE')
461 def testConcurrentRemove(self):
463 self.ls.acquire(['one', 'two', 'four'])
464 Thread(target=self._doLockSet, args=(['one', 'four'], 0)).start()
465 Thread(target=self._doLockSet, args=(['one', 'four'], 1)).start()
466 Thread(target=self._doLockSet, args=(['one', 'two'], 0)).start()
467 Thread(target=self._doLockSet, args=(['one', 'two'], 1)).start()
468 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
469 self.ls.remove('one')
471 self.assertEqual(self.done.get(True, 1), 'ERR')
472 self.assertEqual(self.done.get(True, 1), 'ERR')
473 self.assertEqual(self.done.get(True, 1), 'ERR')
474 self.assertEqual(self.done.get(True, 1), 'ERR')
475 self.ls.add(['five', 'six'], acquired=1)
476 Thread(target=self._doLockSet, args=(['three', 'six'], 1)).start()
477 Thread(target=self._doLockSet, args=(['three', 'six'], 0)).start()
478 Thread(target=self._doLockSet, args=(['four', 'six'], 1)).start()
479 Thread(target=self._doLockSet, args=(['four', 'six'], 0)).start()
480 self.ls.remove('five')
482 self.assertEqual(self.done.get(True, 1), 'DONE')
483 self.assertEqual(self.done.get(True, 1), 'DONE')
484 self.assertEqual(self.done.get(True, 1), 'DONE')
485 self.assertEqual(self.done.get(True, 1), 'DONE')
486 self.ls.acquire(['three', 'four'])
487 Thread(target=self._doRemoveSet, args=(['four', 'six'], )).start()
488 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
489 self.ls.remove('four')
490 self.assertEqual(self.done.get(True, 1), ['six'])
491 Thread(target=self._doRemoveSet, args=(['two'])).start()
492 self.assertEqual(self.done.get(True, 1), ['two'])
495 def testConcurrentSharedSetLock(self):
496 # share the set-lock...
497 self.ls.acquire(None, shared=1)
498 # ...another thread can share it too
499 Thread(target=self._doLockSet, args=(None, 1)).start()
500 self.assertEqual(self.done.get(True, 1), 'DONE')
501 # ...or just share some elements
502 Thread(target=self._doLockSet, args=(['one', 'three'], 1)).start()
503 self.assertEqual(self.done.get(True, 1), 'DONE')
504 # ...but not add new ones or remove any
505 Thread(target=self._doAddSet, args=(['nine'])).start()
506 Thread(target=self._doRemoveSet, args=(['two'], )).start()
507 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
508 # this just releases the set-lock
510 self.assertEqual(self.done.get(True, 1), 'DONE')
511 # release the lock on the actual elements so remove() can proceed too
513 self.assertEqual(self.done.get(True, 1), ['two'])
515 def testConcurrentExclusiveSetLock(self):
516 # acquire the set-lock...
517 self.ls.acquire(None, shared=0)
518 # ...no one can do anything else
519 Thread(target=self._doLockSet, args=(None, 1)).start()
520 Thread(target=self._doLockSet, args=(None, 0)).start()
521 Thread(target=self._doLockSet, args=(['three'], 0)).start()
522 Thread(target=self._doLockSet, args=(['two'], 1)).start()
523 Thread(target=self._doAddSet, args=(['nine'])).start()
524 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
526 self.assertEqual(self.done.get(True, 1), 'DONE')
527 self.assertEqual(self.done.get(True, 1), 'DONE')
528 self.assertEqual(self.done.get(True, 1), 'DONE')
529 self.assertEqual(self.done.get(True, 1), 'DONE')
530 self.assertEqual(self.done.get(True, 1), 'DONE')
532 def testEmptyLockSet(self):
534 self.assertEqual(self.ls.acquire(None), set(['one', 'two', 'three']))
536 self.ls.remove(['one', 'two', 'three'])
537 # and adds/locks by another thread still wait
538 Thread(target=self._doAddSet, args=(['nine'])).start()
539 Thread(target=self._doLockSet, args=(None, 1)).start()
540 Thread(target=self._doLockSet, args=(None, 0)).start()
541 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
543 self.assertEqual(self.done.get(True, 1), 'DONE')
544 self.assertEqual(self.done.get(True, 1), 'DONE')
545 self.assertEqual(self.done.get(True, 1), 'DONE')
547 self.assertEqual(self.ls.remove(['nine']), ['nine'])
549 self.assertEqual(self.ls.acquire(None, shared=1), set())
550 # other sharers can go, adds still wait
551 Thread(target=self._doLockSet, args=(None, 1)).start()
552 self.assertEqual(self.done.get(True, 1), 'DONE')
553 Thread(target=self._doAddSet, args=(['nine'])).start()
554 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
556 self.assertEqual(self.done.get(True, 1), 'DONE')
559 class TestGanetiLockManager(unittest.TestCase):
562 self.nodes=['n1', 'n2']
563 self.instances=['i1', 'i2', 'i3']
564 self.GL = locking.GanetiLockManager(nodes=self.nodes,
565 instances=self.instances)
566 self.done = Queue.Queue(0)
569 # Don't try this at home...
570 locking.GanetiLockManager._instance = None
572 def testLockingConstants(self):
573 # The locking library internally cheats by assuming its constants have some
574 # relationships with each other. Check those hold true.
575 for i in range(len(locking.LEVELS)):
576 self.assertEqual(i, locking.LEVELS[i])
578 def testDoubleGLFails(self):
579 self.assertRaises(AssertionError, locking.GanetiLockManager)
581 def testLockNames(self):
582 self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
583 self.assertEqual(self.GL._names(locking.LEVEL_NODE), set(self.nodes))
584 self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE),
587 def testInitAndResources(self):
588 locking.GanetiLockManager._instance = None
589 self.GL = locking.GanetiLockManager()
590 self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
591 self.assertEqual(self.GL._names(locking.LEVEL_NODE), set())
592 self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE), set())
594 locking.GanetiLockManager._instance = None
595 self.GL = locking.GanetiLockManager(nodes=self.nodes)
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), set())
600 locking.GanetiLockManager._instance = None
601 self.GL = locking.GanetiLockManager(instances=self.instances)
602 self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
603 self.assertEqual(self.GL._names(locking.LEVEL_NODE), set())
604 self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE),
607 def testAcquireRelease(self):
608 self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
609 self.assertEquals(self.GL._list_owned(locking.LEVEL_CLUSTER), set(['BGL']))
610 self.GL.acquire(locking.LEVEL_NODE, ['n1', 'n2'], shared=1)
611 self.GL.release(locking.LEVEL_NODE)
612 self.GL.acquire(locking.LEVEL_NODE, ['n1'])
613 self.assertEquals(self.GL._list_owned(locking.LEVEL_NODE), set(['n1']))
614 self.GL.acquire(locking.LEVEL_INSTANCE, ['i1', 'i2'])
615 self.GL.release(locking.LEVEL_INSTANCE, ['i2'])
616 self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE), set(['i1']))
617 self.GL.release(locking.LEVEL_NODE)
618 self.GL.release(locking.LEVEL_INSTANCE)
619 self.assertRaises(errors.LockError, self.GL.acquire,
620 locking.LEVEL_INSTANCE, ['i5'])
621 self.GL.acquire(locking.LEVEL_INSTANCE, ['i3'], shared=1)
622 self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE), set(['i3']))
624 def testBGLDependency(self):
625 self.assertRaises(AssertionError, self.GL.acquire,
626 locking.LEVEL_NODE, ['n1', 'n2'])
627 self.assertRaises(AssertionError, self.GL.acquire,
628 locking.LEVEL_INSTANCE, ['i3'])
629 self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
630 self.GL.acquire(locking.LEVEL_NODE, ['n1'])
631 self.assertRaises(AssertionError, self.GL.release,
632 locking.LEVEL_CLUSTER, ['BGL'])
633 self.assertRaises(AssertionError, self.GL.release,
634 locking.LEVEL_CLUSTER)
635 self.GL.release(locking.LEVEL_NODE)
636 self.GL.acquire(locking.LEVEL_INSTANCE, ['i1', 'i2'])
637 self.assertRaises(AssertionError, self.GL.release,
638 locking.LEVEL_CLUSTER, ['BGL'])
639 self.assertRaises(AssertionError, self.GL.release,
640 locking.LEVEL_CLUSTER)
641 self.GL.release(locking.LEVEL_INSTANCE)
643 def testWrongOrder(self):
644 self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
645 self.GL.acquire(locking.LEVEL_INSTANCE, ['i3'])
646 self.assertRaises(AssertionError, self.GL.acquire,
647 locking.LEVEL_NODE, ['n1'])
648 self.assertRaises(AssertionError, self.GL.acquire,
649 locking.LEVEL_INSTANCE, ['i2'])
651 # Helper function to run as a thread that shared the BGL and then acquires
652 # some locks at another level.
653 def _doLock(self, level, names, shared):
655 self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
656 self.GL.acquire(level, names, shared=shared)
657 self.done.put('DONE')
658 self.GL.release(level)
659 self.GL.release(locking.LEVEL_CLUSTER)
660 except errors.LockError:
663 def testConcurrency(self):
664 self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
665 Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i1', 1)).start()
666 self.assertEqual(self.done.get(True, 1), 'DONE')
667 self.GL.acquire(locking.LEVEL_NODE, ['n1'])
668 self.GL.acquire(locking.LEVEL_INSTANCE, ['i3'])
669 Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i1', 1)).start()
670 self.assertEqual(self.done.get(True, 1), 'DONE')
671 Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i3', 1)).start()
672 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
673 self.GL.release(locking.LEVEL_INSTANCE)
674 self.assertEqual(self.done.get(True, 1), 'DONE')
675 self.GL.acquire(locking.LEVEL_INSTANCE, ['i2'], shared=1)
676 Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i2', 1)).start()
677 self.assertEqual(self.done.get(True, 1), 'DONE')
678 Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i2', 0)).start()
679 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
680 self.GL.release(locking.LEVEL_INSTANCE)
681 self.assertEqual(self.done.get(True, 1), 'DONE')
684 if __name__ == '__main__':
686 #suite = unittest.TestLoader().loadTestsFromTestCase(TestSharedLock)
687 #unittest.TextTestRunner(verbosity=2).run(suite)