myxce/src/harness/testsuite/harness_test.c
Rongsong Shen 70d56a5df6
fix(harness): xce_test fake worker defers handler notifications and re-joins after a reconnect (bug-1921)
Worker-context handlers (startjob, runtasks, jobcontrol) run as tasks of
the worker's own connection, so their synchronous notify RPCs waited for
a reply queued behind themselves, timed out (-110) and failed the client
over; the session never joined again, so the controller rejected every
later worker request ("is not a worker") and job usage stayed zero.

Handlers now queue the notification (new worker_notify.{c,h} FIFO) and a
one-shot delay-manager task sends it; housekeeping retries anything left.
A recorded worker join is repeated with the saved attributes once the
connection's reconnect_gen changes.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-06 14:42:28 +00:00

121 lines
3.2 KiB
C

#include <argp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unity/unity.h>
extern void test_waldump(void);
extern void test_walcompare(void);
extern void test_snapverify(void);
extern void test_snapdiff(void);
extern void test_configcompare(void);
extern void test_rcfile(void);
extern void test_flagspec(void);
extern void test_xcetest_interrupt(void);
extern void test_interruptcall(void);
extern void test_confirm(void);
extern void test_listfmt_json(void);
extern void test_xcetest_process_entry(void);
extern void test_test_cli(void);
extern void test_worker_notify(void);
/* test_test_cli.c's leak-safety net (see its own comment): reaps and
* closes any clitest session left open by a test function that aborted
* via a TEST_ASSERT_* failure partway through, before it reached its own
* clitest_kill_and_reap()+clitest_close() cleanup. A no-op whenever no
* session is currently open (i.e. after every test outside test_test_cli,
* and after every test_test_cli sub-test that ran its own cleanup). */
extern void clitest_reap_leaked_session(void);
void setUp(void) { return; }
void tearDown(void)
{
clitest_reap_leaked_session();
printf("\n-----------------------------------------------------\n");
return;
}
static char doc[] = "harness_test";
static char args_doc[] = "";
#define MAX_TESTS (256)
struct arguments {
int ntests;
char* tests[MAX_TESTS];
};
static struct argp_option options[] = {
{ "run", 't', "STR", 0, "run test" },
{ 0 }
};
static error_t parse_opt(int key, char* arg, struct argp_state* state)
{
struct arguments* arguments = state->input;
switch (key) {
case 't':
if (arguments->ntests >= MAX_TESTS) {
fprintf(stderr, "Too many tests\n");
exit(-1);
}
arguments->tests[arguments->ntests] = arg;
arguments->ntests++;
break;
default:
return ARGP_ERR_UNKNOWN;
}
return 0;
}
static struct argp argp = { options, parse_opt, args_doc, doc };
struct arguments arguments;
static int check_test(struct arguments* args, char* x)
{
int i;
if (args->ntests == 0) {
return 1;
}
for (i = 0; i < args->ntests; i++) {
if (strcmp(x, args->tests[i]) == 0) {
return 1;
}
}
return 0;
}
#define TEST(x) \
do { \
if (check_test(&arguments, #x)) { \
x(); \
} \
} while (0)
int main(int argc, char* argv[])
{
argp_parse(&argp, argc, argv, 0, 0, &arguments);
UNITY_BEGIN();
TEST(test_waldump);
TEST(test_walcompare);
TEST(test_snapverify);
TEST(test_snapdiff);
TEST(test_configcompare);
TEST(test_rcfile);
TEST(test_flagspec);
TEST(test_xcetest_interrupt);
TEST(test_interruptcall);
TEST(test_confirm);
TEST(test_listfmt_json);
TEST(test_xcetest_process_entry);
TEST(test_test_cli);
TEST(test_worker_notify);
return UNITY_END();
}