test(ha-wal-replication): seed current_lsn in 7 stale wal-catchup tests for bug-850 contiguity guard

The bug-850/851 forward-gap contiguity guard (persist.c:839, added in 20e59d0b)
correctly rejects a catch-up entry whose lsn is ahead of the WAL tail (-EAGAIN).
7 test_wal_catchup_* tests in test_config_repl.c predate the guard and applied
non-contiguous LSNs (42, 10-12, 1000+) to a fresh persist (current_lsn=1),
failing deterministically. Seed current_lsn to each test's first applied LSN so
the in-order stream is contiguous (mirroring the real catch-up streamer); the
apply->advance path and all asserted semantics are unchanged. Test-only; the
production contiguity guard is untouched. 179 controller tests, 0 failures (x3).
This commit is contained in:
Rongsong Shen 2026-06-25 03:03:56 +00:00
parent 13c43c23a4
commit 46bd207b0f

View file

@ -1991,6 +1991,23 @@ static void destroy_test_persist_catchup(persist_t *p)
free(p);
}
/* bug-850/851 contiguity guard (persist.c:839): persist_wal_write_replicated
* REFUSES a forward gap (entry.lsn > current_lsn → -EAGAIN) so a standby never
* creates a WAL hole. A fresh persist has current_lsn == 1 (LSN 0 reserved,
* persist.c:542). The catch-up tests below choose their own non-1 starting LSNs
* (42, 10, 20, …); seed current_lsn to the first applied entry's LSN so the
* first entry is contiguous (entry.lsn == current_lsn) and the guard accepts
* the in-order stream — mirroring the real catch-up streamer, which streams
* contiguously from current_lsn. current_lsn is a plain lock-protected field;
* persist.c sets it directly under p->lock (e.g. persist.c:542,715), so do the
* same here. */
static void seed_persist_current_lsn(persist_t *p, uint64_t next_lsn)
{
pthread_mutex_lock(&p->lock);
p->current_lsn = next_lsn;
pthread_mutex_unlock(&p->lock);
}
/* Test 2.1-A: successful single WAL entry advances applied_lsn */
static void test_wal_catchup_entry_advances_applied_lsn(void)
{
@ -2008,6 +2025,9 @@ static void test_wal_catchup_entry_advances_applied_lsn(void)
TEST_ASSERT_EQUAL_UINT64(0,
(uint64_t)atomic_load_explicit(&ha.applied_lsn, memory_order_acquire));
/* Seed current_lsn so the entry at LSN 42 is contiguous (bug-850 guard). */
seed_persist_current_lsn(p, 42);
/* Build a single-entry WAL catch-up with LSN=42, no payload */
wal_catchup_entry_t entry;
memset(&entry, 0, sizeof(entry));
@ -2111,6 +2131,9 @@ static void test_wal_catchup_batch_advances_applied_lsn(void)
TEST_ASSERT_EQUAL_UINT64(0,
(uint64_t)atomic_load_explicit(&ha.applied_lsn, memory_order_acquire));
/* Seed current_lsn so the batch [10,11,12] is contiguous (bug-850 guard). */
seed_persist_current_lsn(p, 10);
/* Build 3 sub-entries at LSNs 10, 11, 12 */
wal_catchup_entry_t e0, e1, e2;
memset(&e0, 0, sizeof(e0));
@ -2163,6 +2186,9 @@ static void test_wal_catchup_partial_batch(void)
/* Pre-set applied_lsn to 5 to verify monotonic advance */
atomic_store_explicit(&ha.applied_lsn, 5, memory_order_release);
/* Seed current_lsn so the batch [20,21] is contiguous (bug-850 guard). */
seed_persist_current_lsn(p, 20);
wal_catchup_entry_t e0, e1;
memset(&e0, 0, sizeof(e0));
memset(&e1, 0, sizeof(e1));
@ -2209,6 +2235,11 @@ static void test_wal_catchup_batch_error_entry_skipped(void)
cfg.election_timeout_ms = 1500;
ha_init(&ha, &cfg, 0);
/* Seed current_lsn so the first good entry at LSN 30 is contiguous (bug-850
* guard). The NULL sub-entry is skipped (no write, current_lsn stays at 31);
* the test only requires applied_lsn >= 30 (the first good entry held). */
seed_persist_current_lsn(p, 30);
/* Good entry at LSN 30, then a NULL pointer (simulates corrupt entry),
* then good entry at LSN 32. */
wal_catchup_entry_t e0, e2;
@ -2260,6 +2291,10 @@ static void test_wal_catchup_batch_zero_entries_fallback(void)
cfg.election_timeout_ms = 1500;
ha_init(&ha, &cfg, 0);
/* Seed current_lsn so the fallback single entry at LSN 50 is contiguous
* (bug-850 guard). */
seed_persist_current_lsn(p, 50);
/* n_entries == 0 → single-entry path from task 2.1 */
wal_catchup_entry_t entry;
memset(&entry, 0, sizeof(entry));
@ -2303,6 +2338,10 @@ static void test_wal_catchup_batch_256_entries(void)
cfg.election_timeout_ms = 1500;
ha_init(&ha, &cfg, 0);
/* Seed current_lsn so the consecutive batch starting at LSN 1000 is
* contiguous (bug-850 guard). */
seed_persist_current_lsn(p, 1000);
/* Allocate 256 sub-entries at consecutive LSNs starting at 1000 */
const int N = 256;
wal_catchup_entry_t entries[N];
@ -2371,6 +2410,9 @@ static void test_wal_catchup_batch_applied_lsn_only_after_full_batch(void)
* from full advance. */
atomic_store_explicit(&ha.applied_lsn, 100, memory_order_release);
/* Seed current_lsn so the batch [200..203] is contiguous (bug-850 guard). */
seed_persist_current_lsn(p, 200);
/* Build a batch of 4 entries at LSNs 200, 201, 202, 203 */
wal_catchup_entry_t e0, e1, e2, e3;
memset(&e0, 0, sizeof(e0));