test(election-iomgr-refactor): add committing_timeout_fn watchdog unit tests — task 6.1

This commit is contained in:
Rongsong Shen 2026-05-30 13:19:31 +00:00
parent 27ea14cd9a
commit 0fdcd11e5f
2 changed files with 86 additions and 0 deletions

View file

@ -1638,6 +1638,29 @@ int election_timeout_fn_for_test(ha_state_t *ha, ha_elect_ctx_t *ctx,
pthread_mutex_unlock(&ctx->lock);
return 0;
}
/*
* committing_timeout_fn_for_test: test helper that exercises the committing
* timeout callback logic with an explicit cancelled_val. The cluster pointer
* may be NULL; the function checks the role on `ha` and calls
* ha_promote_to_primary(c) only when role == CTRL_PRIMARY_COMMITTING && c != NULL.
*
* Unlike the production callback, this shim does NOT free the ctx structure —
* it is stack/test-owned and must not be heap-freed by the shim.
*
* Returns 0 in all cases (mirrors the real callback).
*/
int committing_timeout_fn_for_test(ha_state_t *ha, cluster_t *c,
int cancelled_val)
{
if (cancelled_val)
return 0;
ctrl_role_t role = (ctrl_role_t)atomic_load_explicit(&ha->role,
memory_order_acquire);
if (role == CTRL_PRIMARY_COMMITTING && c != NULL)
ha_promote_to_primary(c);
return 0;
}
#endif /* XCE_TESTING */
/* ── Task 2.4: election_timeout_fn — delaymgr callback ─────────────────────

View file

@ -26,6 +26,7 @@
#include <unity/unity.h>
#include "ha.h"
#include "xce/cluster_def.h" /* full cluster_t layout for committing_timeout_fn tests */
/* ── Test-only seam: cluster_init_phase2 call counter ───────────────────────
*
@ -366,6 +367,66 @@ static void test_done_posted_prevents_double_execute(void)
printf("test_done_posted_prevents_double_execute: PASS (calls=%d)\n", g_phase2_call_count);
}
/* ── Test 9: committing_timeout_fn fires ha_promote_to_primary ───────────── */
static void test_committing_timeout_fn_promotes_to_primary(void)
{
/* Req 4.3, 8.4: when not cancelled and role == CTRL_PRIMARY_COMMITTING,
* committing_timeout_fn must call ha_promote_to_primary, which drives
* c->ha.role to CTRL_PRIMARY (degraded promotion). */
reset_counters();
/* Zero-init cluster: xce_add_hook returns -EINVAL harmlessly on zeroed
* hooksys, so ha_promote_to_primary is safe to call (comment at ha.c:603). */
cluster_t c;
memset(&c, 0, sizeof(c));
ha_init(&c.ha, &g_cfg, 0);
atomic_store_explicit(&c.ha.role, (int32_t)CTRL_PRIMARY_COMMITTING,
memory_order_release);
extern int committing_timeout_fn_for_test(ha_state_t *ha, cluster_t *c,
int cancelled_val);
committing_timeout_fn_for_test(&c.ha, &c, 0 /* not cancelled */);
ctrl_role_t role =
(ctrl_role_t)atomic_load_explicit(&c.ha.role, memory_order_acquire);
TEST_ASSERT_EQUAL_INT_MESSAGE((int)CTRL_PRIMARY, (int)role,
"committing_timeout_fn (not cancelled, COMMITTING role) must promote to CTRL_PRIMARY");
ha_fini(&c.ha);
clear_hook();
printf("test_committing_timeout_fn_promotes_to_primary: PASS (role=%d==CTRL_PRIMARY)\n",
(int)role);
}
/* ── Test 10: cancelled committing_timeout_fn → no role change ───────────── */
static void test_committing_timeout_fn_cancelled_is_noop(void)
{
/* Req 4.3: when cancelled=1, committing_timeout_fn must be a no-op;
* ha->role must remain CTRL_PRIMARY_COMMITTING. */
reset_counters();
cluster_t c;
memset(&c, 0, sizeof(c));
ha_init(&c.ha, &g_cfg, 0);
atomic_store_explicit(&c.ha.role, (int32_t)CTRL_PRIMARY_COMMITTING,
memory_order_release);
extern int committing_timeout_fn_for_test(ha_state_t *ha, cluster_t *c,
int cancelled_val);
committing_timeout_fn_for_test(&c.ha, &c, 1 /* cancelled */);
ctrl_role_t role =
(ctrl_role_t)atomic_load_explicit(&c.ha.role, memory_order_acquire);
TEST_ASSERT_EQUAL_INT_MESSAGE((int)CTRL_PRIMARY_COMMITTING, (int)role,
"cancelled committing_timeout_fn must not change ha->role");
ha_fini(&c.ha);
clear_hook();
printf("test_committing_timeout_fn_cancelled_is_noop: PASS (role still CTRL_PRIMARY_COMMITTING)\n");
}
/* ── Suite entry point ───────────────────────────────────────────────────── */
void test_ha_evaluate_committing(void)
@ -378,4 +439,6 @@ void test_ha_evaluate_committing(void)
RUN_TEST(test_election_timeout_fn_fires_evaluate);
RUN_TEST(test_cancelled_timeout_is_noop);
RUN_TEST(test_done_posted_prevents_double_execute);
RUN_TEST(test_committing_timeout_fn_promotes_to_primary);
RUN_TEST(test_committing_timeout_fn_cancelled_is_noop);
}