feat(ha-commit-engine): honest write-admission quorum accounting (task 4.2)
repl_active_standby_count: registry truth (ep != NULL && !in_catch_up) under r->lock. ha_state_t gains repl back-pointer (wired at init by task 5.3); ha_has_write_quorum uses registry truth when wired, exact legacy fallback when NULL; formula unchanged. Test 29 (wired gate, catch-up-only standby → NOT_READY, admits after clear) captured RED pre-fix. 29/29 group tests; suite at the 3-failure baseline.
This commit is contained in:
parent
b2598823c0
commit
c9154bd5cc
6 changed files with 92 additions and 11 deletions
|
|
@ -1061,6 +1061,45 @@ static void test_gate_reaccepts_after_reconnect_without_reset(void)
|
|||
printf("test_gate_reaccepts_after_reconnect_without_reset: PASS\n");
|
||||
}
|
||||
|
||||
/* ── Test 29: WIRED gate — registry truth excludes catch-up at the gate ───
|
||||
* Task 4.2 (reviewer-mandated RED for the gate half): n_peers=3 primary with
|
||||
* the ha_state_t.repl back-pointer wired to a registry whose ONLY connected
|
||||
* standby is in catch-up. standby_endpoints still lists the endpoint (as
|
||||
* on_standby_connected would), so the legacy count says 1 — but the registry
|
||||
* truth says 0 active. The gate must reject the write with NOT_READY; once
|
||||
* catch-up clears, the very next dispatch is admitted (stateless, Req 6.2).
|
||||
* (Req 3.1, 3.2, 6.1, 6.2) */
|
||||
static void test_gate_wired_registry_catchup_standby_rejects_then_admits(void)
|
||||
{
|
||||
int rc_catchup, rc_cleared;
|
||||
|
||||
/* Arrange: 3-member primary; endpoint registered in standby_endpoints
|
||||
* AND in the replicator registry, where it is marked in catch-up */
|
||||
gate_setup(3, 1);
|
||||
TEST_ASSERT_EQUAL_INT(0, repl_init(&g_reg));
|
||||
TEST_ASSERT_EQUAL_INT(0, repl_add_standby(&g_reg, &g_eps[0], "sb0", 7000));
|
||||
repl_start_catchup(&g_reg, &g_eps[0], 0);
|
||||
g_gate_ha.repl = &g_reg; /* task 5.3 wires this at init; set directly here */
|
||||
|
||||
/* Act: dispatch while the only standby is catching up... */
|
||||
rc_catchup = ha_dispatch_gate(&g_gate_ha, OPCode_jobsub);
|
||||
/* ...then catch-up completes — nothing else changes */
|
||||
repl_complete_catchup(&g_reg, &g_eps[0]);
|
||||
rc_cleared = ha_dispatch_gate(&g_gate_ha, OPCode_jobsub);
|
||||
|
||||
/* Assert: catch-up-only standby → no write quorum at the gate */
|
||||
TEST_ASSERT_EQUAL_INT_MESSAGE(-XCE_ERR_NOT_READY, rc_catchup,
|
||||
"wired gate must reject writes when the only standby is in catch-up");
|
||||
/* ...and clearing catch-up re-admits with no reset call */
|
||||
TEST_ASSERT_EQUAL_INT_MESSAGE(0, rc_cleared,
|
||||
"wired gate must admit writes once catch-up completes");
|
||||
|
||||
g_gate_ha.repl = NULL;
|
||||
repl_fini(&g_reg);
|
||||
gate_teardown();
|
||||
printf("test_gate_wired_registry_catchup_standby_rejects_then_admits: PASS\n");
|
||||
}
|
||||
|
||||
/* ── Test group entry point ──────────────────────────────────────────────── */
|
||||
|
||||
void test_commit_engine(void)
|
||||
|
|
@ -1097,5 +1136,7 @@ void test_commit_engine(void)
|
|||
RUN_TEST(test_gate_single_member_always_admits_writes);
|
||||
RUN_TEST(test_gate_rejects_writes_with_zero_connected_standbys);
|
||||
RUN_TEST(test_gate_reaccepts_after_reconnect_without_reset);
|
||||
/* Task 4.2 — wired gate: registry truth at ha_dispatch_gate */
|
||||
RUN_TEST(test_gate_wired_registry_catchup_standby_rejects_then_admits);
|
||||
UNITY_END();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue