#define _GNU_SOURCE #include #include #include "config.h" #include "ha.h" /* ==================================================================== * raft-drive-async task 1.1 — drive-async configuration constants and * the peer-scaled liveness-reservation clamp helper. * * Helper under test: * int drive_async_liveness_reserved(int n_peers, int n_vcpus); * * Formula (design "LivenessAdmission → Sizing (peer-scaled)"): * VTASK_LIVENESS_RESERVED = clamp(n_peers - 1, 1, n_vcpus - 1) * = max(1, min(n_peers - 1, n_vcpus - 1)) * floor 1 -> deadlock-freedom (always >=1 guaranteed-free worker) * ceiling n_vcpus - 1 -> keep >=1 REQ_BLOCK (commit) slot, cap never 0 * The floor is applied LAST so it always wins (the hard correctness invariant). * ==================================================================== */ /* ── Regime 1: normal n_peers-1 (the un-clamped middle) ───────────── */ static void test_liveness_reserved_normal_three_peers(void) { /* 3-node cluster, 8 vcpus: n_peers-1 = 2, well under ceiling 7. */ TEST_ASSERT_EQUAL_INT(2, drive_async_liveness_reserved(3, 8)); } static void test_liveness_reserved_normal_five_peers(void) { /* 5-node cluster, 8 vcpus: n_peers-1 = 4, under ceiling 7. */ TEST_ASSERT_EQUAL_INT(4, drive_async_liveness_reserved(5, 8)); } /* ── Regime 2: floor hit (n_peers-1 would be < 1) ─────────────────── */ static void test_liveness_reserved_floor_single_node(void) { /* n_peers=1 -> n_peers-1 = 0 -> floor 1 must win. */ TEST_ASSERT_EQUAL_INT(1, drive_async_liveness_reserved(1, 8)); } static void test_liveness_reserved_floor_zero_peers(void) { /* Degenerate n_peers=0 -> n_peers-1 = -1 -> floor 1 must win. */ TEST_ASSERT_EQUAL_INT(1, drive_async_liveness_reserved(0, 8)); } /* ── Regime 3: ceiling / clamp hit (under-provisioned: n_vcpus < n_peers) ── */ static void test_liveness_reserved_ceiling_clamps_below_npeers(void) { /* n_peers=5, n_vcpus=3: n_peers-1 = 4 clamped to ceiling n_vcpus-1 = 2. */ TEST_ASSERT_EQUAL_INT(2, drive_async_liveness_reserved(5, 3)); } static void test_liveness_reserved_ceiling_floor_wins_one_vcpu(void) { /* n_vcpus=1 -> ceiling n_vcpus-1 = 0, but the floor of 1 must win: * max(1, min(n_peers-1, 0)) = max(1, 0) = 1. Never returns 0. */ TEST_ASSERT_EQUAL_INT(1, drive_async_liveness_reserved(5, 1)); } static void test_liveness_reserved_exactly_npeers_vcpus(void) { /* n_vcpus == n_peers: ceiling = n_vcpus-1 = n_peers-1 -> no clamp. * 3 peers, 3 vcpus -> min(2, 2) = 2. */ TEST_ASSERT_EQUAL_INT(2, drive_async_liveness_reserved(3, 3)); } static void test_liveness_reserved_never_exceeds_vcpus_minus_one(void) { /* Invariant: result <= n_vcpus-1 keeps >=1 commit slot (cap never 0). */ for (int p = 0; p <= 8; p++) { for (int v = 1; v <= 8; v++) { int r = drive_async_liveness_reserved(p, v); TEST_ASSERT_TRUE_MESSAGE(r >= 1, "reservation floor 1 violated"); TEST_ASSERT_TRUE_MESSAGE(r <= (v - 1 > 0 ? v - 1 : 1), "reservation must keep >=1 commit slot"); } } } void test_drive_async_config(void) { UnitySetTestFile(__FILE__); RUN_TEST(test_liveness_reserved_normal_three_peers); RUN_TEST(test_liveness_reserved_normal_five_peers); RUN_TEST(test_liveness_reserved_floor_single_node); RUN_TEST(test_liveness_reserved_floor_zero_peers); RUN_TEST(test_liveness_reserved_ceiling_clamps_below_npeers); RUN_TEST(test_liveness_reserved_ceiling_floor_wins_one_vcpu); RUN_TEST(test_liveness_reserved_exactly_npeers_vcpus); RUN_TEST(test_liveness_reserved_never_exceeds_vcpus_minus_one); }