132 lines
5.2 KiB
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();
|
|
}
|