myxce/src/lib/testsuite/test_request_send_propagation.c
Rongsong Shen 80bb1d766e fix(libxce-failover): classify and propagate netio I/O errors on failover
Add io_classify_io_error and propagate endpoint/epoll errors through
endpoint_update_epoll and cbuf_get instead of swallowing them, so client
failover surfaces the real error rather than hanging. Adds netio arm-failure,
close-propagation, and request send-propagation tests.

Pre-existing uncommitted work, committed to establish a clean baseline before
ha-commit-durability implementation.
2026-06-18 04:17:07 +00:00

72 lines
2.3 KiB
C

/*
* test_request_send_propagation.c — bug-650: xce_request() must PROPAGATE an
* endpoint_enq() send failure, not swallow it.
*
* xce_request() (and the other request.c senders) ignored endpoint_enq()'s
* return and always returned 0. So when the transport was dead — endpoint_enq()
* returns <0 and marks the endpoint dead (bug-646) — xce_request() still
* reported success. xce_jobsubmit() then fell through to a BLOCKING cbuf_get()
* and hung forever waiting for a reply to a request that was never transmitted
* (server idle, client fd unconnected). xce_request() must return the negative
* enq error so the failover loop rotates instead of blocking.
*/
#define _GNU_SOURCE
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include <unity/unity.h>
#include "netio.h"
#include "request.h"
/*
* A request that ENCODES successfully but whose send fails because the endpoint
* is dead (EPOLL_CTL_MOD on an fd that is not registered → ENOENT) must make
* xce_request() return a negative error, not 0.
*/
static void test_xce_request_propagates_send_failure(void)
{
iomgr_t iomgr;
memset(&iomgr, 0, sizeof(iomgr));
TEST_ASSERT_EQUAL_INT(0, iomgr_init(&iomgr));
endpoint_t *ep = endpoint_get();
TEST_ASSERT_NOT_NULL(ep);
ep->fd = socket(AF_INET, SOCK_STREAM, 0); /* valid fd, NOT in the epoll */
TEST_ASSERT_TRUE(ep->fd >= 0);
ep->iomgr = &iomgr;
ep->ssl_handshake_done = 1;
ep->flags = 0; /* force iomgr_update_poll MOD on the unregistered fd */
char nm[] = "tester";
char ky[] = "key";
xce_peerinfo_t peer = { .name = nm, .key = ky };
ep->peer = &peer;
xce_request_t req;
memset(&req, 0, sizeof(req));
req.opcode = OPCode_nop;
req.seq = 42;
int rc = xce_request(ep, &req);
/* Old code: always 0 (swallowed). Fixed: the negative enq error propagates. */
TEST_ASSERT_TRUE(rc < 0);
endpoint_fini(ep);
free(ep);
close(iomgr.epoll_fd);
printf("test_xce_request_propagates_send_failure: PASS\n");
}
void test_request_send_propagation(void)
{
printf("\n>> request send-failure propagation tests\n\n");
RUN_TEST(test_xce_request_propagates_send_failure);
}