test(raft-log-replication): simulator invariant tests (tasks 9.1-9.4)

9.1 replication + partition catch-up: 3-entry quorum replication then Log Matching;
   isolate a follower, heal, assert next_index walks back, catch-up, Log Matching.
9.2 divergent-suffix truncation (G3): follower with a same-index/different-term tail
   converges via conflict-truncate; byte-for-byte prefix equality + Log Matching.
9.3 drop/dup/reorder convergence: dropped AE recovered; duplicate already-have AE is
   a no-op; genuine out-of-order delivery (entry-3 AE before entry-2) rejected via the
   logOk gap with no phantom gap; converges + Log Matching (Req 8.3).
9.4 chaotic-churn G5/bug-851 regression: stale-term node rejoins under a higher-term
   leader, adopts the term via the AE/heartbeat UpdateTerm path (load-bearing: would
   fail as stale-reject if UpdateTerm-on-AE regressed), voted_for cleared, no second
   leader, and a post-converge election campaigns strictly above the old term (cannot
   reuse). Log Matching holds throughout.

Review-applied: genuine reorder in 9.3; active re-election + voted_for assertions in
9.4. ASAN green (219 tests).
This commit is contained in:
Rongsong Shen 2026-06-21 17:06:05 +00:00
parent 6ff07e5843
commit 9c1a034aa8
2 changed files with 427 additions and 4 deletions

View file

@ -161,28 +161,28 @@
## 9. Simulator invariant tests (Log Matching, truncation, faults, G5 regression)
- [ ] 9.1 Replication + partition catch-up Log Matching test
- [x] 9.1 Replication + partition catch-up Log Matching test
- Test: leader appends 3 entries, replicates to a quorum, assert Log Matching; then isolate a follower across more appends, heal, assert `nextIndex` walks back, the follower catches up, and Log Matching holds
- Observable completion: test passes end-to-end via the sim
- _Requirements: 8.1, 8.3, 8.4_
- _Boundary: test_raft.c, raft_sim.c_
- _Depends: 8.2, 8.3_
- [ ] 9.2 Divergent-suffix truncation test (G3)
- [x] 9.2 Divergent-suffix truncation test (G3)
- Test: give a follower a manufactured divergent tail (same indices, different term), replicate from a higher-term leader; assert the follower truncates the divergent suffix (`on_truncate_from`) and converges to the leader's prefix; Log Matching holds
- Observable completion: test passes; follower's post-converge prefix equals the leader's
- _Requirements: 8.5_
- _Boundary: test_raft.c, raft_sim.c_
- _Depends: 9.1_
- [ ] 9.3 Message drop/dup/reorder convergence test
- [x] 9.3 Message drop/dup/reorder convergence test
- Test: drop, duplicate, and reorder AE requests/replies in the sim queue; assert idempotent convergence (a duplicated AE is a no-op via the already-have branch) and Log Matching after faults clear
- Observable completion: test passes despite injected faults
- _Requirements: 8.3_
- _Boundary: test_raft.c, raft_sim.c_
- _Depends: 9.1_
- [ ] 9.4 Chaotic-churn G5 regression test
- [x] 9.4 Chaotic-churn G5 regression test
- Test: a stale-term node (term lagging) rejoins under a higher-term leader; assert it adopts the higher term from the AE/heartbeat path and does NOT re-elect at a reused term; Log Matching holds across the churn
- Observable completion: test passes; the rejoining node's term equals the leader's after the first heartbeat, and no second leader appears at the reused term
- _Requirements: 8.6_