fix(scheduler-sim-diagnostics): correct usage display's resource classification (task 9)

repl_print_limit_usage()/repl_print_limit_usage_per_host() (repl_info.c)
passed vres->vres->name (a synthesized compound scope-instance name, e.g.
"limits2/u=rshen/q=xce/p=") to the byte-value classifier instead of the
limit's actual constrained resource name -- so a byte-valued limit's
usage amounts never got recognized as byte-valued, regardless of the
underlying formatting machinery already working correctly.

Fixed both call sites to pass the limit's own resname
(limit->val.resname / vres->limit->val.resname) instead. Added tests
proving human-readable rendering for both the cluster-wide/GLOBAL path
and a percentage-based per-host limit (Requirement 6 AC 6.4: a
percentage-of-byte-resource limit's resolved absolute amount is
human-formatted too).

Discovered and confirmed (implementer + independent reviewer): the
fix landed with zero pre-existing test failures, not the handful
design.md predicted -- those assertions used whole-number fixture
values with bare strstr() substring checks, which still match the
new, longer human-augmented output by coincidence of formatting.
Documented in tasks.md; task 10.1 will strengthen those assertions
to genuinely exercise the fix rather than pass by accident.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RLSNJhNoULvVcUhXEFafQC
This commit is contained in:
Rongsong Shen 2026-09-20 06:39:49 +00:00
parent 8477f677e4
commit 701901079e
No known key found for this signature in database
GPG key ID: 5BCDAAE0123E9FE2
3 changed files with 180 additions and 5 deletions

View file

