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 class TestSharedLock(unittest.TestCase):
36 """SharedLock tests"""
39 self.sl = locking.SharedLock()
40 # helper threads use the 'done' queue to tell the master they finished.
41 self.done = Queue.Queue(0)
43 def testSequenceAndOwnership(self):
44 self.assert_(not self.sl._is_owned())
45 self.sl.acquire(shared=1)
46 self.assert_(self.sl._is_owned())
47 self.assert_(self.sl._is_owned(shared=1))
48 self.assert_(not self.sl._is_owned(shared=0))
50 self.assert_(not self.sl._is_owned())
52 self.assert_(self.sl._is_owned())
53 self.assert_(not self.sl._is_owned(shared=1))
54 self.assert_(self.sl._is_owned(shared=0))
56 self.assert_(not self.sl._is_owned())
57 self.sl.acquire(shared=1)
58 self.assert_(self.sl._is_owned())
59 self.assert_(self.sl._is_owned(shared=1))
60 self.assert_(not self.sl._is_owned(shared=0))
62 self.assert_(not self.sl._is_owned())
64 def testBooleanValue(self):
65 # semaphores are supposed to return a true value on a successful acquire
66 self.assert_(self.sl.acquire(shared=1))
68 self.assert_(self.sl.acquire())
71 def testDoubleLockingStoE(self):
72 self.sl.acquire(shared=1)
73 self.assertRaises(AssertionError, self.sl.acquire)
75 def testDoubleLockingEtoS(self):
77 self.assertRaises(AssertionError, self.sl.acquire, shared=1)
79 def testDoubleLockingStoS(self):
80 self.sl.acquire(shared=1)
81 self.assertRaises(AssertionError, self.sl.acquire, shared=1)
83 def testDoubleLockingEtoE(self):
85 self.assertRaises(AssertionError, self.sl.acquire)
87 # helper functions: called in a separate thread they acquire the lock, send
88 # their identifier on the done queue, then release it.
89 def _doItSharer(self):
91 self.sl.acquire(shared=1)
94 except errors.LockError:
97 def _doItExclusive(self):
102 except errors.LockError:
105 def _doItDelete(self):
109 except errors.LockError:
112 def testSharersCanCoexist(self):
113 self.sl.acquire(shared=1)
114 Thread(target=self._doItSharer).start()
115 self.assert_(self.done.get(True, 1))
118 def testExclusiveBlocksExclusive(self):
120 Thread(target=self._doItExclusive).start()
121 # give it a bit of time to check that it's not actually doing anything
122 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
124 self.assert_(self.done.get(True, 1))
126 def testExclusiveBlocksDelete(self):
128 Thread(target=self._doItDelete).start()
129 # give it a bit of time to check that it's not actually doing anything
130 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
132 self.assert_(self.done.get(True, 1))
134 def testExclusiveBlocksSharer(self):
136 Thread(target=self._doItSharer).start()
138 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
140 self.assert_(self.done.get(True, 1))
142 def testSharerBlocksExclusive(self):
143 self.sl.acquire(shared=1)
144 Thread(target=self._doItExclusive).start()
146 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
148 self.assert_(self.done.get(True, 1))
150 def testSharerBlocksDelete(self):
151 self.sl.acquire(shared=1)
152 Thread(target=self._doItDelete).start()
154 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
156 self.assert_(self.done.get(True, 1))
158 def testWaitingExclusiveBlocksSharer(self):
159 self.sl.acquire(shared=1)
160 # the lock is acquired in shared mode...
161 Thread(target=self._doItExclusive).start()
162 # ...but now an exclusive is waiting...
164 Thread(target=self._doItSharer).start()
165 # ...so the sharer should be blocked as well
166 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
168 # The exclusive passed before
169 self.assertEqual(self.done.get(True, 1), 'EXC')
170 self.assertEqual(self.done.get(True, 1), 'SHR')
172 def testWaitingSharerBlocksExclusive(self):
174 # the lock is acquired in exclusive mode...
175 Thread(target=self._doItSharer).start()
176 # ...but now a sharer is waiting...
178 Thread(target=self._doItExclusive).start()
179 # ...the exclusive is waiting too...
180 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
182 # The sharer passed before
183 self.assertEqual(self.done.get(True, 1), 'SHR')
184 self.assertEqual(self.done.get(True, 1), 'EXC')
186 def testNoNonBlocking(self):
187 self.assertRaises(NotImplementedError, self.sl.acquire, blocking=0)
188 self.assertRaises(NotImplementedError, self.sl.delete, blocking=0)
190 self.sl.delete(blocking=0) # Fine, because the lock is already acquired
192 def testDelete(self):
194 self.assertRaises(errors.LockError, self.sl.acquire)
195 self.assertRaises(errors.LockError, self.sl.acquire, shared=1)
196 self.assertRaises(errors.LockError, self.sl.delete)
198 def testNoDeleteIfSharer(self):
199 self.sl.acquire(shared=1)
200 self.assertRaises(AssertionError, self.sl.delete)
202 def testDeletePendingSharersExclusiveDelete(self):
204 Thread(target=self._doItSharer).start()
205 Thread(target=self._doItSharer).start()
207 Thread(target=self._doItExclusive).start()
208 Thread(target=self._doItDelete).start()
211 # The two threads who were pending return both ERR
212 self.assertEqual(self.done.get(True, 1), 'ERR')
213 self.assertEqual(self.done.get(True, 1), 'ERR')
214 self.assertEqual(self.done.get(True, 1), 'ERR')
215 self.assertEqual(self.done.get(True, 1), 'ERR')
217 def testDeletePendingDeleteExclusiveSharers(self):
219 Thread(target=self._doItDelete).start()
220 Thread(target=self._doItExclusive).start()
222 Thread(target=self._doItSharer).start()
223 Thread(target=self._doItSharer).start()
226 # The two threads who were pending return both ERR
227 self.assertEqual(self.done.get(True, 1), 'ERR')
228 self.assertEqual(self.done.get(True, 1), 'ERR')
229 self.assertEqual(self.done.get(True, 1), 'ERR')
230 self.assertEqual(self.done.get(True, 1), 'ERR')
233 class TestLockSet(unittest.TestCase):
237 self.resources = ['one', 'two', 'three']
238 self.ls = locking.LockSet(members=self.resources)
239 # helper threads use the 'done' queue to tell the master they finished.
240 self.done = Queue.Queue(0)
242 def testResources(self):
243 self.assertEquals(self.ls._names(), set(self.resources))
244 newls = locking.LockSet()
245 self.assertEquals(newls._names(), set())
247 def testAcquireRelease(self):
248 self.assert_(self.ls.acquire('one'))
249 self.assertEquals(self.ls._list_owned(), set(['one']))
251 self.assertEquals(self.ls._list_owned(), set())
252 self.assertEquals(self.ls.acquire(['one']), set(['one']))
253 self.assertEquals(self.ls._list_owned(), set(['one']))
255 self.assertEquals(self.ls._list_owned(), set())
256 self.ls.acquire(['one', 'two', 'three'])
257 self.assertEquals(self.ls._list_owned(), set(['one', 'two', 'three']))
258 self.ls.release('one')
259 self.assertEquals(self.ls._list_owned(), set(['two', 'three']))
260 self.ls.release(['three'])
261 self.assertEquals(self.ls._list_owned(), set(['two']))
263 self.assertEquals(self.ls._list_owned(), set())
264 self.assertEquals(self.ls.acquire(['one', 'three']), set(['one', 'three']))
265 self.assertEquals(self.ls._list_owned(), set(['one', 'three']))
267 self.assertEquals(self.ls._list_owned(), set())
269 def testNoDoubleAcquire(self):
270 self.ls.acquire('one')
271 self.assertRaises(AssertionError, self.ls.acquire, 'one')
272 self.assertRaises(AssertionError, self.ls.acquire, ['two'])
273 self.assertRaises(AssertionError, self.ls.acquire, ['two', 'three'])
275 self.ls.acquire(['one', 'three'])
276 self.ls.release('one')
277 self.assertRaises(AssertionError, self.ls.acquire, ['two'])
278 self.ls.release('three')
280 def testNoWrongRelease(self):
281 self.assertRaises(AssertionError, self.ls.release)
282 self.ls.acquire('one')
283 self.assertRaises(AssertionError, self.ls.release, 'two')
285 def testAddRemove(self):
287 self.assertEquals(self.ls._list_owned(), set())
288 self.assert_('four' in self.ls._names())
289 self.ls.add(['five', 'six', 'seven'], acquired=1)
290 self.assert_('five' in self.ls._names())
291 self.assert_('six' in self.ls._names())
292 self.assert_('seven' in self.ls._names())
293 self.assertEquals(self.ls._list_owned(), set(['five', 'six', 'seven']))
294 self.assertEquals(self.ls.remove(['five', 'six']), ['five', 'six'])
295 self.assert_('five' not in self.ls._names())
296 self.assert_('six' not in self.ls._names())
297 self.assertEquals(self.ls._list_owned(), set(['seven']))
298 self.ls.add('eight', acquired=1, shared=1)
299 self.assert_('eight' in self.ls._names())
300 self.assertEquals(self.ls._list_owned(), set(['seven', 'eight']))
301 self.ls.remove('seven')
302 self.assert_('seven' not in self.ls._names())
303 self.assertEquals(self.ls._list_owned(), set(['eight']))
305 self.ls.remove(['two'])
306 self.assert_('two' not in self.ls._names())
307 self.ls.acquire('three')
308 self.assertEquals(self.ls.remove(['three']), ['three'])
309 self.assert_('three' not in self.ls._names())
310 self.assertEquals(self.ls.remove('three'), [])
311 self.assertEquals(self.ls.remove(['one', 'three', 'six']), ['one'])
312 self.assert_('one' not in self.ls._names())
314 def testRemoveNonBlocking(self):
315 self.assertRaises(NotImplementedError, self.ls.remove, 'one', blocking=0)
316 self.ls.acquire('one')
317 self.assertEquals(self.ls.remove('one', blocking=0), ['one'])
318 self.ls.acquire(['two', 'three'])
319 self.assertEquals(self.ls.remove(['two', 'three'], blocking=0),
322 def testNoDoubleAdd(self):
323 self.assertRaises(errors.LockError, self.ls.add, 'two')
325 self.assertRaises(errors.LockError, self.ls.add, 'four')
327 def testNoWrongRemoves(self):
328 self.ls.acquire(['one', 'three'], shared=1)
329 # Cannot remove 'two' while holding something which is not a superset
330 self.assertRaises(AssertionError, self.ls.remove, 'two')
331 # Cannot remove 'three' as we are sharing it
332 self.assertRaises(AssertionError, self.ls.remove, 'three')
334 def testAcquireSetLock(self):
335 # acquire the set-lock exclusively
336 self.assertEquals(self.ls.acquire(None), set(['one', 'two', 'three']))
337 # I can still add/remove elements...
338 self.assertEquals(self.ls.remove(['two', 'three']), ['two', 'three'])
339 self.assert_(self.ls.add('six'))
342 self.assertEquals(self.ls.acquire(None, shared=1), set(['one', 'six']))
343 # adding new elements is not possible
344 self.assertRaises(AssertionError, self.ls.add, 'five')
347 def _doLockSet(self, set, shared):
349 self.ls.acquire(set, shared=shared)
350 self.done.put('DONE')
352 except errors.LockError:
355 def _doAddSet(self, set):
357 self.ls.add(set, acquired=1)
358 self.done.put('DONE')
360 except errors.LockError:
363 def _doRemoveSet(self, set):
364 self.done.put(self.ls.remove(set))
366 def testConcurrentSharedAcquire(self):
367 self.ls.acquire(['one', 'two'], shared=1)
368 Thread(target=self._doLockSet, args=(['one', 'two'], 1)).start()
369 self.assertEqual(self.done.get(True, 1), 'DONE')
370 Thread(target=self._doLockSet, args=(['one', 'two', 'three'], 1)).start()
371 self.assertEqual(self.done.get(True, 1), 'DONE')
372 Thread(target=self._doLockSet, args=('three', 1)).start()
373 self.assertEqual(self.done.get(True, 1), 'DONE')
374 Thread(target=self._doLockSet, args=(['one', 'two'], 0)).start()
375 Thread(target=self._doLockSet, args=(['two', 'three'], 0)).start()
376 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
378 self.assertEqual(self.done.get(True, 1), 'DONE')
379 self.assertEqual(self.done.get(True, 1), 'DONE')
381 def testConcurrentExclusiveAcquire(self):
382 self.ls.acquire(['one', 'two'])
383 Thread(target=self._doLockSet, args=('three', 1)).start()
384 self.assertEqual(self.done.get(True, 1), 'DONE')
385 Thread(target=self._doLockSet, args=('three', 0)).start()
386 self.assertEqual(self.done.get(True, 1), 'DONE')
387 Thread(target=self._doLockSet, args=(['one', 'two'], 0)).start()
388 Thread(target=self._doLockSet, args=(['one', 'two'], 1)).start()
389 Thread(target=self._doLockSet, args=('one', 0)).start()
390 Thread(target=self._doLockSet, args=('one', 1)).start()
391 Thread(target=self._doLockSet, args=(['two', 'three'], 0)).start()
392 Thread(target=self._doLockSet, args=(['two', 'three'], 1)).start()
393 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
395 self.assertEqual(self.done.get(True, 1), 'DONE')
396 self.assertEqual(self.done.get(True, 1), 'DONE')
397 self.assertEqual(self.done.get(True, 1), 'DONE')
398 self.assertEqual(self.done.get(True, 1), 'DONE')
399 self.assertEqual(self.done.get(True, 1), 'DONE')
400 self.assertEqual(self.done.get(True, 1), 'DONE')
402 def testConcurrentRemove(self):
404 self.ls.acquire(['one', 'two', 'four'])
405 Thread(target=self._doLockSet, args=(['one', 'four'], 0)).start()
406 Thread(target=self._doLockSet, args=(['one', 'four'], 1)).start()
407 Thread(target=self._doLockSet, args=(['one', 'two'], 0)).start()
408 Thread(target=self._doLockSet, args=(['one', 'two'], 1)).start()
409 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
410 self.ls.remove('one')
412 self.assertEqual(self.done.get(True, 1), 'ERR')
413 self.assertEqual(self.done.get(True, 1), 'ERR')
414 self.assertEqual(self.done.get(True, 1), 'ERR')
415 self.assertEqual(self.done.get(True, 1), 'ERR')
416 self.ls.add(['five', 'six'], acquired=1)
417 Thread(target=self._doLockSet, args=(['three', 'six'], 1)).start()
418 Thread(target=self._doLockSet, args=(['three', 'six'], 0)).start()
419 Thread(target=self._doLockSet, args=(['four', 'six'], 1)).start()
420 Thread(target=self._doLockSet, args=(['four', 'six'], 0)).start()
421 self.ls.remove('five')
423 self.assertEqual(self.done.get(True, 1), 'DONE')
424 self.assertEqual(self.done.get(True, 1), 'DONE')
425 self.assertEqual(self.done.get(True, 1), 'DONE')
426 self.assertEqual(self.done.get(True, 1), 'DONE')
427 self.ls.acquire(['three', 'four'])
428 Thread(target=self._doRemoveSet, args=(['four', 'six'], )).start()
429 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
430 self.ls.remove('four')
431 self.assertEqual(self.done.get(True, 1), ['six'])
432 Thread(target=self._doRemoveSet, args=(['two'])).start()
433 self.assertEqual(self.done.get(True, 1), ['two'])
436 def testConcurrentSharedSetLock(self):
437 # share the set-lock...
438 self.ls.acquire(None, shared=1)
439 # ...another thread can share it too
440 Thread(target=self._doLockSet, args=(None, 1)).start()
441 self.assertEqual(self.done.get(True, 1), 'DONE')
442 # ...or just share some elements
443 Thread(target=self._doLockSet, args=(['one', 'three'], 1)).start()
444 self.assertEqual(self.done.get(True, 1), 'DONE')
445 # ...but not add new ones or remove any
446 Thread(target=self._doAddSet, args=(['nine'])).start()
447 Thread(target=self._doRemoveSet, args=(['two'], )).start()
448 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
449 # this just releases the set-lock
451 self.assertEqual(self.done.get(True, 1), 'DONE')
452 # release the lock on the actual elements so remove() can proceed too
454 self.assertEqual(self.done.get(True, 1), ['two'])
456 def testConcurrentExclusiveSetLock(self):
457 # acquire the set-lock...
458 self.ls.acquire(None, shared=0)
459 # ...no one can do anything else
460 Thread(target=self._doLockSet, args=(None, 1)).start()
461 Thread(target=self._doLockSet, args=(None, 0)).start()
462 Thread(target=self._doLockSet, args=(['three'], 0)).start()
463 Thread(target=self._doLockSet, args=(['two'], 1)).start()
464 Thread(target=self._doAddSet, args=(['nine'])).start()
465 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
467 self.assertEqual(self.done.get(True, 1), 'DONE')
468 self.assertEqual(self.done.get(True, 1), 'DONE')
469 self.assertEqual(self.done.get(True, 1), 'DONE')
470 self.assertEqual(self.done.get(True, 1), 'DONE')
471 self.assertEqual(self.done.get(True, 1), 'DONE')
473 def testEmptyLockSet(self):
475 self.assertEqual(self.ls.acquire(None), set(['one', 'two', 'three']))
477 self.ls.remove(['one', 'two', 'three'])
478 # and adds/locks by another thread still wait
479 Thread(target=self._doAddSet, args=(['nine'])).start()
480 Thread(target=self._doLockSet, args=(None, 1)).start()
481 Thread(target=self._doLockSet, args=(None, 0)).start()
482 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
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')
488 self.assertEqual(self.ls.remove(['nine']), ['nine'])
490 self.assertEqual(self.ls.acquire(None, shared=1), set())
491 # other sharers can go, adds still wait
492 Thread(target=self._doLockSet, args=(None, 1)).start()
493 self.assertEqual(self.done.get(True, 1), 'DONE')
494 Thread(target=self._doAddSet, args=(['nine'])).start()
495 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
497 self.assertEqual(self.done.get(True, 1), 'DONE')
500 class TestGanetiLockManager(unittest.TestCase):
503 self.nodes=['n1', 'n2']
504 self.instances=['i1', 'i2', 'i3']
505 self.GL = locking.GanetiLockManager(nodes=self.nodes,
506 instances=self.instances)
507 self.done = Queue.Queue(0)
510 # Don't try this at home...
511 locking.GanetiLockManager._instance = None
513 def testLockingConstants(self):
514 # The locking library internally cheats by assuming its constants have some
515 # relationships with each other. Check those hold true.
516 for i in range(len(locking.LEVELS)):
517 self.assertEqual(i, locking.LEVELS[i])
519 def testDoubleGLFails(self):
520 # We are not passing test=True, so instantiating a new one should fail
521 self.assertRaises(AssertionError, locking.GanetiLockManager)
523 def testLockNames(self):
524 self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
525 self.assertEqual(self.GL._names(locking.LEVEL_NODE), set(self.nodes))
526 self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE),
528 self.assertEqual(self.GL._names(locking.LEVEL_CONFIG), set(['config']))
530 def testInitAndResources(self):
531 locking.GanetiLockManager._instance = None
532 self.GL = locking.GanetiLockManager()
533 self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
534 self.assertEqual(self.GL._names(locking.LEVEL_NODE), set())
535 self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE), set())
536 self.assertEqual(self.GL._names(locking.LEVEL_CONFIG), set(['config']))
538 locking.GanetiLockManager._instance = None
539 self.GL = locking.GanetiLockManager(nodes=self.nodes)
540 self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
541 self.assertEqual(self.GL._names(locking.LEVEL_NODE), set(self.nodes))
542 self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE), set())
543 self.assertEqual(self.GL._names(locking.LEVEL_CONFIG), set(['config']))
545 locking.GanetiLockManager._instance = None
546 self.GL = locking.GanetiLockManager(instances=self.instances)
547 self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
548 self.assertEqual(self.GL._names(locking.LEVEL_NODE), set())
549 self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE),
551 self.assertEqual(self.GL._names(locking.LEVEL_CONFIG), set(['config']))
553 def testAcquireRelease(self):
554 self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
555 self.assertEquals(self.GL._list_owned(locking.LEVEL_CLUSTER), set(['BGL']))
556 self.GL.acquire(locking.LEVEL_NODE, ['n1', 'n2'], shared=1)
557 self.GL.release(locking.LEVEL_NODE)
558 self.GL.acquire(locking.LEVEL_NODE, ['n1'])
559 self.assertEquals(self.GL._list_owned(locking.LEVEL_NODE), set(['n1']))
560 self.GL.acquire(locking.LEVEL_INSTANCE, ['i1', 'i2'])
561 self.GL.acquire(locking.LEVEL_CONFIG, ['config'])
562 self.GL.release(locking.LEVEL_INSTANCE, ['i2'])
563 self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE), set(['i1']))
564 self.GL.release(locking.LEVEL_NODE)
565 self.GL.release(locking.LEVEL_INSTANCE)
566 self.GL.release(locking.LEVEL_CONFIG)
567 self.assertRaises(errors.LockError, self.GL.acquire,
568 locking.LEVEL_INSTANCE, ['i5'])
569 self.GL.acquire(locking.LEVEL_INSTANCE, ['i3'], shared=1)
570 self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE), set(['i3']))
572 def testBGLDependency(self):
573 self.assertRaises(AssertionError, self.GL.acquire,
574 locking.LEVEL_NODE, ['n1', 'n2'])
575 self.assertRaises(AssertionError, self.GL.acquire,
576 locking.LEVEL_INSTANCE, ['i3'])
577 self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
578 self.GL.acquire(locking.LEVEL_NODE, ['n1'])
579 self.assertRaises(AssertionError, self.GL.release,
580 locking.LEVEL_CLUSTER, ['BGL'])
581 self.assertRaises(AssertionError, self.GL.release,
582 locking.LEVEL_CLUSTER)
583 self.GL.release(locking.LEVEL_NODE)
584 self.GL.acquire(locking.LEVEL_INSTANCE, ['i1', 'i2'])
585 self.assertRaises(AssertionError, self.GL.release,
586 locking.LEVEL_CLUSTER, ['BGL'])
587 self.assertRaises(AssertionError, self.GL.release,
588 locking.LEVEL_CLUSTER)
589 self.GL.release(locking.LEVEL_INSTANCE)
590 self.GL.acquire(locking.LEVEL_CONFIG, ['config'])
591 self.assertRaises(AssertionError, self.GL.release,
592 locking.LEVEL_CLUSTER)
594 def testWrongOrder(self):
595 self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
596 self.GL.acquire(locking.LEVEL_INSTANCE, ['i3'])
597 self.assertRaises(AssertionError, self.GL.acquire,
598 locking.LEVEL_NODE, ['n1'])
599 self.assertRaises(AssertionError, self.GL.acquire,
600 locking.LEVEL_INSTANCE, ['i2'])
601 self.GL.acquire(locking.LEVEL_CONFIG, ['config'])
602 self.assertRaises(AssertionError, self.GL.acquire,
603 locking.LEVEL_CONFIG, ['config'])
604 self.GL.release(locking.LEVEL_INSTANCE)
605 self.assertRaises(AssertionError, self.GL.acquire,
606 locking.LEVEL_NODE, ['n1'])
607 self.assertRaises(AssertionError, self.GL.acquire,
608 locking.LEVEL_INSTANCE, ['i2'])
609 self.assertRaises(AssertionError, self.GL.acquire,
610 locking.LEVEL_CONFIG, ['config'])
612 # Helper function to run as a thread that shared the BGL and then acquires
613 # some locks at another level.
614 def _doLock(self, level, names, shared):
616 self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
617 self.GL.acquire(level, names, shared=shared)
618 self.done.put('DONE')
619 self.GL.release(level)
620 self.GL.release(locking.LEVEL_CLUSTER)
621 except errors.LockError:
624 def testConcurrency(self):
625 self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
626 Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i1', 1)).start()
627 self.assertEqual(self.done.get(True, 1), 'DONE')
628 self.GL.acquire(locking.LEVEL_NODE, ['n1'])
629 self.GL.acquire(locking.LEVEL_INSTANCE, ['i3'])
630 self.GL.acquire(locking.LEVEL_CONFIG, ['config'])
631 Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i1', 1)).start()
632 self.assertEqual(self.done.get(True, 1), 'DONE')
633 Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i3', 1)).start()
634 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
635 self.GL.release(locking.LEVEL_CONFIG)
636 self.GL.release(locking.LEVEL_INSTANCE)
637 self.assertEqual(self.done.get(True, 1), 'DONE')
638 self.GL.acquire(locking.LEVEL_INSTANCE, ['i2'], shared=1)
639 Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i2', 1)).start()
640 self.assertEqual(self.done.get(True, 1), 'DONE')
641 Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i2', 0)).start()
642 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
643 self.GL.release(locking.LEVEL_INSTANCE)
644 self.assertEqual(self.done.get(True, 1), 'DONE')
647 if __name__ == '__main__':
649 #suite = unittest.TestLoader().loadTestsFromTestCase(TestSharedLock)
650 #unittest.TextTestRunner(verbosity=2).run(suite)