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