@ -1352,8 +1352,17 @@ static int repl_print_limit_usage_per_host(xce_sched_sim_driver_t* sim,
* already gated existence for this worker; existence must not
* be re-derived from this read. */
/* Task 9 (Requirement 6.1, 6.3, 6.4, 6.5): classify by the
* limit's OWN constrained resource (vres->limit->val.resname,
* e.g. "mem"), never vres->vres->name (the usage instance's own
* synthesized vres name, e.g. "limit=<name>") -- the latter is
* never one of xce_is_bytes_valued_resource()'s five recognized
* names, so it always misclassifies a byte-valued limit's usage
* as non-byte-valued. vres->limit is an existing back-pointer,
* already dereferenced elsewhere in this file (repl_print_limit_
* usage()'s own `vres->limit != limit` filter). */
repl_format_consumable_value_and_used(
repl_current_units_mode(sim), vres->vres->name,
repl_current_units_mode(sim), vres->limit->val.resname,
cap_v->u.fvalue, used, value_str, sizeof(value_str),
used_str, sizeof(used_str));
@ -1478,8 +1487,15 @@ static void repl_print_limit_usage(xce_sched_sim_driver_t* sim,
* gated existence; existence must not be re-derived from this
* read. */
/* Task 9 (Requirement 6.1, 6.3, 6.4, 6.5): classify by the
* limit's OWN constrained resource (limit->val.resname, e.g.
* "mem"), never vres->vres->name (the usage instance's own
* synthesized vres name, e.g. "limit=<name>") -- see this same
* fix's doc comment in repl_print_limit_usage_per_host() above
* for the full rationale. `limit` is this function's own
* parameter, already in scope. */
repl_format_consumable_value_and_used(
repl_current_units_mode(sim), vres->vres->name,
repl_current_units_mode(sim), limit->val.resname,
cap_v->u.fvalue, used, value_str, sizeof(value_str),
used_str, sizeof(used_str));

View file

@ -1668,6 +1668,159 @@ test_info_limit_named_shows_no_active_usage_instance_when_host_scoped_vres_exist
"scoped_vres_exists_but_no_worker_populated: PASS\n");
}
/* ---------------------------------------------------------------------- */
/* Task 9 (Requirement 6.1, 6.3, 6.4, 6.5): repl_print_limit_usage()'s */
/* GLOBAL/SHARED path and repl_print_limit_usage_per_host()'s per-host */
/* path both classify a live usage instance's accounted/capacity amounts */
/* by the instance's own synthesized vres name (vres->vres->name, e.g. */
/* "limit=<name>") instead of the limit's own constrained resource */
/* (limit->val.resname / vres->limit->val.resname, "mem") -- */
/* xce_is_bytes_valued_resource() is therefore always asked about the */
/* wrong string and always returns false for a limit's usage instance, so */
/* a byte-valued limit's live accounted/capacity amounts never actually */
/* render human-readable even though the exact same limit's CONFIGURED- */
/* setting line (task 8.2) already does. These two tests prove the fix. */
/* ---------------------------------------------------------------------- */
/*
* Cluster-wide (GLOBAL/SHARED) path fix -- mirrors
* test_info_limit_named_shows_accounted_and_capacity_for_matched_and_
* charged_global_instance's exact fixture shape, substituting byte-scale
* capacity/used amounts (the same 5368709120.0/5000000000.0 pair
* test_info_limit_named_shows_byte_valued_amount_human_readable_under_
* default_units_mode and test_utils.c's own fractional-scaling test already
* establish as "5.00 GB"/"4.66 GB") for the pre-existing fixture's small
* 10.0/4.0 pair (too small to distinguish raw from human rendering in a
* reader-legible way). RED against today's code: vres->vres->name (e.g.
* "limit=byte_usage_limit") is never "mem", so repl_is_bytes_valued_
* resource() returns false and both amounts fall back to plain "%.2f" --
* neither "GB" string below appears.
*/
static void
test_info_limit_named_shows_global_usage_amounts_human_readable_for_byte_valued_limit(
void)
{
xce_sched_sim_driver_t sim;
xce_sched_plugin_t plugin;
xce_scheduler_t group_sched;
xce_limit_t* matched = NULL;
var limits_handle;
xce_vres_t* vres;
char* captured;
int rc;
memset(&sim, 0, sizeof(sim));
rc = xce_sched_core_init(&(sim.core));
TEST_ASSERT_EQUAL_INT(0, rc);
register_per_host_resource(&sim, "mem");
register_limit_plugin(&sim, &plugin, &group_sched);
add_configured_limit(&plugin, "byte_usage_limit");
limits_handle = limit_get_configured_limits(&(sim.core));
rc = key_find(limits_handle, (void*)"byte_usage_limit", (void**)&matched);
TEST_ASSERT_TRUE(rc > 0);
TEST_ASSERT_NOT_NULL(matched);
vres = instantiate_and_register_global_vres(&sim, &plugin, matched);
put_shared_fvalue(&(sim.core.sharedInst), vres->vres->idx, 5368709120.0);
put_shared_fvalue(&(sim.core.sharedInUse), vres->vres->idx, 5000000000.0);
captured = capture_info_limit(&sim, "byte_usage_limit");
TEST_ASSERT_NOT_NULL_MESSAGE(
strstr(captured, "capacity=5368709120.000000 (5.00 GB)"),
"Requirement 6.1/6.5: a byte-valued limit's live CAPACITY amount "
"must render human-readable, classified by the limit's OWN "
"constrained resource (limit->val.resname, 'mem') -- this fails "
"against today's buggy vres->vres->name classification, which "
"always prints the plain 'capacity=5368709120.00' fallback "
"instead");
TEST_ASSERT_NOT_NULL_MESSAGE(
strstr(captured, "accounted=5000000000.000000 (4.66 GB)"),
"Requirement 6.1/6.5: ... and its live ACCOUNTED amount too, using "
"the exact same classification fix");
free(captured);
printf(
"test_info_limit_named_shows_global_usage_amounts_human_readable_"
"for_byte_valued_limit: PASS\n");
}
/*
* Per-host path fix, doubling as Requirement 6.4's own proof: this
* fixture's limit is itself PERCENTAGE-based (add_configured_percent_
* limit(), val.percent=1 -- the exact shape task 3.2's own host-scoped
* fixtures already use), so a passing test here demonstrates that a limit
* expressed as a percentage of a byte-valued resource shows its RESOLVED
* ABSOLUTE per-host usage amounts (not the percentage itself) in
* human-readable form too. Mirrors test_info_limit_named_shows_separate_
* per_host_usage_lines_for_touched_hosts_and_none_for_untouched_host's
* exact fixture shape, substituting byte-scale capacity/used amounts for
* the pre-existing fixture's small 5.0/2.0 pair. RED against today's code:
* same vres->vres->name misclassification as the GLOBAL/SHARED test above.
*/
static void
test_info_limit_named_shows_per_host_usage_amounts_human_readable_for_percent_based_byte_valued_limit(
void)
{
xce_sched_sim_driver_t sim;
xce_sched_plugin_t plugin;
xce_scheduler_t group_sched;
xce_limit_t* matched = NULL;
var limits_handle;
xce_vres_t* vres;
xce_sched_worker_t* wA;
char* captured;
int rc;
memset(&sim, 0, sizeof(sim));
rc = xce_sched_core_init(&(sim.core));
TEST_ASSERT_EQUAL_INT(0, rc);
register_per_host_resource(&sim, "mem");
register_limit_plugin(&sim, &plugin, &group_sched);
add_configured_percent_limit(&plugin, "byte_host_usage_limit", "mem");
limits_handle = limit_get_configured_limits(&(sim.core));
rc = key_find(limits_handle, (void*)"byte_host_usage_limit",
(void**)&matched);
TEST_ASSERT_TRUE(rc > 0);
TEST_ASSERT_NOT_NULL(matched);
vres = instantiate_and_register_host_vres(&sim, &plugin, matched);
wA = build_bare_worker(&sim, "hostA");
put_shared_fvalue(&(wA->resvals), vres->vres->idx, 5368709120.0);
put_shared_fvalue(&(wA->resInUse), vres->vres->idx, 5000000000.0);
captured = capture_info_limit(&sim, "byte_host_usage_limit");
TEST_ASSERT_NOT_NULL_MESSAGE(
strstr(captured, "host=hostA"),
"sanity: hostA's populated capacity entry must still produce a "
"usage line");
TEST_ASSERT_NOT_NULL_MESSAGE(
strstr(captured, "capacity=5368709120.000000 (5.00 GB)"),
"Requirement 6.1/6.4/6.5: a percentage-based limit's per-host "
"RESOLVED ABSOLUTE capacity amount must render human-readable, "
"classified by the limit's OWN constrained resource "
"(vres->limit->val.resname, 'mem') -- this fails against today's "
"buggy vres->vres->name classification, which always prints the "
"plain 'capacity=5368709120.00' fallback instead");
TEST_ASSERT_NOT_NULL_MESSAGE(
strstr(captured, "accounted=5000000000.000000 (4.66 GB)"),
"Requirement 6.1/6.4/6.5: ... and its resolved absolute ACCOUNTED "
"amount too, not the percentage itself");
free(captured);
printf(
"test_info_limit_named_shows_per_host_usage_amounts_human_readable_"
"for_percent_based_byte_valued_limit: PASS\n");
}
/*
* Task 4 (Requirement Set 1, Req 4.1/4.2): the first tests in this file to
* drive `info limit <name>`/`info limit all` through the REAL repl_dispatch()
@ -3123,6 +3276,10 @@ int main(void)
test_info_limit_named_shows_accounted_zero_for_host_with_capacity_but_never_charged);
RUN_TEST(
test_info_limit_named_shows_no_active_usage_instance_when_host_scoped_vres_exists_but_no_worker_populated);
RUN_TEST(
test_info_limit_named_shows_global_usage_amounts_human_readable_for_byte_valued_limit);
RUN_TEST(
test_info_limit_named_shows_per_host_usage_amounts_human_readable_for_percent_based_byte_valued_limit);
RUN_TEST(
test_info_limit_dispatch_named_reaches_repl_info_limit_via_real_dispatch);
RUN_TEST(