Revision 8d7d8b57 test/ganeti.locking_unittest.py

b/test/ganeti.locking_unittest.py
953 953
                                       for i in sorted(perprio.keys())]
954 954
                      for (shared, _, threads) in acquires])
955 955

  
956
  class _FakeTimeForSpuriousNotifications:
957
    def __init__(self, now, check_end):
958
      self.now = now
959
      self.check_end = check_end
960

  
961
      # Deterministic random number generator
962
      self.rnd = random.Random(15086)
963

  
964
    def time(self):
965
      # Advance time if the random number generator thinks so (this is to test
966
      # multiple notifications without advancing the time)
967
      if self.rnd.random() < 0.3:
968
        self.now += self.rnd.random()
969

  
970
      self.check_end(self.now)
971

  
972
      return self.now
973

  
974
  @_Repeat
975
  def testAcquireTimeoutWithSpuriousNotifications(self):
976
    ready = threading.Event()
977
    locked = threading.Event()
978
    req = Queue.Queue(0)
979

  
980
    epoch = 4000.0
981
    timeout = 60.0
982

  
983
    def check_end(now):
984
      self.assertFalse(locked.isSet())
985

  
986
      # If we waited long enough (in virtual time), tell main thread to release
987
      # lock, otherwise tell it to notify once more
988
      req.put(now < (epoch + (timeout * 0.8)))
989

  
990
    time_fn = self._FakeTimeForSpuriousNotifications(epoch, check_end).time
991

  
992
    sl = locking.SharedLock("test", _time_fn=time_fn)
993

  
994
    # Acquire in exclusive mode
995
    sl.acquire(shared=0)
996

  
997
    def fn():
998
      self.assertTrue(sl.acquire(shared=0, timeout=timeout,
999
                                 test_notify=ready.set))
1000
      locked.set()
1001
      sl.release()
1002
      self.done.put("success")
1003

  
1004
    # Start acquire with timeout and wait for it to be ready
1005
    self._addThread(target=fn)
1006
    ready.wait()
1007

  
1008
    # The separate thread is now waiting to acquire the lock, so start sending
1009
    # spurious notifications.
1010

  
1011
    # Wait for separate thread to ask for another notification
1012
    count = 0
1013
    while req.get():
1014
      # After sending the notification, the lock will take a short amount of
1015
      # time to notice and to retrieve the current time
1016
      sl._notify_topmost()
1017
      count += 1
1018

  
1019
    self.assertTrue(count > 100, "Not enough notifications were sent")
1020

  
1021
    self.assertFalse(locked.isSet())
1022

  
1023
    # Some notifications have been sent, now actually release the lock
1024
    sl.release()
1025

  
1026
    # Wait for lock to be acquired
1027
    locked.wait()
1028

  
1029
    self._waitThreads()
1030

  
1031
    self.assertEqual(self.done.get_nowait(), "success")
1032
    self.assertRaises(Queue.Empty, self.done.get_nowait)
1033

  
956 1034

  
957 1035
class TestSharedLockInCondition(_ThreadedTestCase):
958 1036
  """SharedLock as a condition lock tests"""

Also available in: Unified diff