myxce/src/controller/testsuite/test_ha_ctrlhello.c
Rongsong Shen a81f2a249c fix(controller-tests): make Unity test-file attribution and counters consistent suite-wide
Only 21 of 86 test_*.c group functions called their own nested
UNITY_BEGIN()/UNITY_END(). Each nested call reset Unity's global
NumberOfTests/TestFailures counters, so controller_test.c's final
`return UNITY_END();` -- the value meson test actually gates on --
only ever reflected whichever small window of tests ran since the
LAST nested reset, silently discarding pass/fail evidence for
everything before it (measured: 16 of 972 total tests in one run).
The same nested-BEGIN calls also caused PASS/FAIL banners to show
the wrong source file for tests in files that don't reset it
themselves (Unity.TestFile just carries over from whichever group
last called UNITY_BEGIN()).

Fix: replace every nested UNITY_BEGIN() with UnitySetTestFile(__FILE__)
(sets file attribution only, no counter reset) and drop the matching
UNITY_END(); add the same UnitySetTestFile(__FILE__) as the first
statement to the other group functions that had neither. The 2
genuinely standalone binaries (test_job_array_sched_push.c,
test_job_array_apiserver_push.c -- each has its own int main(), not
registered via controller_test.c's TEST() macro) are untouched.

Verified: single consolidated summary now reads
"972 Tests 0 Failures 0 Ignored OK", exactly matching the
ground-truth RUN_TEST call-site count across all 83 registered
group files (976 total minus 4 belonging to the 2 standalone
binaries). Every PASS/FAIL banner now names its own true source
file. Full xce-build.sh all regression pass clean (Ok: 9, Fail: 0).

No production code touched -- test-harness plumbing only.
2026-07-17 14:49:12 +00:00

131 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)
{
UnitySetTestFile(__FILE__);
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);
}