Skip to content

Commit 1bc7246

Browse files
Fix test failures in test_sync_noflush_novote, take 2
The doTicks approach did not work well because it isn't very accurate and doesn't take into account the time spent outside of the actual ticking. So this replaces it with a direct loop which compares against the current time to ensure that exactly the right amount of time has elapsed since the creation of the SyncObj. This test may break again if the time spent inside SyncObj increases greatly; for example, if __init__ takes very long, the start time would not match the corresponding values inside the objects. Each individual tick may also not take too long.
1 parent ac263d0 commit 1bc7246

File tree

1 file changed

+25
-6
lines changed

1 file changed

+25
-6
lines changed

test_syncobj.py

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,14 @@ def sync_noflush_novote(journalFile2Enabled):
379379
# Specifically, o2 is expected to ignore the messages until 1.1 * timeout, i.e. including the one sent by o1 after 2.5 seconds, except for updating its term.
380380
# Note that o1 has flushing enabled but o2 doesn't!
381381

382+
def tick(o1, o2, startTime, totalTickTime, sleepTime):
383+
# Tick o1 and o2 until totalTickTime has elapsed since startTime
384+
assert time.time() < startTime + totalTickTime # Make sure that we tick at least once
385+
while time.time() < start + totalTickTime:
386+
o1.doTick()
387+
o2.doTick()
388+
time.sleep(sleepTime)
389+
382390
random.seed(42)
383391

384392
a = [getNextAddr(), getNextAddr()]
@@ -397,14 +405,15 @@ def sync_noflush_novote(journalFile2Enabled):
397405

398406
states = defaultdict(list)
399407

408+
start = time.time()
400409
o1 = TestObj(a[0], [a[1]], TEST_TYPE.NOFLUSH_NOVOTE_1, journalFile = journalFiles[0], onStateChanged=lambda old, new: states[a[0]].append(new))
401410
o2 = TestObj(a[1], [a[0]], TEST_TYPE.NOFLUSH_NOVOTE_2, journalFile = journalFiles[1] if journalFile2Enabled else None, onStateChanged=lambda old, new: states[a[1]].append(new))
402411
objs = [o1, o2]
403412

404413
assert not o1._isReady()
405414
assert not o2._isReady()
406415

407-
doTicks(objs, 2.25)
416+
tick(o1, o2, start, 2.25, 0.01)
408417

409418
# Here, o1 has called several elections, but o2 never granted its vote.
410419

@@ -413,20 +422,30 @@ def sync_noflush_novote(journalFile2Enabled):
413422
assert _RAFT_STATE.LEADER not in states[a[0]]
414423
assert states[a[1]] == [] # Never had a state change, i.e. it's still the default follower
415424

416-
doTicks(objs, 0.3) # 2.55 total
425+
tick(o1, o2, start, 2.45, 0.01)
417426

418-
# We have now surpassed o2's timeout, but the last vote request from o1 was at 2.5, i.e. *before* o2's 1.1 * timeout (= 2.64) has expired.
427+
# We have now surpassed o2's timeout, but the last vote request from o1 was at 2.0, i.e. *before* o2's 1.1 * timeout (= 2.64) has expired.
419428
# o2 is expected to have called for an election at 2.4, but o1 would never vote for o2 due to the missing log entry.
420-
# Due to the bigger term in o2's vote request message, o1 should now be a follower.
429+
# o1 converted to a follower due to o2's bigger term.
421430

422431
assert o1._SyncObj__raftState == _RAFT_STATE.FOLLOWER
423432
assert o2._SyncObj__raftState == _RAFT_STATE.CANDIDATE
424433
assert _RAFT_STATE.LEADER not in states[a[0]]
425434
assert _RAFT_STATE.LEADER not in states[a[1]]
426435

427-
doTicks(objs, 0.6) # 3.15 total
436+
tick(o1, o2, start, 2.55, 0.01)
437+
438+
# While o1 converted to a follower at 2.4 due to o2's vote request, it still called for an election at 2.5 since the term change doesn't affect the election timeout.
439+
# Therefore, o2 converted to a follower again at 2.5 due to the bigger term. However, o2 still didn't grant its vote to o1 since 1.1 * timeout (= 2.64) hasn't elapsed yet.
440+
441+
assert o1._SyncObj__raftState == _RAFT_STATE.CANDIDATE
442+
assert o2._SyncObj__raftState == _RAFT_STATE.FOLLOWER
443+
assert _RAFT_STATE.LEADER not in states[a[0]]
444+
assert _RAFT_STATE.LEADER not in states[a[1]]
445+
446+
tick(o1, o2, start, 3.15, 0.01)
428447

429-
# o1 called for another election at 2.9 (it reset its timeout on o2's vote request at 2.4), i.e. after o2's vote block timeout, so it should now be elected.
448+
# o1 called for another election at 3.0, i.e. after o2's vote block timeout, so it should now be elected.
430449
assert o1._SyncObj__raftState == _RAFT_STATE.LEADER
431450
assert o2._SyncObj__raftState == _RAFT_STATE.FOLLOWER
432451
assert _RAFT_STATE.LEADER not in states[a[1]]

0 commit comments

Comments
 (0)