test(scheduler): G-5 JOB_RUSAGE dequeue routing — routes to sched_apply_job_rusage

Closes the G-5 test gap mirroring the G-8 routing test: the rusage notify
handler enqueues XCE_SCHED_OP_JOB_RUSAGE and sched_update() must dispatch it to
sched_apply_job_rusage(), storing the report on the matching job (bug-765 G-5
remediation, production fix already in 93124c5). Driving the real sched_update()
dequeue loop with a recording stub, asserts the request reaches
sched_apply_job_rusage and the job's rusages field is set.

11/11 sched_redispatch_test PASS; full scheduler suite 6/6 OK. Live: job ran to
DONE on the deployed scheduler (G-3 leak fix in place), zero ASAN errors.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
lei.chen 2026-08-14 02:52:09 +00:00
parent 5d345d86b5
commit f3e510a548

View file

@ -72,9 +72,22 @@ int sched_uncharge_account(xce_scheduler_t* s, xce_job_account_t* a)
{
(void)s; (void)a; return 0;
}
/* Recorded for the JOB_RUSAGE routing test below; stores the report on the
* matching job (in-place), -ENOENT when unknown — mirrors schedobj.c. */
static xce_job_rusages_t* g_last_rusage = NULL;
int sched_apply_job_rusage(xce_scheduler_t* s, xce_job_rusages_t* r)
{
(void)s; (void)r; return -ENOENT;
xce_sched_job_t* job;
if (r == NULL) {
return -EINVAL;
}
g_last_rusage = r;
job = sched_get_job(s, r->jobid);
if (job == NULL) {
return -ENOENT;
}
job->rusages = r;
return 0;
}
/* Recorded for the routing test below; mimics the real schedobj.c semantics
* (in-place state update of the existing job, -ENOENT when unknown). */
@ -314,6 +327,35 @@ static void test_bulk_update_existing_job_no_damage(void)
TEST_ASSERT_EQUAL_PTR(so, job->schedobj);
}
/* ── G-5 dequeue routing: JOB_RUSAGE → sched_apply_job_rusage ───────────── */
/* The rusage notify handler enqueues XCE_SCHED_OP_JOB_RUSAGE; sched_update()
* must dispatch it to sched_apply_job_rusage(), which stores the report on
* the matching job (bug-765 G-5 remediation). We drive the real dequeue loop
* with the recording stub and assert routing + storage. */
static void test_rusage_routes_to_apply_on_job(void)
{
xce_scheduler_t sched;
fixture_init(&sched);
xce_sched_job_t* job = seed_job(&sched, 7, JOB_STAT_RUN);
g_last_rusage = NULL;
xce_sched_update_request_t* req =
(xce_sched_update_request_t*)calloc(1, sizeof(*req));
xce_job_rusages_t* ru = (xce_job_rusages_t*)calloc(1, sizeof(*ru));
ru->jobid = 7;
req->op = XCE_SCHED_OP_JOB_RUSAGE;
req->u.job_rusage.rusages = ru;
dataq_enq(sched.pend_updates[0], &(req->link));
TEST_ASSERT_EQUAL_INT(0, sched_update(&sched));
/* routed to sched_apply_job_rusage and stored on the job */
TEST_ASSERT_EQUAL_PTR(ru, g_last_rusage);
TEST_ASSERT_EQUAL_PTR(ru, job->rusages);
}
/* ── Runner ──────────────────────────────────────────────────────────────── */
int main(int argc, char* argv[])
@ -330,5 +372,6 @@ int main(int argc, char* argv[])
RUN_TEST(test_dispatch_commit_null_alloc_unchanged, 0);
RUN_TEST(test_update_fields_routes_to_inplace_path, 0);
RUN_TEST(test_bulk_update_existing_job_no_damage, 0);
RUN_TEST(test_rusage_routes_to_apply_on_job, 0);
return UNITY_END();
}