瀏覽代碼

Add a test to show a bug caused by stale sentinel index.

If timing is right, we could get stale sentinel index from RaftState, and use
that index to authorize tickets in a newer term.
Jing Yang 3 年之前
父節點
當前提交
06e029b724
共有 1 個文件被更改,包括 38 次插入0 次删除
  1. 38 0
      src/verify_authority.rs

+ 38 - 0
src/verify_authority.rs

@@ -953,4 +953,42 @@ mod tests {
         );
         assert_ticket_ready!(t4, VerifyAuthorityResult::TimedOut);
     }
+
+    #[test]
+    fn test_edge_case_stale_sentinel() {
+        let daemon = init_daemon();
+        // We were the leader at an earlier term.
+        let stale_commit_index = COMMIT_INDEX;
+        let stale_sentinel_commit_index = COMMIT_INDEX;
+
+        // Then we lost leadership. Someone became the leader and created new
+        // entries. Those entries are committed, but we did not know.
+        // So our commit index is not moved.
+        let _prev_term_log_index = COMMIT_INDEX + 2;
+        // However, the new leader had answer queries at _prev_term_log_index.
+
+        // We created a new sentinel, it is not yet committed.
+        let _sentinel_commit_index = COMMIT_INDEX + 3;
+
+        // New term, we are the leader.
+        daemon.reset_state(NEXT_TERM);
+        let t = daemon.verify_authority_async(NEXT_TERM, COMMIT_INDEX);
+
+        // We received 3 heartbeats.
+        let beat_ticker0 = daemon.beat_tickers[0].clone();
+        let beat_ticker1 = daemon.beat_tickers[1].clone();
+        let beat_ticker2 = daemon.beat_tickers[2].clone();
+        beat_ticker0.tick(beat_ticker0.next_beat());
+        beat_ticker1.tick(beat_ticker1.next_beat());
+        beat_ticker2.tick(beat_ticker2.next_beat());
+
+        // We are now using stale data from the old term.
+        daemon.run_verify_authority_iteration(
+            TERM,
+            stale_commit_index,
+            stale_sentinel_commit_index,
+        );
+        // This is not right.
+        assert_ticket_ready!(t, VerifyAuthorityResult::Success(COMMIT_INDEX));
+    }
 }