cluster_start (which set c->running) is orphaned on the HA myapp_run path, so the running flag was never set on HA nodes — check_controller() treated the primary as shutting down and zeroed joblist/workerlist reply chunks. Own the flag lifecycle in cluster_run, symmetric with the c->running=0 on shutdown. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
108 lines
3.7 KiB
C
108 lines
3.7 KiB
C
#include <errno.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unity/unity.h>
|
|
#include "request.h"
|
|
#include "xce/types.h"
|
|
|
|
/* Tests for xce_hostctrl_req() validation paths.
|
|
* We test only early-return paths (before xce_request() is called)
|
|
* since a live endpoint is not available in unit tests. */
|
|
|
|
static void test_hostctrl_req_null_ep(void)
|
|
{
|
|
xce_hostctrl_t ctrl = { .action = HOST_OPEN, .hostname = "host1" };
|
|
int rc = xce_hostctrl_req(NULL, &ctrl);
|
|
TEST_ASSERT_EQUAL_INT(-EINVAL, rc);
|
|
}
|
|
|
|
static void test_hostctrl_req_null_ctrl(void)
|
|
{
|
|
/* non-NULL dummy ep is enough; the NULL ctrl check fires first */
|
|
int rc = xce_hostctrl_req((endpoint_t*)0x1, NULL);
|
|
TEST_ASSERT_EQUAL_INT(-EINVAL, rc);
|
|
}
|
|
|
|
static void test_hostctrl_req_null_hostname(void)
|
|
{
|
|
xce_hostctrl_t ctrl = { .action = HOST_OPEN, .hostname = NULL };
|
|
int rc = xce_hostctrl_req((endpoint_t*)0x1, &ctrl);
|
|
TEST_ASSERT_EQUAL_INT(-EINVAL, rc);
|
|
}
|
|
|
|
static void test_hostctrl_req_empty_hostname(void)
|
|
{
|
|
xce_hostctrl_t ctrl = { .action = HOST_OPEN, .hostname = "" };
|
|
int rc = xce_hostctrl_req((endpoint_t*)0x1, &ctrl);
|
|
TEST_ASSERT_EQUAL_INT(-EINVAL, rc);
|
|
}
|
|
|
|
static void test_hostctrl_req_noop(void)
|
|
{
|
|
xce_hostctrl_t ctrl = { .action = HOST_DO_NONE, .hostname = "host1" };
|
|
int rc = xce_hostctrl_req((endpoint_t*)0x1, &ctrl);
|
|
TEST_ASSERT_EQUAL_INT(0, rc);
|
|
}
|
|
|
|
static void test_hostctrl_req_reject_tag(void)
|
|
{
|
|
xce_hostctrl_t ctrl = { .action = HOST_TAG, .hostname = "host1" };
|
|
int rc = xce_hostctrl_req((endpoint_t*)0x1, &ctrl);
|
|
TEST_ASSERT_EQUAL_INT(-EINVAL, rc);
|
|
}
|
|
|
|
static void test_hostctrl_req_reject_untag(void)
|
|
{
|
|
xce_hostctrl_t ctrl = { .action = HOST_UNTAG, .hostname = "host1" };
|
|
int rc = xce_hostctrl_req((endpoint_t*)0x1, &ctrl);
|
|
TEST_ASSERT_EQUAL_INT(-EINVAL, rc);
|
|
}
|
|
|
|
static void test_hostctrl_req_reject_negative_action(void)
|
|
{
|
|
xce_hostctrl_t ctrl = { .action = -1, .hostname = "host1" };
|
|
int rc = xce_hostctrl_req((endpoint_t*)0x1, &ctrl);
|
|
TEST_ASSERT_EQUAL_INT(-EINVAL, rc);
|
|
}
|
|
|
|
/* init_reply_by_req must fully zero the reply so the generated
|
|
* encode_RequestReply never reads a stale `redirect_host` pointer (and the
|
|
* other common trailer fields) off an uninitialized stack reply. Regression
|
|
* guard for the heap-use-after-free in encode_RequestReply / strlen seen on a
|
|
* NOP/state-report reply whose redirect_host was stack garbage. */
|
|
static void test_init_reply_by_req_zeroes_reply(void)
|
|
{
|
|
/* Poison the whole reply with non-zero bytes — mirrors an uninitialized
|
|
* stack reply whose redirect_host happens to be a (dangling) non-NULL. */
|
|
xce_reply_t reply;
|
|
xce_request_t req = { .seq = 42, .opcode = OPCode_nop };
|
|
memset(&reply, 0xFF, sizeof(reply));
|
|
|
|
init_reply_by_req(&reply, &req);
|
|
|
|
/* seq/opcode carried from the request */
|
|
TEST_ASSERT_EQUAL_UINT64(42, reply.seq);
|
|
TEST_ASSERT_EQUAL_INT(OPCode_nop, reply.opcode);
|
|
|
|
/* Trailer/common fields the encoder always reads must be cleared so a
|
|
* handler that only sets data_which/data cannot leak garbage onto the wire
|
|
* (or dereference a dangling redirect_host). */
|
|
TEST_ASSERT_NULL(reply.redirect_host);
|
|
TEST_ASSERT_EQUAL_UINT(0, reply.redirect_port);
|
|
TEST_ASSERT_EQUAL_INT(0, reply.status);
|
|
TEST_ASSERT_EQUAL_INT(0, reply.data_which);
|
|
}
|
|
|
|
void test_request(void)
|
|
{
|
|
printf("\n>> host control request validation tests\n\n");
|
|
RUN_TEST(test_hostctrl_req_null_ep);
|
|
RUN_TEST(test_hostctrl_req_null_ctrl);
|
|
RUN_TEST(test_hostctrl_req_null_hostname);
|
|
RUN_TEST(test_hostctrl_req_empty_hostname);
|
|
RUN_TEST(test_hostctrl_req_noop);
|
|
RUN_TEST(test_hostctrl_req_reject_tag);
|
|
RUN_TEST(test_hostctrl_req_reject_untag);
|
|
RUN_TEST(test_hostctrl_req_reject_negative_action);
|
|
RUN_TEST(test_init_reply_by_req_zeroes_reply);
|
|
}
|