myxce/src/controller/testsuite/test_ha_ctrlhello.c

132 lines
5.2 KiB
C

/*
* 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 <errno.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <unity/unity.h>
#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();
}