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:
parent
13c43c23a4
commit
46bd207b0f
1 changed files with 42 additions and 0 deletions
|
|
@ -1991,6 +1991,23 @@ static void destroy_test_persist_catchup(persist_t *p)
|
||||||
free(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 */
|
/* Test 2.1-A: successful single WAL entry advances applied_lsn */
|
||||||
static void test_wal_catchup_entry_advances_applied_lsn(void)
|
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,
|
TEST_ASSERT_EQUAL_UINT64(0,
|
||||||
(uint64_t)atomic_load_explicit(&ha.applied_lsn, memory_order_acquire));
|
(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 */
|
/* Build a single-entry WAL catch-up with LSN=42, no payload */
|
||||||
wal_catchup_entry_t entry;
|
wal_catchup_entry_t entry;
|
||||||
memset(&entry, 0, sizeof(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,
|
TEST_ASSERT_EQUAL_UINT64(0,
|
||||||
(uint64_t)atomic_load_explicit(&ha.applied_lsn, memory_order_acquire));
|
(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 */
|
/* Build 3 sub-entries at LSNs 10, 11, 12 */
|
||||||
wal_catchup_entry_t e0, e1, e2;
|
wal_catchup_entry_t e0, e1, e2;
|
||||||
memset(&e0, 0, sizeof(e0));
|
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 */
|
/* Pre-set applied_lsn to 5 to verify monotonic advance */
|
||||||
atomic_store_explicit(&ha.applied_lsn, 5, memory_order_release);
|
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;
|
wal_catchup_entry_t e0, e1;
|
||||||
memset(&e0, 0, sizeof(e0));
|
memset(&e0, 0, sizeof(e0));
|
||||||
memset(&e1, 0, sizeof(e1));
|
memset(&e1, 0, sizeof(e1));
|
||||||
|
|
@ -2209,6 +2235,11 @@ static void test_wal_catchup_batch_error_entry_skipped(void)
|
||||||
cfg.election_timeout_ms = 1500;
|
cfg.election_timeout_ms = 1500;
|
||||||
ha_init(&ha, &cfg, 0);
|
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),
|
/* Good entry at LSN 30, then a NULL pointer (simulates corrupt entry),
|
||||||
* then good entry at LSN 32. */
|
* then good entry at LSN 32. */
|
||||||
wal_catchup_entry_t e0, e2;
|
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;
|
cfg.election_timeout_ms = 1500;
|
||||||
ha_init(&ha, &cfg, 0);
|
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 */
|
/* n_entries == 0 → single-entry path from task 2.1 */
|
||||||
wal_catchup_entry_t entry;
|
wal_catchup_entry_t entry;
|
||||||
memset(&entry, 0, sizeof(entry));
|
memset(&entry, 0, sizeof(entry));
|
||||||
|
|
@ -2303,6 +2338,10 @@ static void test_wal_catchup_batch_256_entries(void)
|
||||||
cfg.election_timeout_ms = 1500;
|
cfg.election_timeout_ms = 1500;
|
||||||
ha_init(&ha, &cfg, 0);
|
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 */
|
/* Allocate 256 sub-entries at consecutive LSNs starting at 1000 */
|
||||||
const int N = 256;
|
const int N = 256;
|
||||||
wal_catchup_entry_t entries[N];
|
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. */
|
* from full advance. */
|
||||||
atomic_store_explicit(&ha.applied_lsn, 100, memory_order_release);
|
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 */
|
/* Build a batch of 4 entries at LSNs 200, 201, 202, 203 */
|
||||||
wal_catchup_entry_t e0, e1, e2, e3;
|
wal_catchup_entry_t e0, e1, e2, e3;
|
||||||
memset(&e0, 0, sizeof(e0));
|
memset(&e0, 0, sizeof(e0));
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue