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.assertRaises(AssertionError, self.ls.add, 'eight', acquired=1)
358 self.ls.remove('seven')
359 self.assert_('seven' not in self.ls._names())
360 self.assertEquals(self.ls._list_owned(), set([]))
361 self.ls.acquire(None, shared=1)
362 self.assertRaises(AssertionError, self.ls.add, 'eight')
364 self.ls.acquire(None)
365 self.ls.add('eight', acquired=1)
366 self.assert_('eight' in self.ls._names())
367 self.assert_('eight' in self.ls._list_owned())
369 self.assert_('nine' in self.ls._names())
370 self.assert_('nine' not in self.ls._list_owned())
372 self.ls.remove(['two'])
373 self.assert_('two' not in self.ls._names())
374 self.ls.acquire('three')
375 self.assertEquals(self.ls.remove(['three']), ['three'])
376 self.assert_('three' not in self.ls._names())
377 self.assertEquals(self.ls.remove('three'), [])
378 self.assertEquals(self.ls.remove(['one', 'three', 'six']), ['one'])
379 self.assert_('one' not in self.ls._names())
381 def testRemoveNonBlocking(self):
382 self.assertRaises(NotImplementedError, self.ls.remove, 'one', blocking=0)
383 self.ls.acquire('one')
384 self.assertEquals(self.ls.remove('one', blocking=0), ['one'])
385 self.ls.acquire(['two', 'three'])
386 self.assertEquals(self.ls.remove(['two', 'three'], blocking=0),
389 def testNoDoubleAdd(self):
390 self.assertRaises(errors.LockError, self.ls.add, 'two')
392 self.assertRaises(errors.LockError, self.ls.add, 'four')
394 def testNoWrongRemoves(self):
395 self.ls.acquire(['one', 'three'], shared=1)
396 # Cannot remove 'two' while holding something which is not a superset
397 self.assertRaises(AssertionError, self.ls.remove, 'two')
398 # Cannot remove 'three' as we are sharing it
399 self.assertRaises(AssertionError, self.ls.remove, 'three')
401 def testAcquireSetLock(self):
402 # acquire the set-lock exclusively
403 self.assertEquals(self.ls.acquire(None), set(['one', 'two', 'three']))
404 self.assertEquals(self.ls._list_owned(), set(['one', 'two', 'three']))
405 self.assertEquals(self.ls._is_owned(), True)
406 self.assertEquals(self.ls._names(), set(['one', 'two', 'three']))
407 # I can still add/remove elements...
408 self.assertEquals(self.ls.remove(['two', 'three']), ['two', 'three'])
409 self.assert_(self.ls.add('six'))
412 self.assertEquals(self.ls.acquire(None, shared=1), set(['one', 'six']))
413 # adding new elements is not possible
414 self.assertRaises(AssertionError, self.ls.add, 'five')
417 def testAcquireWithRepetitions(self):
418 self.assertEquals(self.ls.acquire(['two', 'two', 'three'], shared=1),
419 set(['two', 'two', 'three']))
420 self.ls.release(['two', 'two'])
421 self.assertEquals(self.ls._list_owned(), set(['three']))
423 def testEmptyAcquire(self):
424 # Acquire an empty list of locks...
425 self.assertEquals(self.ls.acquire([]), set())
426 self.assertEquals(self.ls._list_owned(), set())
427 # New locks can still be addded
428 self.assert_(self.ls.add('six'))
429 # "re-acquiring" is not an issue, since we had really acquired nothing
430 self.assertEquals(self.ls.acquire([], shared=1), set())
431 self.assertEquals(self.ls._list_owned(), set())
432 # We haven't really acquired anything, so we cannot release
433 self.assertRaises(AssertionError, self.ls.release)
435 def _doLockSet(self, set, shared):
437 self.ls.acquire(set, shared=shared)
438 self.done.put('DONE')
440 except errors.LockError:
443 def _doAddSet(self, set):
445 self.ls.add(set, acquired=1)
446 self.done.put('DONE')
448 except errors.LockError:
451 def _doRemoveSet(self, set):
452 self.done.put(self.ls.remove(set))
454 def testConcurrentSharedAcquire(self):
455 self.ls.acquire(['one', 'two'], shared=1)
456 Thread(target=self._doLockSet, args=(['one', 'two'], 1)).start()
457 self.assertEqual(self.done.get(True, 1), 'DONE')
458 Thread(target=self._doLockSet, args=(['one', 'two', 'three'], 1)).start()
459 self.assertEqual(self.done.get(True, 1), 'DONE')
460 Thread(target=self._doLockSet, args=('three', 1)).start()
461 self.assertEqual(self.done.get(True, 1), 'DONE')
462 Thread(target=self._doLockSet, args=(['one', 'two'], 0)).start()
463 Thread(target=self._doLockSet, args=(['two', 'three'], 0)).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')
469 def testConcurrentExclusiveAcquire(self):
470 self.ls.acquire(['one', 'two'])
471 Thread(target=self._doLockSet, args=('three', 1)).start()
472 self.assertEqual(self.done.get(True, 1), 'DONE')
473 Thread(target=self._doLockSet, args=('three', 0)).start()
474 self.assertEqual(self.done.get(True, 1), 'DONE')
475 Thread(target=self._doLockSet, args=(['one', 'two'], 0)).start()
476 Thread(target=self._doLockSet, args=(['one', 'two'], 1)).start()
477 Thread(target=self._doLockSet, args=('one', 0)).start()
478 Thread(target=self._doLockSet, args=('one', 1)).start()
479 Thread(target=self._doLockSet, args=(['two', 'three'], 0)).start()
480 Thread(target=self._doLockSet, args=(['two', 'three'], 1)).start()
481 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
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.assertEqual(self.done.get(True, 1), 'DONE')
487 self.assertEqual(self.done.get(True, 1), 'DONE')
488 self.assertEqual(self.done.get(True, 1), 'DONE')
490 def testConcurrentRemove(self):
492 self.ls.acquire(['one', 'two', 'four'])
493 Thread(target=self._doLockSet, args=(['one', 'four'], 0)).start()
494 Thread(target=self._doLockSet, args=(['one', 'four'], 1)).start()
495 Thread(target=self._doLockSet, args=(['one', 'two'], 0)).start()
496 Thread(target=self._doLockSet, args=(['one', 'two'], 1)).start()
497 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
498 self.ls.remove('one')
500 self.assertEqual(self.done.get(True, 1), 'ERR')
501 self.assertEqual(self.done.get(True, 1), 'ERR')
502 self.assertEqual(self.done.get(True, 1), 'ERR')
503 self.assertEqual(self.done.get(True, 1), 'ERR')
504 self.ls.add(['five', 'six'], acquired=1)
505 Thread(target=self._doLockSet, args=(['three', 'six'], 1)).start()
506 Thread(target=self._doLockSet, args=(['three', 'six'], 0)).start()
507 Thread(target=self._doLockSet, args=(['four', 'six'], 1)).start()
508 Thread(target=self._doLockSet, args=(['four', 'six'], 0)).start()
509 self.ls.remove('five')
511 self.assertEqual(self.done.get(True, 1), 'DONE')
512 self.assertEqual(self.done.get(True, 1), 'DONE')
513 self.assertEqual(self.done.get(True, 1), 'DONE')
514 self.assertEqual(self.done.get(True, 1), 'DONE')
515 self.ls.acquire(['three', 'four'])
516 Thread(target=self._doRemoveSet, args=(['four', 'six'], )).start()
517 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
518 self.ls.remove('four')
519 self.assertEqual(self.done.get(True, 1), ['six'])
520 Thread(target=self._doRemoveSet, args=(['two'])).start()
521 self.assertEqual(self.done.get(True, 1), ['two'])
524 def testConcurrentSharedSetLock(self):
525 # share the set-lock...
526 self.ls.acquire(None, shared=1)
527 # ...another thread can share it too
528 Thread(target=self._doLockSet, args=(None, 1)).start()
529 self.assertEqual(self.done.get(True, 1), 'DONE')
530 # ...or just share some elements
531 Thread(target=self._doLockSet, args=(['one', 'three'], 1)).start()
532 self.assertEqual(self.done.get(True, 1), 'DONE')
533 # ...but not add new ones or remove any
534 Thread(target=self._doAddSet, args=(['nine'])).start()
535 Thread(target=self._doRemoveSet, args=(['two'], )).start()
536 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
537 # this just releases the set-lock
539 self.assertEqual(self.done.get(True, 1), 'DONE')
540 # release the lock on the actual elements so remove() can proceed too
542 self.assertEqual(self.done.get(True, 1), ['two'])
544 def testConcurrentExclusiveSetLock(self):
545 # acquire the set-lock...
546 self.ls.acquire(None, shared=0)
547 # ...no one can do anything else
548 Thread(target=self._doLockSet, args=(None, 1)).start()
549 Thread(target=self._doLockSet, args=(None, 0)).start()
550 Thread(target=self._doLockSet, args=(['three'], 0)).start()
551 Thread(target=self._doLockSet, args=(['two'], 1)).start()
552 Thread(target=self._doAddSet, args=(['nine'])).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')
558 self.assertEqual(self.done.get(True, 1), 'DONE')
559 self.assertEqual(self.done.get(True, 1), 'DONE')
561 def testConcurrentSetLockAdd(self):
562 self.ls.acquire('one')
563 # Another thread wants the whole SetLock
564 Thread(target=self._doLockSet, args=(None, 0)).start()
565 Thread(target=self._doLockSet, args=(None, 1)).start()
566 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
567 self.assertRaises(AssertionError, self.ls.add, 'four')
569 self.assertEqual(self.done.get(True, 1), 'DONE')
570 self.assertEqual(self.done.get(True, 1), 'DONE')
571 self.ls.acquire(None)
572 Thread(target=self._doLockSet, args=(None, 0)).start()
573 Thread(target=self._doLockSet, args=(None, 1)).start()
574 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
576 self.ls.add('five', acquired=1)
577 self.ls.add('six', acquired=1, shared=1)
578 self.assertEquals(self.ls._list_owned(),
579 set(['one', 'two', 'three', 'five', 'six']))
580 self.assertEquals(self.ls._is_owned(), True)
581 self.assertEquals(self.ls._names(),
582 set(['one', 'two', 'three', 'four', 'five', 'six']))
584 self.assertEqual(self.done.get(True, 1), 'DONE')
585 self.assertEqual(self.done.get(True, 1), 'DONE')
587 def testEmptyLockSet(self):
589 self.assertEqual(self.ls.acquire(None), set(['one', 'two', 'three']))
591 self.ls.remove(['one', 'two', 'three'])
592 # and adds/locks by another thread still wait
593 Thread(target=self._doAddSet, args=(['nine'])).start()
594 Thread(target=self._doLockSet, args=(None, 1)).start()
595 Thread(target=self._doLockSet, args=(None, 0)).start()
596 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
598 self.assertEqual(self.done.get(True, 1), 'DONE')
599 self.assertEqual(self.done.get(True, 1), 'DONE')
600 self.assertEqual(self.done.get(True, 1), 'DONE')
602 self.assertEqual(self.ls.remove(['nine']), ['nine'])
604 self.assertEqual(self.ls.acquire(None, shared=1), set())
605 # other sharers can go, adds still wait
606 Thread(target=self._doLockSet, args=(None, 1)).start()
607 self.assertEqual(self.done.get(True, 1), 'DONE')
608 Thread(target=self._doAddSet, args=(['nine'])).start()
609 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
611 self.assertEqual(self.done.get(True, 1), 'DONE')
614 class TestGanetiLockManager(unittest.TestCase):
617 self.nodes=['n1', 'n2']
618 self.instances=['i1', 'i2', 'i3']
619 self.GL = locking.GanetiLockManager(nodes=self.nodes,
620 instances=self.instances)
621 self.done = Queue.Queue(0)
624 # Don't try this at home...
625 locking.GanetiLockManager._instance = None
627 def testLockingConstants(self):
628 # The locking library internally cheats by assuming its constants have some
629 # relationships with each other. Check those hold true.
630 # This relationship is also used in the Processor to recursively acquire
631 # the right locks. Again, please don't break it.
632 for i in range(len(locking.LEVELS)):
633 self.assertEqual(i, locking.LEVELS[i])
635 def testDoubleGLFails(self):
636 self.assertRaises(AssertionError, locking.GanetiLockManager)
638 def testLockNames(self):
639 self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
640 self.assertEqual(self.GL._names(locking.LEVEL_NODE), set(self.nodes))
641 self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE),
644 def testInitAndResources(self):
645 locking.GanetiLockManager._instance = None
646 self.GL = locking.GanetiLockManager()
647 self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
648 self.assertEqual(self.GL._names(locking.LEVEL_NODE), set())
649 self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE), set())
651 locking.GanetiLockManager._instance = None
652 self.GL = locking.GanetiLockManager(nodes=self.nodes)
653 self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
654 self.assertEqual(self.GL._names(locking.LEVEL_NODE), set(self.nodes))
655 self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE), set())
657 locking.GanetiLockManager._instance = None
658 self.GL = locking.GanetiLockManager(instances=self.instances)
659 self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
660 self.assertEqual(self.GL._names(locking.LEVEL_NODE), set())
661 self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE),
664 def testAcquireRelease(self):
665 self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
666 self.assertEquals(self.GL._list_owned(locking.LEVEL_CLUSTER), set(['BGL']))
667 self.GL.acquire(locking.LEVEL_INSTANCE, ['i1'])
668 self.GL.acquire(locking.LEVEL_NODE, ['n1', 'n2'], shared=1)
669 self.GL.release(locking.LEVEL_NODE, ['n2'])
670 self.assertEquals(self.GL._list_owned(locking.LEVEL_NODE), set(['n1']))
671 self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE), set(['i1']))
672 self.GL.release(locking.LEVEL_NODE)
673 self.assertEquals(self.GL._list_owned(locking.LEVEL_NODE), set())
674 self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE), set(['i1']))
675 self.GL.release(locking.LEVEL_INSTANCE)
676 self.assertRaises(errors.LockError, self.GL.acquire,
677 locking.LEVEL_INSTANCE, ['i5'])
678 self.GL.acquire(locking.LEVEL_INSTANCE, ['i3'], shared=1)
679 self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE), set(['i3']))
681 def testAcquireWholeSets(self):
682 self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
683 self.assertEquals(self.GL.acquire(locking.LEVEL_INSTANCE, None),
685 self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE),
687 self.assertEquals(self.GL.acquire(locking.LEVEL_NODE, None, shared=1),
689 self.assertEquals(self.GL._list_owned(locking.LEVEL_NODE),
691 self.GL.release(locking.LEVEL_NODE)
692 self.GL.release(locking.LEVEL_INSTANCE)
693 self.GL.release(locking.LEVEL_CLUSTER)
695 def testAcquireWholeAndPartial(self):
696 self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
697 self.assertEquals(self.GL.acquire(locking.LEVEL_INSTANCE, None),
699 self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE),
701 self.assertEquals(self.GL.acquire(locking.LEVEL_NODE, ['n2'], shared=1),
703 self.assertEquals(self.GL._list_owned(locking.LEVEL_NODE),
705 self.GL.release(locking.LEVEL_NODE)
706 self.GL.release(locking.LEVEL_INSTANCE)
707 self.GL.release(locking.LEVEL_CLUSTER)
709 def testBGLDependency(self):
710 self.assertRaises(AssertionError, self.GL.acquire,
711 locking.LEVEL_NODE, ['n1', 'n2'])
712 self.assertRaises(AssertionError, self.GL.acquire,
713 locking.LEVEL_INSTANCE, ['i3'])
714 self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
715 self.GL.acquire(locking.LEVEL_NODE, ['n1'])
716 self.assertRaises(AssertionError, self.GL.release,
717 locking.LEVEL_CLUSTER, ['BGL'])
718 self.assertRaises(AssertionError, self.GL.release,
719 locking.LEVEL_CLUSTER)
720 self.GL.release(locking.LEVEL_NODE)
721 self.GL.acquire(locking.LEVEL_INSTANCE, ['i1', 'i2'])
722 self.assertRaises(AssertionError, self.GL.release,
723 locking.LEVEL_CLUSTER, ['BGL'])
724 self.assertRaises(AssertionError, self.GL.release,
725 locking.LEVEL_CLUSTER)
726 self.GL.release(locking.LEVEL_INSTANCE)
728 def testWrongOrder(self):
729 self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
730 self.GL.acquire(locking.LEVEL_NODE, ['n2'])
731 self.assertRaises(AssertionError, self.GL.acquire,
732 locking.LEVEL_NODE, ['n1'])
733 self.assertRaises(AssertionError, self.GL.acquire,
734 locking.LEVEL_INSTANCE, ['i2'])
736 # Helper function to run as a thread that shared the BGL and then acquires
737 # some locks at another level.
738 def _doLock(self, level, names, shared):
740 self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
741 self.GL.acquire(level, names, shared=shared)
742 self.done.put('DONE')
743 self.GL.release(level)
744 self.GL.release(locking.LEVEL_CLUSTER)
745 except errors.LockError:
748 def testConcurrency(self):
749 self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
750 Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i1', 1)).start()
751 self.assertEqual(self.done.get(True, 1), 'DONE')
752 self.GL.acquire(locking.LEVEL_INSTANCE, ['i3'])
753 Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i1', 1)).start()
754 self.assertEqual(self.done.get(True, 1), 'DONE')
755 Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i3', 1)).start()
756 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
757 self.GL.release(locking.LEVEL_INSTANCE)
758 self.assertEqual(self.done.get(True, 1), 'DONE')
759 self.GL.acquire(locking.LEVEL_INSTANCE, ['i2'], shared=1)
760 Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i2', 1)).start()
761 self.assertEqual(self.done.get(True, 1), 'DONE')
762 Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i2', 0)).start()
763 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
764 self.GL.release(locking.LEVEL_INSTANCE)
765 self.assertEqual(self.done.get(True, 1), 'DONE')
768 if __name__ == '__main__':
770 #suite = unittest.TestLoader().loadTestsFromTestCase(TestSharedLock)
771 #unittest.TextTestRunner(verbosity=2).run(suite)