fix(scheduler): gate resource value/used display on XCE_RESF_CONSUMABLE

repl_info_worker_one() ("info worker <name>") unconditionally showed a
total=/available= pair for every numeric per-worker resource, regardless
of whether it was actually consumable -- misleading for a static
per-worker attribute nothing ever allocates against.

repl_info_resource_one() ("info resource <name|all>") never reported a
consumable GLOBAL/SHARED resource's in-use amount at all, even though
core->sharedInUse (the cluster-wide mirror of a worker's resInUse)
already exists and is populated by the real resource-accounting code.

Both now gate on XCE_RESF_CONSUMABLE: consumable resources report
value=<capacity> used=<in-use>, non-consumable resources keep a single
value=<current> line. Also added the resource definition's missing
ordtype= field.

Add test_info_resource_reports_consumable_value_and_used and
test_info_worker_reports_consumable_value_and_used; update 3 pre-existing
tests whose asserted output shape changed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Rongsong Shen 2026-08-20 07:27:00 +00:00
parent 51063c1dc8
commit 9473361683
No known key found for this signature in database
GPG key ID: 5BCDAAE0123E9FE2
2 changed files with 250 additions and 48 deletions

View file

@ -732,11 +732,12 @@ static void test_info_worker_reports_resource_values(void)
captured = capture_dispatch(&sim, "info worker hostA");
TEST_ASSERT_NOT_NULL_MESSAGE(
strstr(captured, "resource mem: total=42.50 available=42.50"),
strstr(captured, "resource mem: value=42.50"),
"a worker's real numeric resource value must be displayed, not "
"the XCE_VAL_NUMERIC/Value_u_fvalue type-tag mismatch's 0.00 "
"(bug-1568)");
TEST_ASSERT_NULL_MESSAGE(strstr(captured, "total=0.00 available=0.00"),
"(bug-1568); a non-consumable resource (no flags set here) gets a "
"single value= line, not a value=/used= pair");
TEST_ASSERT_NULL_MESSAGE(strstr(captured, "value=0.00"),
"must not fall back to the zero default for a "
"genuinely-set numeric value");
@ -745,6 +746,82 @@ static void test_info_worker_reports_resource_values(void)
printf("test_info_worker_reports_resource_values: PASS\n");
}
/*
* New requirement (2026-08-20): a per-worker resource additionally flagged
* XCE_RESF_CONSUMABLE must report both value (available+inUse) and used
* (inUse); a non-consumable numeric resource keeps a single value= line
* (test_info_worker_reports_resource_values above covers that case).
*/
static void test_info_worker_reports_consumable_value_and_used(void)
{
xce_sched_sim_driver_t sim;
xce_core_event_t events[1];
xce_resource_t wire_resource;
xce_resource_t* r;
xce_worker_t wire_worker;
xce_worker_t* worker_ptrs[1];
xce_val_t val;
xce_name_val_t nv;
xce_name_val_t* nv_ptrs[1];
xce_val_t used_val;
xce_sched_worker_t* sw;
char* captured;
int rc;
memset(&sim, 0, sizeof(sim));
rc = xce_sched_core_init(&(sim.core));
TEST_ASSERT_EQUAL_INT(0, rc);
memset(&wire_resource, 0, sizeof(wire_resource));
wire_resource.name = "slots";
wire_resource.valtype = XCE_VAL_NUMERIC;
wire_resource.flags = XCE_RESF_CONSUMABLE;
r = makeResource(sim.core.resmgr, &wire_resource);
TEST_ASSERT_NOT_NULL(r);
memset(&val, 0, sizeof(val));
val.which = Value_u_fvalue;
val.u.fvalue = 5.0;
memset(&nv, 0, sizeof(nv));
nv.name = "slots";
nv.val = &val;
nv_ptrs[0] = &nv;
memset(&wire_worker, 0, sizeof(wire_worker));
wire_worker.name = "hostA";
wire_worker.status = 0;
wire_worker.nresvals_to_sched = 1;
wire_worker.resvals_to_sched = nv_ptrs;
worker_ptrs[0] = &wire_worker;
memset(events, 0, sizeof(events));
events[0].type = XCE_CORE_EVENT_WORKERS_PUSH;
events[0].u.workers_push.nworkers = 1;
events[0].u.workers_push.workers = worker_ptrs;
rc = xce_core_push_events(&(sim.core), events, 1);
TEST_ASSERT_EQUAL_INT(0, rc);
sw = sched_get_worker(&(sim.core), "hostA");
TEST_ASSERT_NOT_NULL(sw);
memset(&used_val, 0, sizeof(used_val));
used_val.which = Value_u_fvalue;
used_val.u.fvalue = 2.0;
zarray_put(&(sw->resInUse), r->idx, dup_val(&used_val));
captured = capture_dispatch(&sim, "info worker hostA");
TEST_ASSERT_NOT_NULL_MESSAGE(
strstr(captured, "resource slots: value=7.00 used=2.00"),
"a CONSUMABLE worker resource must report value=avail+used and "
"used=inUse");
free(captured);
printf("test_info_worker_reports_consumable_value_and_used: PASS\n");
}
/*
* bug-1590: repl_info_worker_one() forced EVERY resource value through the
* numeric "total=%.2f available=%.2f" format, silently coercing any
@ -893,7 +970,8 @@ static void test_info_resource_reports_string_value(void)
TEST_ASSERT_NOT_NULL_MESSAGE(
strstr(captured, "resource license_pool: desc=(none) "
"valtype=string flags=GLOBAL interval=0"),
"valtype=string ordtype=incr flags=GLOBAL "
"interval=0"),
"a GLOBAL resource's definition metadata must be printed "
"(bug-1593)");
TEST_ASSERT_NOT_NULL_MESSAGE(
@ -912,6 +990,71 @@ static void test_info_resource_reports_string_value(void)
printf("test_info_resource_reports_string_value: PASS\n");
}
/*
* New requirement (2026-08-20): a GLOBAL/SHARED resource additionally
* flagged XCE_RESF_CONSUMABLE must report both its value (capacity,
* available+inUse) and how much is currently in use, read from
* core->sharedInUse -- the cluster-wide mirror of repl_info_worker_one()'s
* resInUse-derived value/used split.
*/
static void test_info_resource_reports_consumable_value_and_used(void)
{
xce_sched_sim_driver_t sim;
xce_core_event_t events[1];
xce_resource_t wire_resource;
xce_resource_t* r;
xce_val_t avail_val;
xce_val_t used_val;
xce_resval_t rv;
xce_resval_t* rv_ptrs[1];
char* captured;
int rc;
memset(&sim, 0, sizeof(sim));
rc = xce_sched_core_init(&(sim.core));
TEST_ASSERT_EQUAL_INT(0, rc);
memset(&wire_resource, 0, sizeof(wire_resource));
wire_resource.name = "licenses";
wire_resource.valtype = XCE_VAL_NUMERIC;
wire_resource.flags = XCE_RESF_SHARED | XCE_RESF_CONSUMABLE;
r = makeResource(sim.core.resmgr, &wire_resource);
TEST_ASSERT_NOT_NULL(r);
memset(&avail_val, 0, sizeof(avail_val));
avail_val.which = Value_u_fvalue;
avail_val.u.fvalue = 8.0;
memset(&rv, 0, sizeof(rv));
rv.name = "licenses";
rv.val = &avail_val;
rv_ptrs[0] = &rv;
memset(events, 0, sizeof(events));
events[0].type = XCE_CORE_EVENT_RESVALS_FULL;
events[0].u.resvals_full.n = 1;
events[0].u.resvals_full.resvals = rv_ptrs;
rc = xce_core_push_events(&(sim.core), events, 1);
TEST_ASSERT_EQUAL_INT(0, rc);
memset(&used_val, 0, sizeof(used_val));
used_val.which = Value_u_fvalue;
used_val.u.fvalue = 3.0;
zarray_put(&(sim.core.sharedInUse), r->idx, dup_val(&used_val));
captured = capture_dispatch(&sim, "info resource licenses");
TEST_ASSERT_NOT_NULL_MESSAGE(
strstr(captured, "value=11.00 used=3.00"),
"a CONSUMABLE global resource must report value=avail+used and "
"used=inUse, sourced from core->sharedInUse");
free(captured);
printf("test_info_resource_reports_consumable_value_and_used: PASS\n");
}
/*
* bug-1593 (task 12.5): `info resource all` must list only resources
* flagged XCE_RESF_GLOBAL/XCE_RESF_SHARED -- a host-based resource (no
@ -1005,7 +1148,7 @@ static void test_info_resource_named_lookup_reports_host_based_note(void)
TEST_ASSERT_NOT_NULL_MESSAGE(
strstr(captured, "resource cpus: desc=(none) valtype=numeric "
"flags=(none) interval=0"),
"ordtype=incr flags=(none) interval=0"),
"a host-based resource's metadata must still be reported by a "
"named lookup (bug-1593)");
TEST_ASSERT_NOT_NULL_MESSAGE(
@ -1661,8 +1804,10 @@ int main(void)
RUN_TEST(test_info_job_unknown_reports_not_found);
RUN_TEST(test_info_queue_reports_status_and_queued_jobs);
RUN_TEST(test_info_worker_reports_resource_values);
RUN_TEST(test_info_worker_reports_consumable_value_and_used);
RUN_TEST(test_info_worker_reports_string_and_boolean_resource_values);
RUN_TEST(test_info_resource_reports_string_value);
RUN_TEST(test_info_resource_reports_consumable_value_and_used);
RUN_TEST(test_info_resource_all_lists_only_global_shared_resources);
RUN_TEST(test_info_resource_named_lookup_reports_host_based_note);
RUN_TEST(test_info_resource_all_reports_when_none_are_global_shared);