feat(raft-log-replication): require 4 log callbacks in raft_init + sim log backing (tasks 2.1, 8.1)
2.1: raft_init returns -EINVAL when any of on_persist_entry/on_get_entry_term/ on_send_append_entries/on_truncate_from is NULL (Req 7.1-7.4), before any write to *s; restores s->log_len = cfg->initial_log_len (Req 1.1). 8.1: raft_sim gains a per-node in-memory log (term+bytes per 1-based index) and an AE buffer queue; wires all four callbacks (persist/get-term/truncate/send). Pulled forward to land with 2.1 so the stricter init does not leave the sim/proto suite red between tasks. AE delivery deferred to 8.2. Suite green under ASAN (Ok:1 Fail:0).
This commit is contained in:
parent
7b6cbb8e3e
commit
d70f2507c3
5 changed files with 314 additions and 2 deletions
|
|
@ -46,6 +46,37 @@ static void stub_start_election_after_delay(void *ctx, uint32_t delay_ms)
|
|||
(void)ctx; (void)delay_ms;
|
||||
}
|
||||
|
||||
/* ---- log-replication callback stubs (raft-log-replication) ---- */
|
||||
|
||||
static int stub_persist_entry(void *ctx, uint64_t index, uint64_t term,
|
||||
const void *entry, size_t len)
|
||||
{
|
||||
(void)ctx; (void)index; (void)term; (void)entry; (void)len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint64_t stub_get_entry_term(void *ctx, uint64_t index)
|
||||
{
|
||||
(void)ctx; (void)index;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stub_send_append_entries(void *ctx, int peer_idx,
|
||||
uint64_t prev_log_index,
|
||||
uint64_t prev_log_term,
|
||||
uint64_t leader_commit, int n_entries)
|
||||
{
|
||||
(void)ctx; (void)peer_idx; (void)prev_log_index; (void)prev_log_term;
|
||||
(void)leader_commit; (void)n_entries;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stub_truncate_from(void *ctx, uint64_t index)
|
||||
{
|
||||
(void)ctx; (void)index;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Build a fully-populated callbacks struct */
|
||||
static raft_callbacks_t make_full_cbs(void)
|
||||
{
|
||||
|
|
@ -58,6 +89,10 @@ static raft_callbacks_t make_full_cbs(void)
|
|||
cbs.on_schedule_timeout = stub_schedule_timeout;
|
||||
cbs.on_cancel_timeout = stub_cancel_timeout;
|
||||
cbs.on_start_election_after_delay = stub_start_election_after_delay;
|
||||
cbs.on_persist_entry = stub_persist_entry;
|
||||
cbs.on_get_entry_term = stub_get_entry_term;
|
||||
cbs.on_send_append_entries = stub_send_append_entries;
|
||||
cbs.on_truncate_from = stub_truncate_from;
|
||||
/* on_vote_eligible and on_trace left NULL (optional) */
|
||||
return cbs;
|
||||
}
|
||||
|
|
@ -222,6 +257,12 @@ static raft_callbacks_t make_mock_cbs(void)
|
|||
cbs.on_cancel_timeout = mock_cancel_timeout;
|
||||
cbs.on_start_election_after_delay = mock_start_election_after_delay;
|
||||
cbs.on_send_pre_vote_request = mock_send_pre_vote_request;
|
||||
/* Log-replication callbacks: stubs (task 2.1 only needs them non-NULL for
|
||||
* raft_init validation; behaviour is exercised by later tasks). */
|
||||
cbs.on_persist_entry = stub_persist_entry;
|
||||
cbs.on_get_entry_term = stub_get_entry_term;
|
||||
cbs.on_send_append_entries = stub_send_append_entries;
|
||||
cbs.on_truncate_from = stub_truncate_from;
|
||||
/* on_vote_eligible and on_trace left NULL — tests that need them set explicitly */
|
||||
return cbs;
|
||||
}
|
||||
|
|
@ -361,6 +402,86 @@ static void test_raft_init_null_start_election_after_delay_returns_einval(void)
|
|||
TEST_ASSERT_EQUAL_INT(-EINVAL, raft_init(&s, &cfg));
|
||||
}
|
||||
|
||||
/* ---- log-replication required callbacks (Req 7.1–7.4): each NULL → -EINVAL ---- */
|
||||
|
||||
static void test_raft_init_null_persist_entry_returns_einval(void)
|
||||
{
|
||||
raft_state_t s;
|
||||
raft_callbacks_t cbs = make_full_cbs();
|
||||
raft_config_t cfg;
|
||||
|
||||
memset(&s, 0, sizeof(s));
|
||||
cbs.on_persist_entry = NULL;
|
||||
|
||||
memset(&cfg, 0, sizeof(cfg));
|
||||
cfg.n_peers = 3; cfg.self_idx = 0; cfg.cbs = &cbs;
|
||||
|
||||
TEST_ASSERT_EQUAL_INT(-EINVAL, raft_init(&s, &cfg));
|
||||
}
|
||||
|
||||
static void test_raft_init_null_get_entry_term_returns_einval(void)
|
||||
{
|
||||
raft_state_t s;
|
||||
raft_callbacks_t cbs = make_full_cbs();
|
||||
raft_config_t cfg;
|
||||
|
||||
memset(&s, 0, sizeof(s));
|
||||
cbs.on_get_entry_term = NULL;
|
||||
|
||||
memset(&cfg, 0, sizeof(cfg));
|
||||
cfg.n_peers = 3; cfg.self_idx = 0; cfg.cbs = &cbs;
|
||||
|
||||
TEST_ASSERT_EQUAL_INT(-EINVAL, raft_init(&s, &cfg));
|
||||
}
|
||||
|
||||
static void test_raft_init_null_send_append_entries_returns_einval(void)
|
||||
{
|
||||
raft_state_t s;
|
||||
raft_callbacks_t cbs = make_full_cbs();
|
||||
raft_config_t cfg;
|
||||
|
||||
memset(&s, 0, sizeof(s));
|
||||
cbs.on_send_append_entries = NULL;
|
||||
|
||||
memset(&cfg, 0, sizeof(cfg));
|
||||
cfg.n_peers = 3; cfg.self_idx = 0; cfg.cbs = &cbs;
|
||||
|
||||
TEST_ASSERT_EQUAL_INT(-EINVAL, raft_init(&s, &cfg));
|
||||
}
|
||||
|
||||
static void test_raft_init_null_truncate_from_returns_einval(void)
|
||||
{
|
||||
raft_state_t s;
|
||||
raft_callbacks_t cbs = make_full_cbs();
|
||||
raft_config_t cfg;
|
||||
|
||||
memset(&s, 0, sizeof(s));
|
||||
cbs.on_truncate_from = NULL;
|
||||
|
||||
memset(&cfg, 0, sizeof(cfg));
|
||||
cfg.n_peers = 3; cfg.self_idx = 0; cfg.cbs = &cbs;
|
||||
|
||||
TEST_ASSERT_EQUAL_INT(-EINVAL, raft_init(&s, &cfg));
|
||||
}
|
||||
|
||||
/* All four log callbacks present → succeeds; initial_log_len restored to log_len (Req 1.1) */
|
||||
static void test_raft_init_log_callbacks_present_succeeds(void)
|
||||
{
|
||||
raft_state_t s;
|
||||
raft_callbacks_t cbs = make_full_cbs();
|
||||
raft_config_t cfg;
|
||||
|
||||
memset(&s, 0, sizeof(s));
|
||||
memset(&cfg, 0, sizeof(cfg));
|
||||
cfg.n_peers = 3;
|
||||
cfg.self_idx = 0;
|
||||
cfg.initial_log_len = 5; /* WAL length restored from disk */
|
||||
cfg.cbs = &cbs;
|
||||
|
||||
TEST_ASSERT_EQUAL_INT(0, raft_init(&s, &cfg));
|
||||
TEST_ASSERT_EQUAL_UINT64(5, s.log_len);
|
||||
}
|
||||
|
||||
/* n_peers even (>1) → -EINVAL: even-sized clusters have no fault-tolerance
|
||||
* advantage over the next-smaller odd cluster; reject to prevent misconfiguration. */
|
||||
static void test_raft_init_even_peers_returns_einval(void)
|
||||
|
|
@ -3864,6 +3985,11 @@ void test_raft(void)
|
|||
RUN_TEST(test_raft_init_null_schedule_timeout_returns_einval);
|
||||
RUN_TEST(test_raft_init_null_cancel_timeout_returns_einval);
|
||||
RUN_TEST(test_raft_init_null_start_election_after_delay_returns_einval);
|
||||
RUN_TEST(test_raft_init_null_persist_entry_returns_einval);
|
||||
RUN_TEST(test_raft_init_null_get_entry_term_returns_einval);
|
||||
RUN_TEST(test_raft_init_null_send_append_entries_returns_einval);
|
||||
RUN_TEST(test_raft_init_null_truncate_from_returns_einval);
|
||||
RUN_TEST(test_raft_init_log_callbacks_present_succeeds);
|
||||
RUN_TEST(test_raft_init_even_peers_returns_einval);
|
||||
RUN_TEST(test_raft_init_zero_peers_returns_einval);
|
||||
RUN_TEST(test_raft_init_success_fields);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue