feat(scheduler-sim-diagnostics): display per-host usage for host-scoped limits
repl_print_limit_usage_per_host() fans a single host-scoped xce_vres_t out across every worker with a populated capacity entry at that vres's shared resource index (w->resvals[idx]/w->resInUse[idx]), rather than constructing any per-host vres object -- matching design.md's (xce_vres_t, worker) pair cardinality model exactly. A worker with no populated capacity entry produces no line at all (not a fabricated zero); a worker with capacity but no charged usage shows accounted=0. Uses the corrected idx<0 + .caps-only bounds-check pattern task 3.1 established, avoiding bug-1824's latent imprecision. This closes out all of Requirement 3 (3.1-3.4). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RLSNJhNoULvVcUhXEFafQC
This commit is contained in:
parent
716abe121f
commit
4f60f148fb
3 changed files with 424 additions and 10 deletions
|
|
@ -1246,14 +1246,122 @@ static void repl_print_limit_host_scope_note_if_implicit(
|
|||
}
|
||||
|
||||
/*
|
||||
* repl_print_limit_usage - task 3.1, Requirement 1.4/2.1/2.2/2.3/3.3:
|
||||
* prints `limit`'s live accounted usage against its configured capacity,
|
||||
* one line per distinct GLOBAL/SHARED xce_vres_t instance found in
|
||||
* limit_get_usage_instances() whose `->limit` pointer-equals `limit`.
|
||||
* A host-scoped instance (`vres->vres` not flagged GLOBAL/SHARED) is
|
||||
* task 3.2's job and is silently skipped here, per design.md's own
|
||||
* per-instance filter ("skip -- do not display -- any per-host-scoped
|
||||
* vres in this task").
|
||||
* repl_print_limit_usage_per_host - task 3.2, Requirement 1.4/2.1/2.2/2.3/
|
||||
* 3.1/3.2/3.4: for ONE host-scoped xce_vres_t (`vres->vres` NOT flagged
|
||||
* GLOBAL/SHARED), prints one usage line per worker that has a populated
|
||||
* capacity entry at `vres->vres->idx` in its OWN resvals zarray --
|
||||
* design.md's Data Models section: "a displayed 'instance' is therefore a
|
||||
* (xce_vres_t, worker) pair when host-scoped." There is exactly ONE
|
||||
* xce_vres_t per matched (user, queue, project) combination regardless of
|
||||
* host-scoping (build_vres_name(), xcelimit.c, never encodes host) -- this
|
||||
* function does NOT create a vres per host; it fans a SINGLE vres out over
|
||||
* every worker by reading each worker's own resvals/resInUse at the SAME
|
||||
* vres->vres->idx.
|
||||
*
|
||||
* Existence-of-instance is gated ONLY on a worker's CAPACITY entry
|
||||
* (w->resvals[idx]) being present -- never on its in-use entry
|
||||
* (w->resInUse[idx]), the same existence-vs-zero-usage distinction
|
||||
* repl_print_limit_usage()'s own GLOBAL/SHARED branch below establishes,
|
||||
* applied per worker here: a worker with a populated capacity but no
|
||||
* in-use entry yet gets a genuine accounted=0 line; a worker with no
|
||||
* populated capacity entry at all (this limit's shadow resource has never
|
||||
* been written for that host -- the host is configured but untouched) gets
|
||||
* no line at all, never a fabricated zero (Requirement 2.2 at per-host
|
||||
* granularity).
|
||||
*
|
||||
* Bounds safety mirrors repl_print_limit_usage()'s own corrected pattern
|
||||
* (bug-1824 is the still-unfixed older mistake in repl_info_resource_one(),
|
||||
* NOT repeated here): relies on zarray_get()/zarray_get_ex()'s own
|
||||
* `.caps`-based bound rather than a `.count`-based pre-check (imprecise for
|
||||
* a sparsely-populated zarray) -- no manual upper-bound pre-check is
|
||||
* performed at all, matching the GLOBAL/SHARED branch's own omission of
|
||||
* one.
|
||||
*
|
||||
* Returns the number of lines printed (0 if no worker has a populated
|
||||
* capacity entry at this vres's idx).
|
||||
*/
|
||||
static int repl_print_limit_usage_per_host(xce_sched_sim_driver_t* sim,
|
||||
xce_vres_t* vres)
|
||||
{
|
||||
iterator_t it;
|
||||
int rc;
|
||||
int n_shown = 0;
|
||||
|
||||
if (vres->vres->idx < 0) {
|
||||
/* No capacity index allocated at all -- this vres has never
|
||||
* actually been evaluated to a usable capacity on any host; do not
|
||||
* fabricate a display for it (Requirement 2.2). */
|
||||
return 0;
|
||||
}
|
||||
|
||||
rc = iter_make(&it, sim->core.workers);
|
||||
if (rc < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
xce_sched_worker_t* w = NULL;
|
||||
xce_val_t* cap_v = NULL;
|
||||
|
||||
rc = iter_next(&it, (void**)&w);
|
||||
if ((rc < 0) || (rc == RTTI_ITER_NO_DATA) || (w == NULL)) {
|
||||
break;
|
||||
}
|
||||
|
||||
cap_v = (xce_val_t*)zarray_get(&(w->resvals), vres->vres->idx);
|
||||
if ((cap_v == NULL) || (cap_v->which != Value_u_fvalue)) {
|
||||
/* This worker's capacity entry for this vres does not exist --
|
||||
* the limit has never been evaluated against a job on this
|
||||
* host. Must not appear as a line at all (Observable: "a third
|
||||
* configured-but-untouched host shows no line at all"). */
|
||||
continue;
|
||||
}
|
||||
|
||||
{
|
||||
xce_val_t* used_v = NULL;
|
||||
double used = 0.0;
|
||||
char value_str[80];
|
||||
char used_str[80];
|
||||
|
||||
used_v = (xce_val_t*)zarray_get(&(w->resInUse), vres->vres->idx);
|
||||
if ((used_v != NULL) && (used_v->which == Value_u_fvalue)) {
|
||||
used = used_v->u.fvalue;
|
||||
}
|
||||
/* used_v == NULL (or wrong-typed) here is genuine zero usage on
|
||||
* this host, never "no instance" -- the capacity check above
|
||||
* already gated existence for this worker; existence must not
|
||||
* be re-derived from this read. */
|
||||
|
||||
repl_format_consumable_value_and_used(
|
||||
repl_current_units_mode(sim), vres->vres->name,
|
||||
cap_v->u.fvalue, used, value_str, sizeof(value_str),
|
||||
used_str, sizeof(used_str));
|
||||
|
||||
/* Requirement 3.4: label with BOTH the scope values already
|
||||
* encoded in the vres's own name (user/queue/project, via
|
||||
* build_vres_name()) AND this worker's own hostname, so each
|
||||
* per-host line is distinguishable from every other. */
|
||||
fprintf(stdout,
|
||||
"[sim] usage %s host=%s: accounted=%s capacity=%s\n",
|
||||
vres->vres->name, w->name, used_str, value_str);
|
||||
}
|
||||
|
||||
n_shown++;
|
||||
}
|
||||
iter_destroy(&it);
|
||||
|
||||
return n_shown;
|
||||
}
|
||||
|
||||
/*
|
||||
* repl_print_limit_usage - task 3.1/3.2, Requirement 1.4/2.1/2.2/2.3/3.1/
|
||||
* 3.2/3.3/3.4: prints `limit`'s live accounted usage against its configured
|
||||
* capacity, one section per distinct xce_vres_t instance found in
|
||||
* limit_get_usage_instances() whose `->limit` pointer-equals `limit`. A
|
||||
* GLOBAL/SHARED vres prints exactly one line (this function's own inline
|
||||
* logic below); a host-scoped vres (`vres->vres` not flagged GLOBAL/
|
||||
* SHARED) fans out into zero or more per-host lines via
|
||||
* repl_print_limit_usage_per_host() above (task 3.2).
|
||||
*
|
||||
* Existence-of-instance is gated ONLY on the matched vres's CAPACITY entry
|
||||
* (core.sharedInst[idx]) being present -- never on the in-use entry
|
||||
|
|
@ -1300,7 +1408,13 @@ static void repl_print_limit_usage(xce_sched_sim_driver_t* sim,
|
|||
}
|
||||
|
||||
if ((vres->vres->flags & (XCE_RESF_GLOBAL | XCE_RESF_SHARED)) == 0) {
|
||||
/* Host-scoped instance -- task 3.2's branch, not this one. */
|
||||
/* Host-scoped instance (task 3.2): fan out over every worker
|
||||
* with a populated capacity entry at this vres's shared idx --
|
||||
* see repl_print_limit_usage_per_host()'s own doc comment.
|
||||
* There is still exactly ONE xce_vres_t here; the fan-out
|
||||
* happens entirely inside that helper by reading each worker's
|
||||
* OWN resvals/resInUse zarrays. */
|
||||
n_shown += repl_print_limit_usage_per_host(sim, vres);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -598,6 +598,97 @@ static void put_shared_fvalue(zarray_t* array, int idx, double val)
|
|||
TEST_ASSERT_TRUE(rc >= 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* instantiate_and_register_host_vres - task 3.2's own fixture, mirroring
|
||||
* instantiate_and_register_global_vres() above but for a HOST-SCOPED
|
||||
* xce_vres_t: drives the real, already-linked instantiate_limit()
|
||||
* (xcelimit.c) against `matched_limit` the same way, then key_add()s it
|
||||
* into `plugin`'s privdata->instances.
|
||||
*
|
||||
* `matched_limit` must be configured the way add_configured_percent_limit()
|
||||
* shapes it (percent-based, on a resource register_per_host_resource()
|
||||
* registered as non-GLOBAL/non-SHARED) so is_host_based_limit() returns > 0
|
||||
* and instantiate_limit()'s internal `shared` local stays 0 -- add_vres()
|
||||
* then flags the resulting vres->vres XCE_RESF_DEFAULT_HOST (never GLOBAL/
|
||||
* SHARED), the exact case task 3.2's own scope covers.
|
||||
*/
|
||||
static xce_vres_t* instantiate_and_register_host_vres(
|
||||
xce_sched_sim_driver_t* sim, xce_sched_plugin_t* plugin,
|
||||
xce_limit_t* matched_limit)
|
||||
{
|
||||
limit_plugin_data_t* privdata = (limit_plugin_data_t*)plugin->data;
|
||||
xce_vres_t* vres = NULL;
|
||||
int rc;
|
||||
|
||||
rc = instantiate_limit(&vres, sim->core.resmgr, matched_limit, "", "",
|
||||
"");
|
||||
TEST_ASSERT_TRUE(rc >= 0);
|
||||
TEST_ASSERT_NOT_NULL(vres);
|
||||
TEST_ASSERT_NOT_NULL(vres->vres);
|
||||
TEST_ASSERT_TRUE(vres->vres->idx >= 0);
|
||||
TEST_ASSERT_TRUE_MESSAGE(
|
||||
(vres->vres->flags & (XCE_RESF_GLOBAL | XCE_RESF_SHARED)) == 0,
|
||||
"fixture sanity: this helper only ever produces a host-scoped "
|
||||
"(non-GLOBAL/non-SHARED) vres -- a GLOBAL/SHARED vres would mean "
|
||||
"the fixture's own limit shape drifted from "
|
||||
"add_configured_percent_limit()'s implicit-host-scope contract");
|
||||
|
||||
rc = key_add(privdata->instances, (void*)vres->vres->name, (void*)vres);
|
||||
TEST_ASSERT_TRUE(rc >= 0);
|
||||
|
||||
return vres;
|
||||
}
|
||||
|
||||
/*
|
||||
* build_bare_worker - registers a real xce_sched_worker_t named `hostname`
|
||||
* into `sim`'s core via the real XCE_CORE_EVENT_WORKERS_PUSH path
|
||||
* (core_events.c's core_upsert_worker()/core_build_worker(), the exact
|
||||
* production path test_repl_resource_table.c's own
|
||||
* build_worker_with_one_numeric_resource() already drives) -- this
|
||||
* zarray_init()s a real resvals/resInUse pair on the new worker, each with
|
||||
* a real killer (kill_sched_resval, stubbed above), so this file's own
|
||||
* put_shared_fvalue() can safely zarray_put() directly into a returned
|
||||
* worker's OWN resvals/resInUse afterward (task 3.2's fan-out reads
|
||||
* exactly those two zarrays per worker) without this fixture needing to
|
||||
* drive the real put_resvals()/update_limit_res_value() (resource.c,
|
||||
* deliberately not linked into this TU, see this file's own header
|
||||
* comment). No wire resvals are carried on the push itself
|
||||
* (nresvals_to_sched=0) -- this fixture only needs the worker to exist with
|
||||
* its own zarrays ready for a direct put_shared_fvalue() write at the
|
||||
* limit's own shadow-resource idx.
|
||||
*/
|
||||
static xce_sched_worker_t* build_bare_worker(xce_sched_sim_driver_t* sim,
|
||||
const char* hostname)
|
||||
{
|
||||
xce_worker_t* wire_worker;
|
||||
xce_worker_t* worker_ptrs[1];
|
||||
xce_core_event_t events[1];
|
||||
int rc;
|
||||
|
||||
wire_worker = (xce_worker_t*)calloc(1, sizeof(*wire_worker));
|
||||
TEST_ASSERT_NOT_NULL(wire_worker);
|
||||
wire_worker->name = (char*)hostname;
|
||||
wire_worker->status = 0;
|
||||
wire_worker->nresvals_to_sched = 0;
|
||||
wire_worker->resvals_to_sched = NULL;
|
||||
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);
|
||||
|
||||
{
|
||||
xce_sched_worker_t* w
|
||||
= sched_get_worker(&(sim->core), (char*)hostname);
|
||||
TEST_ASSERT_NOT_NULL(w);
|
||||
return w;
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Tests */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
|
@ -1200,6 +1291,207 @@ test_info_limit_named_shows_accounted_zero_for_matched_but_never_charged_instanc
|
|||
"never_charged_instance: PASS\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Task 3.2's own central Observable (Requirement 3.1, 3.2, 3.4): a
|
||||
* host-scoped limit matched against jobs on TWO distinct hosts shows TWO
|
||||
* SEPARATE usage lines, each labeled with its own host -- and a THIRD
|
||||
* configured-but-untouched host (registered as a real worker, but never
|
||||
* given a populated capacity entry at this limit's shadow-resource idx)
|
||||
* shows no line at all, proving existence is gated on a per-worker
|
||||
* capacity read, not on the worker merely existing.
|
||||
*/
|
||||
static void
|
||||
test_info_limit_named_shows_separate_per_host_usage_lines_for_touched_hosts_and_none_for_untouched_host(
|
||||
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;
|
||||
xce_sched_worker_t* wB;
|
||||
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, "host_usage_limit", "mem");
|
||||
|
||||
limits_handle = limit_get_configured_limits(&(sim.core));
|
||||
rc = key_find(limits_handle, (void*)"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");
|
||||
wB = build_bare_worker(&sim, "hostB");
|
||||
/* hostC is registered as a real worker but deliberately never given a
|
||||
* populated capacity entry below -- configured, but untouched by this
|
||||
* limit. */
|
||||
(void)build_bare_worker(&sim, "hostC");
|
||||
|
||||
put_shared_fvalue(&(wA->resvals), vres->vres->idx, 5.0);
|
||||
put_shared_fvalue(&(wA->resInUse), vres->vres->idx, 2.0);
|
||||
|
||||
put_shared_fvalue(&(wB->resvals), vres->vres->idx, 5.0);
|
||||
put_shared_fvalue(&(wB->resInUse), vres->vres->idx, 3.0);
|
||||
|
||||
captured = capture_info_limit(&sim, "host_usage_limit");
|
||||
|
||||
TEST_ASSERT_NOT_NULL_MESSAGE(
|
||||
strstr(captured, "host=hostA"),
|
||||
"Requirement 3.2/3.4: a host-scoped limit matched on hostA must "
|
||||
"show a usage line labeled with hostA");
|
||||
TEST_ASSERT_NOT_NULL_MESSAGE(
|
||||
strstr(captured, "host=hostB"),
|
||||
"Requirement 3.2/3.4: a host-scoped limit matched on hostB must "
|
||||
"show a SEPARATE usage line labeled with hostB");
|
||||
TEST_ASSERT_NULL_MESSAGE(
|
||||
strstr(captured, "host=hostC"),
|
||||
"Observable: a third configured-but-untouched host must show no "
|
||||
"line at all, not a fabricated zero");
|
||||
TEST_ASSERT_NOT_NULL_MESSAGE(
|
||||
strstr(captured, "accounted=2.00"),
|
||||
"Requirement 2.1: hostA's own accounted usage must be shown");
|
||||
TEST_ASSERT_NOT_NULL_MESSAGE(
|
||||
strstr(captured, "accounted=3.00"),
|
||||
"Requirement 2.1: hostB's own accounted usage must be shown, "
|
||||
"distinct from hostA's");
|
||||
|
||||
free(captured);
|
||||
|
||||
printf("test_info_limit_named_shows_separate_per_host_usage_lines_for_"
|
||||
"touched_hosts_and_none_for_untouched_host: PASS\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Task 3.2's own existence-vs-zero-usage distinction, applied per host
|
||||
* (mirrors task 3.1's central Observable #3 for the GLOBAL/SHARED case):
|
||||
* a worker with a genuinely populated CAPACITY entry at this limit's
|
||||
* shadow-resource idx, but no in-use entry (never charged), must display a
|
||||
* genuine accounted=0 line for that host -- not omit the host entirely.
|
||||
*/
|
||||
static void
|
||||
test_info_limit_named_shows_accounted_zero_for_host_with_capacity_but_never_charged(
|
||||
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, "host_uncharged_limit", "mem");
|
||||
|
||||
limits_handle = limit_get_configured_limits(&(sim.core));
|
||||
rc = key_find(limits_handle, (void*)"host_uncharged_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, 5.0);
|
||||
/* Deliberately no put_shared_fvalue() into wA->resInUse -- a genuinely
|
||||
* populated capacity entry, but nothing charged against it yet. */
|
||||
|
||||
captured = capture_info_limit(&sim, "host_uncharged_limit");
|
||||
|
||||
TEST_ASSERT_NOT_NULL_MESSAGE(
|
||||
strstr(captured, "host=hostA"),
|
||||
"hostA has a genuinely populated capacity entry and must appear as "
|
||||
"a line, even though nothing has been charged against it yet");
|
||||
TEST_ASSERT_NOT_NULL_MESSAGE(
|
||||
strstr(captured, "accounted=0.00"),
|
||||
"the existence-vs-zero-usage distinction applies per host too: a "
|
||||
"populated capacity entry with an absent in-use entry must display "
|
||||
"a genuine accounted=0, not omit the host");
|
||||
|
||||
free(captured);
|
||||
|
||||
printf("test_info_limit_named_shows_accounted_zero_for_host_with_"
|
||||
"capacity_but_never_charged: PASS\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Requirement 2.2 applied to the host-scoped case as a whole: a host-scoped
|
||||
* xce_vres_t that genuinely exists (instantiated, real capacity idx
|
||||
* allocated) but for which NO worker has ever been given a populated
|
||||
* capacity entry must report the same "no active usage instance yet"
|
||||
* message the GLOBAL/SHARED case reports for an unmatched limit -- proving
|
||||
* repl_print_limit_usage_per_host()'s own zero-lines-printed return value
|
||||
* correctly threads through to repl_print_limit_usage()'s outer n_shown
|
||||
* fallback rather than silently printing nothing with no explanation.
|
||||
*/
|
||||
static void
|
||||
test_info_limit_named_shows_no_active_usage_instance_when_host_scoped_vres_exists_but_no_worker_populated(
|
||||
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;
|
||||
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, "host_untouched_limit", "mem");
|
||||
|
||||
limits_handle = limit_get_configured_limits(&(sim.core));
|
||||
rc = key_find(limits_handle, (void*)"host_untouched_limit",
|
||||
(void**)&matched);
|
||||
TEST_ASSERT_TRUE(rc > 0);
|
||||
TEST_ASSERT_NOT_NULL(matched);
|
||||
|
||||
(void)instantiate_and_register_host_vres(&sim, &plugin, matched);
|
||||
/* A worker exists, but its capacity entry at this vres's idx is
|
||||
* deliberately never populated -- the limit's shadow resource has
|
||||
* never actually been written for any host. */
|
||||
(void)build_bare_worker(&sim, "hostA");
|
||||
|
||||
captured = capture_info_limit(&sim, "host_untouched_limit");
|
||||
|
||||
TEST_ASSERT_NOT_NULL_MESSAGE(
|
||||
strstr(captured, "no active usage instance yet"),
|
||||
"Requirement 2.2: a host-scoped vres that exists but has no worker "
|
||||
"with a populated capacity entry must report no active usage "
|
||||
"instance, not a fabricated zero and not silence with no "
|
||||
"explanation");
|
||||
TEST_ASSERT_NULL_MESSAGE(
|
||||
strstr(captured, "host=hostA"),
|
||||
"hostA has no populated capacity entry and must not appear as a "
|
||||
"line");
|
||||
|
||||
free(captured);
|
||||
|
||||
printf("test_info_limit_named_shows_no_active_usage_instance_when_host_"
|
||||
"scoped_vres_exists_but_no_worker_populated: PASS\n");
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
UNITY_BEGIN();
|
||||
|
|
@ -1230,5 +1522,11 @@ int main(void)
|
|||
test_info_limit_named_shows_no_active_usage_instance_for_never_matched_limit);
|
||||
RUN_TEST(
|
||||
test_info_limit_named_shows_accounted_zero_for_matched_but_never_charged_instance);
|
||||
RUN_TEST(
|
||||
test_info_limit_named_shows_separate_per_host_usage_lines_for_touched_hosts_and_none_for_untouched_host);
|
||||
RUN_TEST(
|
||||
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);
|
||||
return UNITY_END();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue