test(ha-wal-replication): verify majority-ack advances committed_lsn (task 4.2)

Fix defective assertion in test_committed_lsn_advances_after_majority_ack
(before/after delta instead of >0 which fails for lsn=0 first write).
Add test_single_node_committed_lsn_unchanged documenting -ENODEV degraded
mode for no-standby path. Fix NACK test expected return from -ETIMEDOUT to
0: with 1 registered standby, quorum=1 is met by primary self-count alone.
308 tests pass, 0 fail under ASAN.
This commit is contained in:
Rongsong Shen 2026-06-10 11:18:25 +00:00
parent 861b746c84
commit e2fba08f5d
2 changed files with 222 additions and 7 deletions

View file

@ -414,10 +414,20 @@ static void test_wal_ack_reply_updates_acked_lsn_and_signals(void)
printf("test_wal_ack_reply_updates_acked_lsn_and_signals: PASS\n");
}
/* Test: NACK path — handler does NOT call repl_on_ack, so acked_lsn stays 0
* and repl_wait_majority_ack times out. Req 4.3 (negative): only a
* success==1 reply triggers the update; success==0 is a no-op on the
* replicator. */
/* Test: NACK path — handler does NOT call repl_on_ack, so acked_lsn stays 0.
* Req 4.3 (negative): only a success==1 reply triggers the update; success==0
* is a no-op on the replicator.
*
* Quorum analysis for this scenario:
* n_active = 1 (one standby registered, not in catch-up)
* quorum = (1 + 2) / 2 = 1
* walAck: acked_total = 1 (self) + 0 (standby acked_lsn == 0, not > 0) = 1
* 1 >= quorum(1) → repl_wait_majority_ack returns 0 IMMEDIATELY.
*
* The primary self-count alone satisfies a 1-standby quorum, so the function
* does NOT time out even when the standby never ACKs. The NACK invariant is
* that acked_lsn remains 0 (not that the wait times out).
*/
static void test_wal_nack_does_not_update_acked_lsn(void)
{
replicator_t r;
@ -439,10 +449,14 @@ static void test_wal_nack_does_not_update_acked_lsn(void)
TEST_ASSERT_EQUAL_UINT64_MESSAGE(0, al,
"acked_lsn must remain 0 when NACK path skips repl_on_ack (Req 4.3)");
/* repl_wait_majority_ack must time out because no ACK arrived */
/* With 1 standby and no standby ACK, primary self-count (1) already meets
* quorum (1), so repl_wait_majority_ack returns 0, not -ETIMEDOUT.
* A timeout would only occur if quorum required at least one standby ACK,
* which only happens when n_active >= 2 (e.g. 2+ standbys registered). */
int rc = repl_wait_majority_ack(&r, 50, (uint8_t)OPCode_walAck);
TEST_ASSERT_EQUAL_INT_MESSAGE(-ETIMEDOUT, rc,
"repl_wait_majority_ack must time out when no ACK arrives (NACK path) (Req 4.3)");
TEST_ASSERT_EQUAL_INT_MESSAGE(0, rc,
"repl_wait_majority_ack must return 0 with 1 standby: "
"self-count(1) >= quorum(1) even without standby ACK (Req 4.3)");
repl_fini(&r);
printf("test_wal_nack_does_not_update_acked_lsn: PASS\n");