test(raft-log-replication): close Req 8.3 node-restart with sim restart primitive

raft_sim_restart_node models a process restart: the durable in-memory log[]
(WAL) and persisted (term, voted_for) survive, while volatile consensus state
is cleared by re-running raft_init (returns the node to FOLLOWER). Callbacks,
ctx, idx, and partition flag are preserved.

test_sim_9_5_node_restart_resumes_replication restarts a follower mid-replication
(partial 2-of-3 log), asserts the log survived (load-bearing: log_count==2 would
fail if wiped), role/term restored, then replication resumes and converges with
Log Matching. Closes the 8.3 'node restart while replication proceeds' sub-clause
(8/8 requirement sections now fully covered). ASAN green (220 tests).
This commit is contained in:
Rongsong Shen 2026-06-21 21:49:20 +00:00
parent 0dbccf4b0a
commit 3d6dc9cc56
4 changed files with 116 additions and 1 deletions

View file

@ -513,6 +513,18 @@ void raft_sim_partition(raft_sim_cluster_t *c, int node_idx, int isolated);
*/
int raft_sim_check_log_matching(const raft_sim_cluster_t *c);
/*
* raft_sim_restart_node: model a process restart of node_idx (Req 8.3).
*
* Durable state survives a restart: the in-memory log[] (which models the WAL on
* disk) and the persisted (term, voted_for) are retained. Volatile consensus
* state (role, votes, election bookkeeping, leader progress) is cleared by
* re-running raft_init with the restored (term, voted_for, log_count), returning
* the node to FOLLOWER. The four callbacks, ctx, idx, and partition flag are
* preserved. Returns raft_init's status (0 on success).
*/
int raft_sim_restart_node(raft_sim_cluster_t *c, int node_idx);
#endif /* XCE_TESTING */
#endif /* RAFT_H */

View file

@ -413,4 +413,37 @@ int raft_sim_check_log_matching(const raft_sim_cluster_t *c)
return 1; /* holds */
}
int raft_sim_restart_node(raft_sim_cluster_t *c, int node_idx)
{
if (node_idx < 0 || node_idx >= c->n)
return -1;
raft_sim_node_t *node = &c->nodes[node_idx];
/* Snapshot the DURABLE state that survives a process restart: the persisted
* (term, voted_for) and the log length (the in-memory log[] models the WAL on
* disk and is left untouched). Volatile consensus state is discarded by the
* re-init below. */
uint64_t restored_term = node->state.term;
int restored_voted_for = node->state.voted_for;
uint64_t restored_log_len = (uint64_t)node->log_count;
raft_config_t cfg;
memset(&cfg, 0, sizeof(cfg));
cfg.n_peers = node->state.n_peers;
cfg.self_idx = node->idx;
cfg.my_priority = node->idx;
cfg.election_timeout_ms = node->state.election_timeout_ms;
cfg.initial_term = restored_term;
cfg.initial_voted_for = restored_voted_for;
cfg.initial_log_len = restored_log_len;
cfg.cbs = &node->cbs;
cfg.ctx = node; /* same ctx convention as raft_sim_init */
/* raft_init returns the node to FOLLOWER and clears votes/election/leader
* progress while restoring (term, voted_for, log_len). The log[] array and
* the partition flag are preserved. */
return raft_init(&node->state, &cfg);
}
#endif /* XCE_TESTING */