/* * test_ha_ctrlhello.c — Unit tests for handle_ctrlhello() (task 9.3). * * Tests exercise the primary-side OP_ctrlHello handler: * - CtrlHelloRequest struct fields accessible (schema compile check) * - CtrlHelloReply fields accessible (schema compile check) * - handle_ctrlhello with malformed request returns -EINVAL * - typemap fields: ctrl_hello_req_t and ctrl_hello_reply_t compile * - OPCode_walCatchupEntry exists in generated capnp header * - Request_body_ctrlhellomsg discriminant exists * * Full integration (WAL streaming, snapshot transfer) requires a live cluster * and is validated via make test-integration. * * Requirements: 6.5, 6.6, 6.7 */ #define _GNU_SOURCE #include #include #include #include #include #include "controller.capnp.h" #include "typemap.h" #include "config_repl.h" /* ── Test 1: CtrlHelloRequest struct is accessible from capnp.h ─────────── */ static void test_ctrl_hello_request_fields_accessible(void) { /* Static compile check: access CtrlHelloRequest field constants */ TEST_ASSERT_GREATER_THAN(0, (int)CtrlHelloRequest_struct_bytes_count); TEST_ASSERT_GREATER_THAN(0, (int)CtrlHelloRequest_word_count); printf("test_ctrl_hello_request_fields_accessible: PASS\n"); } /* ── Test 2: CtrlHelloReply struct is accessible from capnp.h ──────────── */ static void test_ctrl_hello_reply_fields_accessible(void) { TEST_ASSERT_GREATER_THAN(0, (int)CtrlHelloReply_struct_bytes_count); TEST_ASSERT_GREATER_THAN(0, (int)CtrlHelloReply_word_count); printf("test_ctrl_hello_reply_fields_accessible: PASS\n"); } /* ── Test 3: ctrl_hello_req_t C struct compiles correctly ───────────────── */ static void test_ctrl_hello_req_t_layout(void) { ctrl_hello_req_t req; memset(&req, 0, sizeof(req)); req.name = NULL; req.key = NULL; req.applied_lsn = 42; req.config_tag = 7; TEST_ASSERT_EQUAL_UINT64(42, req.applied_lsn); TEST_ASSERT_EQUAL_UINT64(7, req.config_tag); printf("test_ctrl_hello_req_t_layout: PASS\n"); } /* ── Test 4: ctrl_hello_reply_t C struct compiles correctly ─────────────── */ static void test_ctrl_hello_reply_t_layout(void) { ctrl_hello_reply_t rep; memset(&rep, 0, sizeof(rep)); rep.committed_lsn = 100; rep.needs_snapshot = 0; rep.config_tag = 5; TEST_ASSERT_EQUAL_UINT64(100, rep.committed_lsn); TEST_ASSERT_EQUAL_INT(0, rep.needs_snapshot); TEST_ASSERT_EQUAL_UINT64(5, rep.config_tag); printf("test_ctrl_hello_reply_t_layout: PASS\n"); } /* ── Test 5: OPCode_walCatchupEntry exists in generated capnp header ────── */ static void test_opcode_walcatchupentry_exists(void) { int opcode = (int)OPCode_walCatchupEntry; TEST_ASSERT_EQUAL_INT(37, opcode); printf("test_opcode_walcatchupentry_exists: PASS\n"); } /* ── Test 6: Request_body_ctrlhellomsg discriminant exists ─────────────── */ static void test_request_body_ctrlhellomsg_exists(void) { int disc = (int)Request_body_ctrlhellomsg; /* The body union discriminant is derived from @N in the capnp schema. * ctrlhellomsg @26 → discriminant 23 (0-indexed from @3, fields @3..@26). */ TEST_ASSERT_GREATER_OR_EQUAL(0, disc); printf("test_request_body_ctrlhellomsg_exists (disc=%d): PASS\n", disc); } /* ── Test 7: handle_ctrlhello rejects request with wrong body_which ─────── */ static void test_handle_ctrlhello_rejects_malformed(void) { /* NULL cluster — handle_ctrlhello checks body_which before dereferencing c */ xce_request_t req; memset(&req, 0, sizeof(req)); req.opcode = OPCode_hello; req.body_which = Request_body_nomsg; /* not ctrlhellomsg */ int rc = handle_ctrlhello(NULL, NULL, &req); TEST_ASSERT_EQUAL_INT(-EINVAL, rc); printf("test_handle_ctrlhello_rejects_malformed: PASS\n"); } /* ── Test 8: handle_ctrlhello rejects NULL body pointer ─────────────────── */ static void test_handle_ctrlhello_rejects_null_body(void) { xce_request_t req; memset(&req, 0, sizeof(req)); req.opcode = OPCode_hello; req.body_which = Request_body_ctrlhellomsg; req.body.ctrlhellomsg = NULL; /* body set but null payload */ int rc = handle_ctrlhello(NULL, NULL, &req); TEST_ASSERT_EQUAL_INT(-EINVAL, rc); printf("test_handle_ctrlhello_rejects_null_body: PASS\n"); } /* ── Suite entry point ──────────────────────────────────────────────────── */ void test_ha_ctrlhello(void) { UNITY_BEGIN(); RUN_TEST(test_ctrl_hello_request_fields_accessible); RUN_TEST(test_ctrl_hello_reply_fields_accessible); RUN_TEST(test_ctrl_hello_req_t_layout); RUN_TEST(test_ctrl_hello_reply_t_layout); RUN_TEST(test_opcode_walcatchupentry_exists); RUN_TEST(test_request_body_ctrlhellomsg_exists); RUN_TEST(test_handle_ctrlhello_rejects_malformed); RUN_TEST(test_handle_ctrlhello_rejects_null_body); UNITY_END(); }