myxce/src/controller/testsuite/test_ctrlstatus.c
Rongsong Shen f4327ce4f6 feat(ha-heartbeat-committed-propagation): migrate last_known_committed_config_tag to _Atomic (task 1.1)
Mirror the sibling last_known_committed_lsn: all writes release, reads acquire.
Prereq for a heartbeat-receive writer + the ctrlstatus reader to interact
safely (Req 2.3). Pure access migration, no behavior change; controller suite
0 failures.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 11:27:46 +00:00

530 lines
22 KiB
C

/* test_ctrlstatus.c — unit tests for the controller status handler
* (controller-status spec, task 2.1).
*
* Exercises ctrlstatus_fill(), the pure local-state snapshot used by
* handle_ctrlstatus(). Splitting the snapshot from the socket send (mirroring
* ha_nop_reply_state_report) makes the field sourcing unit-testable without an
* endpoint. Covers Requirements 1.2, 1.3, 2.1, 2.2, 2.3, 3.1, 3.2, 4.1, 4.2,
* 5.1, 5.2, 5.3, 6.1, 6.2, 6.3, 6.4.
*/
#include <stdatomic.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h> /* setenv */
#include <string.h>
#include <time.h>
#include <unity/unity.h>
#include "ha.h"
#include "include/cluster.h"
#include "myconf.h"
#include "persist.h"
#include "xce/cluster_def.h"
#include "ctrlstatus_fmt.h" /* ctrlstatus_format_time_ms (task 6.3) */
/* ── helpers ────────────────────────────────────────────────── */
static ha_config_t cs_valid_cfg(void)
{
ha_config_t cfg = {
.heartbeat_interval_ms = 3000,
.heartbeat_timeout_ms = 10000,
.election_timeout_ms = 2000,
.probe_connect_timeout_ms = 500,
.max_promotion_retries = 5,
};
return cfg;
}
/* Build a minimal cluster_t whose ha/myconf fields the handler reads.
* Only the fields ctrlstatus_fill() touches are initialised. */
static void cs_setup_cluster(cluster_t* c, myconf_t* mc)
{
memset(c, 0, sizeof(*c));
memset(mc, 0, sizeof(*mc));
ha_config_t cfg = cs_valid_cfg();
TEST_ASSERT_EQUAL_INT(0, ha_init(&c->ha, &cfg, 0));
c->myconf = mc;
mc->name = "ctrlA";
mc->cluster_config = NULL; /* cluster name read from peers/own identity */
/* own identity (xce_peerinfo_t.name is a char*, not a buffer) */
c->myhost_info.name = "ctrlA";
c->myhost = &c->myhost_info;
/* loaded config version + checksum */
mc->config_version_tag = 0xAABBCCDDEE001122ULL;
for (int i = 0; i < 32; i++)
mc->config_sha256[i] = (uint8_t)(i + 1);
/* configured controllers (peers) */
mc->peers_cfg.candidates_count = 3;
strncpy(mc->peers_cfg.candidates[0].name, "ctrlA",
sizeof(mc->peers_cfg.candidates[0].name) - 1);
strncpy(mc->peers_cfg.candidates[0].hostname, "10.0.0.1",
sizeof(mc->peers_cfg.candidates[0].hostname) - 1);
mc->peers_cfg.candidates[0].port = 7001;
strncpy(mc->peers_cfg.candidates[1].name, "ctrlB",
sizeof(mc->peers_cfg.candidates[1].name) - 1);
strncpy(mc->peers_cfg.candidates[1].hostname, "10.0.0.2",
sizeof(mc->peers_cfg.candidates[1].hostname) - 1);
mc->peers_cfg.candidates[1].port = 7002;
strncpy(mc->peers_cfg.candidates[2].name, "ctrlC",
sizeof(mc->peers_cfg.candidates[2].name) - 1);
strncpy(mc->peers_cfg.candidates[2].hostname, "10.0.0.3",
sizeof(mc->peers_cfg.candidates[2].hostname) - 1);
mc->peers_cfg.candidates[2].port = 7003;
}
static void cs_teardown_cluster(cluster_t* c)
{
ha_fini(&c->ha);
}
/* ── tests ──────────────────────────────────────────────────── */
/* (a) PRIMARY: responderRole==PRIMARY, primaryName==self, peers/version
* populated; committed/applied/term reflect the atomics. (Req 2.1, 3.1, 3.2,
* 4.1, 4.2, 5.1, 6.1, 6.2, 6.4) */
static void test_ctrlstatus_primary(void)
{
cluster_t c;
myconf_t mc;
cs_setup_cluster(&c, &mc);
atomic_store_explicit(&c.ha.role, (int32_t)CTRL_PRIMARY,
memory_order_release);
atomic_store_explicit(&c.ha.term, 7, memory_order_release);
atomic_store_explicit(&c.ha.applied_lsn, 42, memory_order_release);
atomic_store_explicit(&c.ha.committed_config_tag, 0xAABBCCDDEE001122ULL,
memory_order_release);
atomic_store_explicit(&c.persist.committed_lsn, 41, memory_order_release);
/* A primary voted "self"; primaryName is derived from its OWN name (role
* == CTRL_PRIMARY), NOT from voted_for_name or the dead primary_host. */
strncpy(c.ha.voted_for_name, "self", sizeof(c.ha.voted_for_name) - 1);
xce_ctrlstatus_t st;
ctrlstatus_fill(&c, &st);
TEST_ASSERT_EQUAL_UINT8((uint8_t)CTRL_PRIMARY, st.responderRole);
TEST_ASSERT_NOT_NULL(st.responderName);
TEST_ASSERT_EQUAL_STRING("ctrlA", st.responderName);
/* Req 2.1: a primary reports itself as the primary (own name). */
TEST_ASSERT_NOT_NULL(st.primaryName);
TEST_ASSERT_EQUAL_STRING("ctrlA", st.primaryName);
TEST_ASSERT_EQUAL_UINT64(7, st.term);
TEST_ASSERT_EQUAL_UINT64(42, st.appliedLsn);
TEST_ASSERT_EQUAL_UINT64(41, st.committedLsn);
TEST_ASSERT_EQUAL_UINT64(0xAABBCCDDEE001122ULL, st.configVersion);
TEST_ASSERT_EQUAL_UINT64(0xAABBCCDDEE001122ULL, st.committedConfigVersion);
/* configChecksum: 64-char lowercase-hex of config_sha256[i]=(i+1), i.e.
* bytes 0x01..0x20. (Req 5.2 content checksum, 5.3 divergence detection) */
TEST_ASSERT_NOT_NULL(st.configChecksum);
TEST_ASSERT_EQUAL_UINT(64u, (unsigned)strlen(st.configChecksum));
TEST_ASSERT_EQUAL_STRING(
"0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20",
st.configChecksum);
TEST_ASSERT_EQUAL_UINT32(3, st.peerCount);
TEST_ASSERT_EQUAL_INT(3, st.peers.count);
TEST_ASSERT_NOT_NULL(st.peers.list);
TEST_ASSERT_EQUAL_STRING("ctrlB", st.peers.list[1]->name);
TEST_ASSERT_EQUAL_STRING("10.0.0.2", st.peers.list[1]->host);
TEST_ASSERT_EQUAL_UINT32(7002, st.peers.list[1]->port);
TEST_ASSERT_EQUAL_UINT(0, st.fenced);
ctrlstatus_free_fields(&st);
cs_teardown_cluster(&c);
printf("test_ctrlstatus_primary: PASS\n");
}
/* (b) STANDBY: role==STANDBY and primaryName is empty ("unknown"). The
* controller does NOT track the current primary's NAME off-primary
* (primary_host is dead; voted_for_name is the last vote, often self — NOT the
* elected leader), so a standby honestly reports "unknown"; the client's
* authoritative path reaches the real primary by rotation. (Req 2.3) */
static void test_ctrlstatus_standby_known_primary(void)
{
cluster_t c;
myconf_t mc;
cs_setup_cluster(&c, &mc);
atomic_store_explicit(&c.ha.role, (int32_t)CTRL_STANDBY,
memory_order_release);
/* Even with a voted_for_name set, a standby must NOT report it as the
* primary (it is frequently the node's own self-vote). */
strncpy(c.ha.voted_for_name, "ctrl-1", sizeof(c.ha.voted_for_name) - 1);
/* All-0xFF digest → 64 'f' chars: a distinct content checksum from the
* primary case proves Req 5.3 — same version tag but differing config bytes
* produce a differing hex; identical bytes would yield identical hex. */
for (int i = 0; i < 32; i++)
mc.config_sha256[i] = 0xFFu;
xce_ctrlstatus_t st;
ctrlstatus_fill(&c, &st);
TEST_ASSERT_EQUAL_UINT8((uint8_t)CTRL_STANDBY, st.responderRole);
TEST_ASSERT_EQUAL_STRING("ctrlA", st.responderName);
TEST_ASSERT_NOT_NULL(st.primaryName);
TEST_ASSERT_EQUAL_STRING("", st.primaryName); /* standby → "unknown" */
TEST_ASSERT_NOT_NULL(st.configChecksum);
TEST_ASSERT_EQUAL_UINT(64u, (unsigned)strlen(st.configChecksum));
TEST_ASSERT_EQUAL_STRING(
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
st.configChecksum);
ctrlstatus_free_fields(&st);
cs_teardown_cluster(&c);
printf("test_ctrlstatus_standby_known_primary: PASS\n");
}
/* (c) STANDBY with no voted_for_name → empty primaryName ("unknown").
* (Req 1.3, 2.2) */
static void test_ctrlstatus_unknown_primary(void)
{
cluster_t c;
myconf_t mc;
cs_setup_cluster(&c, &mc);
atomic_store_explicit(&c.ha.role, (int32_t)CTRL_STANDBY,
memory_order_release);
/* voted_for_name left empty by ha_init → unknown */
xce_ctrlstatus_t st;
ctrlstatus_fill(&c, &st);
TEST_ASSERT_EQUAL_UINT8((uint8_t)CTRL_STANDBY, st.responderRole);
TEST_ASSERT_NOT_NULL(st.primaryName);
TEST_ASSERT_EQUAL_STRING("", st.primaryName); /* empty ⇒ "unknown" */
ctrlstatus_free_fields(&st);
cs_teardown_cluster(&c);
printf("test_ctrlstatus_unknown_primary: PASS\n");
}
/* (c2) STANDBY whose voted_for_name == "self" is NOT a real peer name →
* empty primaryName ("unknown"). "self" is the test/own-vote placeholder
* (ha.c:1282) and must not be surfaced as a primary. (Req 1.3, 2.2) */
static void test_ctrlstatus_standby_self_vote_is_unknown(void)
{
cluster_t c;
myconf_t mc;
cs_setup_cluster(&c, &mc);
atomic_store_explicit(&c.ha.role, (int32_t)CTRL_STANDBY,
memory_order_release);
strncpy(c.ha.voted_for_name, "self", sizeof(c.ha.voted_for_name) - 1);
xce_ctrlstatus_t st;
ctrlstatus_fill(&c, &st);
TEST_ASSERT_EQUAL_UINT8((uint8_t)CTRL_STANDBY, st.responderRole);
TEST_ASSERT_NOT_NULL(st.primaryName);
TEST_ASSERT_EQUAL_STRING("", st.primaryName); /* "self" ⇒ "unknown" */
ctrlstatus_free_fields(&st);
cs_teardown_cluster(&c);
printf("test_ctrlstatus_standby_self_vote_is_unknown: PASS\n");
}
/* (c3) ELECTING (no confirmed primary) → empty primaryName even if a stale
* voted_for_name is present: only CTRL_STANDBY surfaces voted_for_name as the
* primary. (Req 2.2) */
static void test_ctrlstatus_electing_is_unknown(void)
{
cluster_t c;
myconf_t mc;
cs_setup_cluster(&c, &mc);
atomic_store_explicit(&c.ha.role, (int32_t)CTRL_ELECTING,
memory_order_release);
strncpy(c.ha.voted_for_name, "ctrl-1", sizeof(c.ha.voted_for_name) - 1);
xce_ctrlstatus_t st;
ctrlstatus_fill(&c, &st);
TEST_ASSERT_EQUAL_UINT8((uint8_t)CTRL_ELECTING, st.responderRole);
TEST_ASSERT_NOT_NULL(st.primaryName);
TEST_ASSERT_EQUAL_STRING("", st.primaryName); /* electing ⇒ "unknown" */
ctrlstatus_free_fields(&st);
cs_teardown_cluster(&c);
printf("test_ctrlstatus_electing_is_unknown: PASS\n");
}
/* (d) fenced reflects in_catch_up. (Req 6.3) */
static void test_ctrlstatus_fenced_when_in_catch_up(void)
{
cluster_t c;
myconf_t mc;
cs_setup_cluster(&c, &mc);
atomic_store_explicit(&c.ha.role, (int32_t)CTRL_STANDBY,
memory_order_release);
atomic_store_explicit(&c.ha.in_catch_up, 1, memory_order_release);
xce_ctrlstatus_t st;
ctrlstatus_fill(&c, &st);
TEST_ASSERT_EQUAL_UINT(1u, st.fenced ? 1u : 0u);
ctrlstatus_free_fields(&st);
cs_teardown_cluster(&c);
printf("test_ctrlstatus_fenced_when_in_catch_up: PASS\n");
}
/* (e) No-mutation: ctrlstatus_fill() must not change any HA/config state.
* Snapshot the relevant fields, call fill, assert they are unchanged. (Req 1.2)
*/
static void test_ctrlstatus_no_mutation(void)
{
cluster_t c;
myconf_t mc;
cs_setup_cluster(&c, &mc);
atomic_store_explicit(&c.ha.role, (int32_t)CTRL_PRIMARY,
memory_order_release);
atomic_store_explicit(&c.ha.term, 9, memory_order_release);
atomic_store_explicit(&c.ha.applied_lsn, 100, memory_order_release);
atomic_store_explicit(&c.persist.committed_lsn, 99, memory_order_release);
atomic_store_explicit(&c.ha.committed_config_tag, 0x1234ULL,
memory_order_release);
atomic_store_explicit(&c.ha.in_catch_up, 0, memory_order_release);
strncpy(c.ha.voted_for_name, "ctrl-1", sizeof(c.ha.voted_for_name) - 1);
int32_t role0 = atomic_load_explicit(&c.ha.role, memory_order_acquire);
uint64_t term0 = atomic_load_explicit(&c.ha.term, memory_order_acquire);
uint64_t applied0 = atomic_load_explicit(&c.ha.applied_lsn,
memory_order_acquire);
uint64_t committed0 = atomic_load_explicit(&c.persist.committed_lsn,
memory_order_acquire);
uint64_t cfgtag0 = atomic_load_explicit(&c.ha.committed_config_tag,
memory_order_acquire);
int catchup0 = atomic_load_explicit(&c.ha.in_catch_up,
memory_order_acquire);
char voted0[XCE_MAXNAME_LEN];
strncpy(voted0, c.ha.voted_for_name, sizeof(voted0));
uint64_t vertag0 = mc.config_version_tag;
xce_ctrlstatus_t st;
ctrlstatus_fill(&c, &st);
ctrlstatus_free_fields(&st);
TEST_ASSERT_EQUAL_INT(role0, atomic_load_explicit(&c.ha.role,
memory_order_acquire));
TEST_ASSERT_EQUAL_UINT64(term0, atomic_load_explicit(&c.ha.term,
memory_order_acquire));
TEST_ASSERT_EQUAL_UINT64(applied0,
atomic_load_explicit(&c.ha.applied_lsn,
memory_order_acquire));
TEST_ASSERT_EQUAL_UINT64(committed0,
atomic_load_explicit(&c.persist.committed_lsn,
memory_order_acquire));
TEST_ASSERT_EQUAL_UINT64(cfgtag0,
atomic_load_explicit(&c.ha.committed_config_tag,
memory_order_acquire));
TEST_ASSERT_EQUAL_INT(catchup0,
atomic_load_explicit(&c.ha.in_catch_up,
memory_order_acquire));
TEST_ASSERT_EQUAL_STRING(voted0, c.ha.voted_for_name);
TEST_ASSERT_EQUAL_UINT64(vertag0, mc.config_version_tag);
cs_teardown_cluster(&c);
printf("test_ctrlstatus_no_mutation: PASS\n");
}
/* (f) STANDBY reports the LEARNED committed position (Req 10.1, 10.3).
* A standby has never served as primary, so its node-local committed marker
* (persist.committed_lsn) is 0, but it has learned a committed position from
* the primary's heartbeats (last_known_committed_lsn) and has applied entries
* beyond that learned floor. The reply must report the LEARNED committed LSN +
* committed config version (not the node-local zero) and the real applied
* position — with no applied>committed inversion relative to what it knows. */
static void test_ctrlstatus_standby_reports_learned_committed(void)
{
cluster_t c;
myconf_t mc;
cs_setup_cluster(&c, &mc);
atomic_store_explicit(&c.ha.role, (int32_t)CTRL_STANDBY,
memory_order_release);
/* node-local committed marker is unset on a never-primary node */
atomic_store_explicit(&c.persist.committed_lsn, 0, memory_order_release);
/* the primary's own committed_config_tag is also unset locally */
atomic_store_explicit(&c.ha.committed_config_tag, 0, memory_order_release);
/* applied beyond the learned committed floor */
atomic_store_explicit(&c.ha.applied_lsn, 38, memory_order_release);
/* learned from the primary's heartbeats */
atomic_store_explicit(&c.ha.last_known_committed_lsn, 36,
memory_order_release);
atomic_store_explicit(&c.ha.last_known_committed_config_tag,
0x00C0FFEE0000CAFEULL, memory_order_release);
xce_ctrlstatus_t st;
ctrlstatus_fill(&c, &st);
TEST_ASSERT_EQUAL_UINT8((uint8_t)CTRL_STANDBY, st.responderRole);
/* Req 10.1: learned committed values, not the node-local zero */
TEST_ASSERT_EQUAL_UINT64(36, st.committedLsn);
TEST_ASSERT_EQUAL_UINT64(0x00C0FFEE0000CAFEULL, st.committedConfigVersion);
/* Req 10.3: real applied position; no applied>committed inversion vs the
* node's own knowledge (applied 38 >= learned committed 36 is consistent). */
TEST_ASSERT_EQUAL_UINT64(38, st.appliedLsn);
ctrlstatus_free_fields(&st);
cs_teardown_cluster(&c);
printf("test_ctrlstatus_standby_reports_learned_committed: PASS\n");
}
/* (g) STANDBY pre-learn → committed LSN + committed config version are the
* well-defined "unknown"/zero value (Req 10.2). The node has not yet learned
* any committed position from a primary, so it must report 0 (not a stale or
* guessed value), consistent with Req 1.3. */
static void test_ctrlstatus_standby_prelearn_committed_zero(void)
{
cluster_t c;
myconf_t mc;
cs_setup_cluster(&c, &mc);
atomic_store_explicit(&c.ha.role, (int32_t)CTRL_STANDBY,
memory_order_release);
atomic_store_explicit(&c.ha.last_known_committed_lsn, 0,
memory_order_release);
atomic_store_explicit(&c.ha.last_known_committed_config_tag, 0,
memory_order_release);
/* even if the node-local primary marker had a stale value, off-primary it
* must NOT be surfaced — prove the learned (zero) value wins. */
atomic_store_explicit(&c.persist.committed_lsn, 77, memory_order_release);
atomic_store_explicit(&c.ha.committed_config_tag, 0xDEADULL,
memory_order_release);
xce_ctrlstatus_t st;
ctrlstatus_fill(&c, &st);
TEST_ASSERT_EQUAL_UINT8((uint8_t)CTRL_STANDBY, st.responderRole);
TEST_ASSERT_EQUAL_UINT64(0, st.committedLsn); /* Req 10.2 */
TEST_ASSERT_EQUAL_UINT64(0, st.committedConfigVersion); /* Req 10.2 */
ctrlstatus_free_fields(&st);
cs_teardown_cluster(&c);
printf("test_ctrlstatus_standby_prelearn_committed_zero: PASS\n");
}
/* (h) PRIMARY reports its OWN authoritative local committed markers
* (persist.committed_lsn, ha->committed_config_tag) — unchanged behavior. The
* learned last_known_* values must NOT shadow the primary's own markers. */
static void test_ctrlstatus_primary_reports_own_committed(void)
{
cluster_t c;
myconf_t mc;
cs_setup_cluster(&c, &mc);
atomic_store_explicit(&c.ha.role, (int32_t)CTRL_PRIMARY,
memory_order_release);
atomic_store_explicit(&c.persist.committed_lsn, 512, memory_order_release);
atomic_store_explicit(&c.ha.committed_config_tag, 0x0BADF00DULL,
memory_order_release);
/* stale learned values must NOT be surfaced on a primary */
atomic_store_explicit(&c.ha.last_known_committed_lsn, 9,
memory_order_release);
atomic_store_explicit(&c.ha.last_known_committed_config_tag, 0x1111ULL,
memory_order_release);
xce_ctrlstatus_t st;
ctrlstatus_fill(&c, &st);
TEST_ASSERT_EQUAL_UINT8((uint8_t)CTRL_PRIMARY, st.responderRole);
TEST_ASSERT_EQUAL_UINT64(512, st.committedLsn); /* own */
TEST_ASSERT_EQUAL_UINT64(0x0BADF00DULL, st.committedConfigVersion); /* own */
ctrlstatus_free_fields(&st);
cs_teardown_cluster(&c);
printf("test_ctrlstatus_primary_reports_own_committed: PASS\n");
}
/* (i) Responder snapshot timestamp (Req 11.1): responder_time_ms is the
* responder's CLOCK_REALTIME wall clock (epoch ms) at sample time — non-zero
* and within [before, after] of a test-captured wall-clock sample. */
static void test_ctrlstatus_responder_time_ms(void)
{
cluster_t c;
myconf_t mc;
cs_setup_cluster(&c, &mc);
atomic_store_explicit(&c.ha.role, (int32_t)CTRL_STANDBY,
memory_order_release);
struct timespec before_ts;
clock_gettime(CLOCK_REALTIME, &before_ts);
uint64_t before_ms = (uint64_t)before_ts.tv_sec * 1000u
+ (uint64_t)before_ts.tv_nsec / 1000000u;
xce_ctrlstatus_t st;
ctrlstatus_fill(&c, &st);
struct timespec after_ts;
clock_gettime(CLOCK_REALTIME, &after_ts);
uint64_t after_ms = (uint64_t)after_ts.tv_sec * 1000u
+ (uint64_t)after_ts.tv_nsec / 1000000u;
TEST_ASSERT_NOT_EQUAL_UINT64(0, st.responder_time_ms);
/* within the captured window (1 ms slack each side for clock resolution) */
TEST_ASSERT_TRUE(st.responder_time_ms + 1u >= before_ms);
TEST_ASSERT_TRUE(st.responder_time_ms <= after_ms + 1u);
ctrlstatus_free_fields(&st);
cs_teardown_cluster(&c);
printf("test_ctrlstatus_responder_time_ms: PASS\n");
}
/* (j) Responder snapshot timestamp rendering (Req 11.2, 11.3): the test client
* renders responder_time_ms (epoch-millis) into the SAME wall-clock string the
* controller logger (tlog) emits — local-time "YYYY-MM-DD HH:MM:SS,mmm" — so it
* is byte-comparable against ctrl-N.log. Pin TZ=UTC for determinism, then assert
* the exact rendered string for a known epoch-millis. */
static void test_ctrlstatus_format_time_ms(void)
{
setenv("TZ", "UTC", 1);
tzset();
/* 1781939830000 ms == 2026-06-20 07:17:10 UTC; +911 ms of fractional part.
* Renders local time (TZ=UTC) in the tlog prefix shape "%.4d-%.2d-%.2d
* %.2d:%.2d:%.2d,%.3d". */
char buf[64];
uint64_t ms = UINT64_C(1781939830000) + 911u;
char* ret = ctrlstatus_format_time_ms(ms, buf, sizeof(buf));
TEST_ASSERT_EQUAL_PTR(buf, ret);
TEST_ASSERT_EQUAL_STRING("2026-06-20 07:17:10,911", buf);
/* zero-millis fractional part must still be zero-padded to 3 digits */
char* ret2 = ctrlstatus_format_time_ms(UINT64_C(1781939830000), buf,
sizeof(buf));
TEST_ASSERT_EQUAL_PTR(buf, ret2);
TEST_ASSERT_EQUAL_STRING("2026-06-20 07:17:10,000", buf);
printf("test_ctrlstatus_format_time_ms: PASS\n");
}
/* ── suite entry point ─────────────────────────────────────── */
void test_ctrlstatus(void)
{
RUN_TEST(test_ctrlstatus_format_time_ms);
RUN_TEST(test_ctrlstatus_primary);
RUN_TEST(test_ctrlstatus_standby_known_primary);
RUN_TEST(test_ctrlstatus_unknown_primary);
RUN_TEST(test_ctrlstatus_standby_self_vote_is_unknown);
RUN_TEST(test_ctrlstatus_electing_is_unknown);
RUN_TEST(test_ctrlstatus_fenced_when_in_catch_up);
RUN_TEST(test_ctrlstatus_no_mutation);
RUN_TEST(test_ctrlstatus_standby_reports_learned_committed);
RUN_TEST(test_ctrlstatus_standby_prelearn_committed_zero);
RUN_TEST(test_ctrlstatus_primary_reports_own_committed);
RUN_TEST(test_ctrlstatus_responder_time_ms);
}