Revision 7ee7c0c7 test/ganeti.locking_unittest.py

b/test/ganeti.locking_unittest.py
412 412
    self.ls.release()
413 413

  
414 414

  
415
class TestGanetiLockManager(unittest.TestCase):
416

  
417
  def setUp(self):
418
    self.nodes=['n1', 'n2']
419
    self.instances=['i1', 'i2', 'i3']
420
    self.GL = locking.GanetiLockManager(nodes=self.nodes,
421
                                        instances=self.instances)
422
    self.done = Queue.Queue(0)
423

  
424
  def tearDown(self):
425
    # Don't try this at home...
426
    locking.GanetiLockManager._instance = None
427

  
428
  def testLockingConstants(self):
429
    # The locking library internally cheats by assuming its constants have some
430
    # relationships with each other. Check those hold true.
431
    for i in range(len(locking.LEVELS)):
432
      self.assertEqual(i, locking.LEVELS[i])
433

  
434
  def testDoubleGLFails(self):
435
    # We are not passing test=True, so instantiating a new one should fail
436
    self.assertRaises(AssertionError, locking.GanetiLockManager)
437

  
438
  def testLockNames(self):
439
    self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
440
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set(self.nodes))
441
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE), set(self.instances))
442
    self.assertEqual(self.GL._names(locking.LEVEL_CONFIG), set(['config']))
443

  
444
  def testInitAndResources(self):
445
    locking.GanetiLockManager._instance = None
446
    self.GL = locking.GanetiLockManager()
447
    self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
448
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set())
449
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE), set())
450
    self.assertEqual(self.GL._names(locking.LEVEL_CONFIG), set(['config']))
451

  
452
    locking.GanetiLockManager._instance = None
453
    self.GL = locking.GanetiLockManager(nodes=self.nodes)
454
    self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
455
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set(self.nodes))
456
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE), set())
457
    self.assertEqual(self.GL._names(locking.LEVEL_CONFIG), set(['config']))
458

  
459
    locking.GanetiLockManager._instance = None
460
    self.GL = locking.GanetiLockManager(instances=self.instances)
461
    self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
462
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set())
463
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE), set(self.instances))
464
    self.assertEqual(self.GL._names(locking.LEVEL_CONFIG), set(['config']))
465

  
466
  def testAcquireRelease(self):
467
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
468
    self.assertEquals(self.GL._list_owned(locking.LEVEL_CLUSTER), set(['BGL']))
469
    self.GL.acquire(locking.LEVEL_NODE, ['n1', 'n2'], shared=1)
470
    self.GL.release(locking.LEVEL_NODE)
471
    self.GL.acquire(locking.LEVEL_NODE, ['n1'])
472
    self.assertEquals(self.GL._list_owned(locking.LEVEL_NODE), set(['n1']))
473
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i1', 'i2'])
474
    self.GL.acquire(locking.LEVEL_CONFIG, ['config'])
475
    self.GL.release(locking.LEVEL_INSTANCE, ['i2'])
476
    self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE), set(['i1']))
477
    self.GL.release(locking.LEVEL_NODE)
478
    self.GL.release(locking.LEVEL_INSTANCE)
479
    self.GL.release(locking.LEVEL_CONFIG)
480
    self.assertRaises(errors.LockError, self.GL.acquire,
481
                      locking.LEVEL_INSTANCE, ['i5'])
482
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i3'], shared=1)
483
    self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE), set(['i3']))
484

  
485
  def testBGLDependency(self):
486
    self.assertRaises(AssertionError, self.GL.acquire,
487
                      locking.LEVEL_NODE, ['n1', 'n2'])
488
    self.assertRaises(AssertionError, self.GL.acquire,
489
                      locking.LEVEL_INSTANCE, ['i3'])
490
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
491
    self.GL.acquire(locking.LEVEL_NODE, ['n1'])
492
    self.assertRaises(AssertionError, self.GL.release,
493
                      locking.LEVEL_CLUSTER, ['BGL'])
494
    self.assertRaises(AssertionError, self.GL.release,
495
                      locking.LEVEL_CLUSTER)
496
    self.GL.release(locking.LEVEL_NODE)
497
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i1', 'i2'])
498
    self.assertRaises(AssertionError, self.GL.release,
499
                      locking.LEVEL_CLUSTER, ['BGL'])
500
    self.assertRaises(AssertionError, self.GL.release,
501
                      locking.LEVEL_CLUSTER)
502
    self.GL.release(locking.LEVEL_INSTANCE)
503
    self.GL.acquire(locking.LEVEL_CONFIG, ['config'])
504
    self.assertRaises(AssertionError, self.GL.release,
505
                      locking.LEVEL_CLUSTER)
506

  
507
  def testWrongOrder(self):
508
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
509
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i3'])
510
    self.assertRaises(AssertionError, self.GL.acquire,
511
                      locking.LEVEL_NODE, ['n1'])
512
    self.assertRaises(AssertionError, self.GL.acquire,
513
                      locking.LEVEL_INSTANCE, ['i2'])
514
    self.GL.acquire(locking.LEVEL_CONFIG, ['config'])
515
    self.assertRaises(AssertionError, self.GL.acquire,
516
                      locking.LEVEL_CONFIG, ['config'])
517
    self.GL.release(locking.LEVEL_INSTANCE)
518
    self.assertRaises(AssertionError, self.GL.acquire,
519
                      locking.LEVEL_NODE, ['n1'])
520
    self.assertRaises(AssertionError, self.GL.acquire,
521
                      locking.LEVEL_INSTANCE, ['i2'])
522
    self.assertRaises(AssertionError, self.GL.acquire,
523
                      locking.LEVEL_CONFIG, ['config'])
524

  
525
  # Helper function to run as a thread that shared the BGL and then acquires
526
  # some locks at another level.
527
  def _doLock(self, level, names, shared):
528
    try:
529
      self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
530
      self.GL.acquire(level, names, shared=shared)
531
      self.done.put('DONE')
532
      self.GL.release(level)
533
      self.GL.release(locking.LEVEL_CLUSTER)
534
    except errors.LockError:
535
      self.done.put('ERR')
536

  
537
  def testConcurrency(self):
538
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
539
    Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i1', 1)).start()
540
    self.assertEqual(self.done.get(True, 1), 'DONE')
541
    self.GL.acquire(locking.LEVEL_NODE, ['n1'])
542
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i3'])
543
    self.GL.acquire(locking.LEVEL_CONFIG, ['config'])
544
    Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i1', 1)).start()
545
    self.assertEqual(self.done.get(True, 1), 'DONE')
546
    Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i3', 1)).start()
547
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
548
    self.GL.release(locking.LEVEL_CONFIG)
549
    self.GL.release(locking.LEVEL_INSTANCE)
550
    self.assertEqual(self.done.get(True, 1), 'DONE')
551
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i2'], shared=1)
552
    Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i2', 1)).start()
553
    self.assertEqual(self.done.get(True, 1), 'DONE')
554
    Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i2', 0)).start()
555
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
556
    self.GL.release(locking.LEVEL_INSTANCE)
557
    self.assertEqual(self.done.get(True, 1), 'DONE')
558

  
559

  
415 560
if __name__ == '__main__':
416 561
  unittest.main()
417 562
  #suite = unittest.TestLoader().loadTestsFromTestCase(TestSharedLock)

Also available in: Unified diff