feat(scheduler-sim-diagnostics): implement info limit name/all resolution

repl_info_limit() (repl_info.c, not yet wired into repl_cmd_info() -- that's
task 4) resolves "all" vs a specific name against limit_get_configured_limits():
a NULL/empty handle on the all path reports "no limits configured" (Req 1.7);
a NULL handle or key_find() miss on the named path reports "no such limit
'<name>'" (Req 1.3) and never collapses into the all-only message. New
white-box test_repl_limit_table.c exercises both paths directly, including a
dedicated regression guard for the NULL-scoping rule.

Making repl_info.c genuinely call limit_get_configured_limits() broke the link
for ~24 other white-box test files that #include repl_info.c without also
linking plugins/limit.c -- fixed with the same link-satisfying-stub idiom this
file family already uses elsewhere (all return NULL, verified behavior-
preserving since none of these fixtures register the limit plugin).

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-17 09:53:59 +00:00
parent b79a547a1e
commit d3df8fb29f
No known key found for this signature in database
GPG key ID: 5BCDAAE0123E9FE2
28 changed files with 1098 additions and 1 deletions

View file

@ -9,7 +9,7 @@
- _Boundary: Limit Plugin Accessor_
- [ ] 2. Core: Limit lookup and configured-setting display
- [ ] 2.1 Implement name/all resolution with correct absence messaging
- [x] 2.1 Implement name/all resolution with correct absence messaging
- New white-box test file `test_repl_limit_table.c` created (sibling of `test_repl_resource_table.c`, own `#include` set covering `plugins/limit.c` and `resource.c` for real — not stubbed — per `design.md`'s build-wiring risk note citing bug-1762's precedent)
- `repl_info_limit(sim, arg)`: `arg == "all"` iterates `limit_get_configured_limits()`; `NULL`/empty prints "no limits configured" (Requirement 1.7); `arg != "all"` does a `key_find()` by name (not a scan) on the same handle, printing "no such limit '<name>'" (Requirement 1.3) for a `NULL` handle or a miss — a `NULL` handle on this path is never treated as "no limits configured," matching that message's own `all`-only scoping
- Wired as a direct call for now (`repl_dispatch()`/`repl_cmd_info()` wiring itself deferred to task 4); tests in this task call `repl_info_limit()` directly, not through `repl_dispatch()`
@ -64,3 +64,4 @@ No `(P)` markers are used anywhere in this plan. Tasks 2.1–2.3 and 3.1–3.2 a
## Implementation Notes
- **Task 1**: `test_limit_plugin.c`'s pre-existing `fixture_init()` never populated `core->plugins` (`plugin_register()` is stubbed to a no-op in that white-box TU). Closed with two new test-local fixture helpers that hand-build a real `core->plugins` kvmgr and `key_add()` the plugin under its real `"xce_sched_limit"` name — necessary to exercise the accessors' real `key_find()` path, not a workaround. `test_repl_limit_table.c` (tasks 2.1+) is a *different* white-box TU with its own include set (per design.md's build-wiring risk note) — it should link real `plugin.c`/`core.c` machinery where `register_limit()`/`xce_sched_core_init()` actually populate `core->plugins`, so it likely does NOT need this same hand-built-kvmgr workaround; confirm this when starting 2.1 rather than assuming the same gap exists there.
- **Task 2.1**: Making `repl_info.c` genuinely call `limit_get_configured_limits()` broke the link for ~24 pre-existing white-box test files that `#include "../src/repl_info.c"` without also linking `plugins/limit.c` — this codebase's white-box test convention means any new cross-file call from an included production file ripples to every file that includes the caller but not the callee. Fixed with an identical 5-line link-satisfying stub (`return NULL`) added to each, matching the established "duplicate, don't share" stub idiom already used throughout this file family; verified behavior-preserving since none of those 24 fixtures register the limit plugin (the real function would also return `NULL` there). **Task 3 (which calls `limit_get_usage_instances()`) will very likely hit the identical ripple across an overlapping or identical file set — expect it, and apply the same fix pattern rather than treating it as a surprise.**

View file

@ -1154,6 +1154,84 @@ static void repl_info_resource(xce_sched_sim_driver_t* sim, const char* arg)
}
}
/*
* repl_info_limit - `info limit <name|all>` name/all resolution
* (scheduler-sim-diagnostics spec, Requirement Set 1, task 2.1, Req 1.3,
* 1.7, 4.1, 4.2). THIS task implements only the name/all resolution and
* the two absence messages -- printing a matched limit's configured
* setting (fmt_limit(), Req 1.1/1.2/1.5) is task 2.2's job, and printing
* its live usage instances (Req 2.1-2.3, 3.1-3.4) is task 3's job. Not yet
* wired into repl_cmd_info() (task 4 adds that branch) -- static and
* currently uncalled from production code; exercised directly by
* test_repl_limit_table.c per this task's own scope.
*
* Requirement 1.7's "no limits configured" message is reserved for the
* `all` path specifically -- its own acceptance criterion scopes it to
* "when an operator requests information for all limits". On the named
* path (`arg != "all"`), a NULL limit_get_configured_limits() handle (the
* limit plugin was never registered -- a simulation with nothing
* configured never registers it) reports Requirement 1.3's "no such limit
* '<name>'" instead: absence of ANY configuration and absence of THIS ONE
* name collapse to the same "no such limit" message on the named path,
* per design.md's REPL Limit Info Command Responsibilities and Error
* Handling's "Limit plugin not registered/initialized" category. A NULL
* handle must never fall through to "no limits configured" on this path.
*/
static void repl_info_limit(xce_sched_sim_driver_t* sim, const char* arg)
{
var limits = limit_get_configured_limits(&(sim->core));
if (strcmp(arg, "all") == 0) {
iterator_t it;
xce_limit_t* limit = NULL;
int rc;
int n_shown = 0;
if (limits == NULL) {
fprintf(stdout, "[sim] no limits configured\n");
return;
}
rc = iter_make(&it, limits);
if (rc < 0) {
fprintf(stdout, "[sim] no limits configured\n");
return;
}
for (;;) {
rc = iter_next(&it, (void**)&limit);
if ((rc < 0) || (rc == RTTI_ITER_NO_DATA) || (limit == NULL)) {
break;
}
/* task 2.2 prints this limit's configured setting here
* (fmt_limit()); task 3 adds its live usage. This task's own
* scope stops at proving resolution reaches a genuine match. */
n_shown++;
}
iter_destroy(&it);
if (n_shown == 0) {
fprintf(stdout, "[sim] no limits configured\n");
}
return;
}
{
xce_limit_t* match = NULL;
int rc = (limits != NULL)
? key_find(limits, (void*)arg, (void**)&match)
: -1;
if ((limits == NULL) || (rc <= 0) || (match == NULL)) {
fprintf(stdout, "[sim] info limit: no such limit '%s'\n", arg);
return;
}
/* task 2.2 prints the matched limit's configured setting here
* (fmt_limit()); task 3 adds its live usage. This task's own scope
* stops at proving resolution reaches a genuine match. */
}
}
/*
* repl_info_summary - AC 22's "info summary": "Quick overview: N_jobs (M
* pending, K running), N_workers (M online), N_queues, N_resources." Four

View file

@ -1103,6 +1103,40 @@ sched_repl_resource_table_test = executable(
dependencies: [scheduler_test_deps, libedit_dep],
install: false)
# Contract test for the interactive simulation REPL's `info limit <name|all>`
# name/all resolution and absence messaging (scheduler-sim-diagnostics spec,
# Requirement Set 1, task 2.1, Requirements 1.3, 1.7, 4.1, 4.2). Split into
# its own file rather than added to test_repl_resource_table.c, per
# design.md's own explicit build-wiring risk note: that file's white-box
# #include set deliberately does NOT link plugins/limit.c or resource.c
# ("resource.c, not linked here"), and this task needs the REAL
# plugins/limit.c (for the real limit_get_configured_limits()/limit_init()/
# limit_update_config() its own fixtures and repl_info_limit() call) --
# not stubbed, the same bug-1762 precedent design.md cites for a different
# scheduler-sim-repl-verbosity command that hit the identical undefined-
# reference link-failure class. Same white-box #include pattern as
# sched_repl_resource_table_test above (core.c, core_clock.c, core_events.c,
# core_session.c, decision.c, plugin.c, plugins/builtin_fcfs.c, recording.c,
# recording_session.c, sim.c, sim_loop.c, sim_picker.c, sim_record.c,
# sim_verify.c, snapshot.c/snapshot_wire.c/snapshot_load.c, repl.c,
# repl_fmt.c, repl_rollup.c, repl_break.c, repl_info.c, repl_params.c) PLUS
# the new ../src/plugins/limit.c under test. task 2.1's own scope never
# reads live usage/resource accounting (that's task 3), so resource.c is
# NOT linked here -- the same minimal link-satisfying stubs
# test_limit_plugin.c already establishes for limit.c's unused
# limit_job_election()/limit_prepare_allocation() hook bodies
# (reset_sched_obj()/get_resvals()/put_resvals()) are reused verbatim,
# confirmed sufficient by actually attempting the build and reading the
# resulting undefined-reference errors rather than guessing blindly.
# `repl_info_limit()` is not yet wired into repl_cmd_info() (task 4) -- every
# test in this file calls it directly, not through repl_dispatch().
sched_repl_limit_table_test = executable(
'sched_repl_limit_table_test',
['test_repl_limit_table.c'],
include_directories:[incdir],
dependencies: [scheduler_test_deps, libedit_dep],
install: false)
# Contract test for the interactive simulation REPL's Help & Breakpoint
# Discoverability component (scheduler-sim-repl-verbosity spec, task 9.1,
# Requirements 7.1-7.4): `help`'s listing groups commands into four labeled
@ -1828,6 +1862,9 @@ test('scheduler repl breakpoints inspection test',
test('scheduler repl resource table test',
sched_repl_resource_table_test, suite: 'scheduler',
env: ['ASAN_OPTIONS=detect_leaks=0'])
test('scheduler repl limit table test',
sched_repl_limit_table_test, suite: 'scheduler',
env: ['ASAN_OPTIONS=detect_leaks=0'])
test('scheduler repl help test',
sched_repl_help_test, suite: 'scheduler',
env: ['ASAN_OPTIONS=detect_leaks=0'])

View file

@ -165,6 +165,21 @@ void kill_sched_user(void* arg) { (void)arg; }
void kill_sched_project(void* arg) { (void)arg; }
void kill_sched_resval(xce_val_t* val) { (void)val; }
/* repl_info.c (scheduler-sim-diagnostics spec, task 2.1) now calls
* limit_get_configured_limits() (plugins/limit.c, not part of this TU) to
* resolve `info limit`'s name/all argument -- link-satisfying stub only,
* same rationale as kill_sched_job()/kill_sched_resval() above; this
* file's own fixtures never register the limit plugin, so NULL
* (limit_get_configured_limits()'s own documented "plugin absent" return)
* is also the behaviorally correct answer here, not just a link
* placeholder. repl_info_limit() itself is not yet wired into
* repl_cmd_info() (task 4), so no test in this file can reach it anyway. */
var limit_get_configured_limits(xce_sched_core_t* core)
{
(void)core;
return NULL;
}
int sched_reconcile_job_resource_usage(xce_sched_core_t* c,
xce_job_account_t* a,
xce_job_rusages_t* r)

View file

@ -101,6 +101,21 @@ void kill_sched_user(void* arg) { (void)arg; }
void kill_sched_project(void* arg) { (void)arg; }
void kill_sched_resval(xce_val_t* val) { (void)val; }
/* repl_info.c (scheduler-sim-diagnostics spec, task 2.1) now calls
* limit_get_configured_limits() (plugins/limit.c, not part of this TU) to
* resolve `info limit`'s name/all argument -- link-satisfying stub only,
* same rationale as kill_sched_job()/kill_sched_resval() above; this
* file's own fixtures never register the limit plugin, so NULL
* (limit_get_configured_limits()'s own documented "plugin absent" return)
* is also the behaviorally correct answer here, not just a link
* placeholder. repl_info_limit() itself is not yet wired into
* repl_cmd_info() (task 4), so no test in this file can reach it anyway. */
var limit_get_configured_limits(xce_sched_core_t* core)
{
(void)core;
return NULL;
}
/* resource-accounting.md's reconciliation (resource.c, not linked here --
* this file only #includes core_events.c). core_events.c's
* XCE_CORE_EVENT_JOB_RUSAGE handler calls this whenever job->accounts !=

View file

@ -150,6 +150,21 @@ void kill_sched_user(void* arg) { (void)arg; }
void kill_sched_project(void* arg) { (void)arg; }
void kill_sched_resval(xce_val_t* val) { (void)val; }
/* repl_info.c (scheduler-sim-diagnostics spec, task 2.1) now calls
* limit_get_configured_limits() (plugins/limit.c, not part of this TU) to
* resolve `info limit`'s name/all argument -- link-satisfying stub only,
* same rationale as kill_sched_job()/kill_sched_resval() above; this
* file's own fixtures never register the limit plugin, so NULL
* (limit_get_configured_limits()'s own documented "plugin absent" return)
* is also the behaviorally correct answer here, not just a link
* placeholder. repl_info_limit() itself is not yet wired into
* repl_cmd_info() (task 4), so no test in this file can reach it anyway. */
var limit_get_configured_limits(xce_sched_core_t* core)
{
(void)core;
return NULL;
}
/* resource-accounting.md's reconciliation (resource.c, not linked here --
* this file only #includes core_events.c). core_events.c's
* XCE_CORE_EVENT_JOB_RUSAGE handler calls this whenever job->accounts !=

View file

@ -118,6 +118,21 @@ void kill_sched_user(void* arg) { (void)arg; }
void kill_sched_project(void* arg) { (void)arg; }
void kill_sched_resval(xce_val_t* val) { (void)val; }
/* repl_info.c (scheduler-sim-diagnostics spec, task 2.1) now calls
* limit_get_configured_limits() (plugins/limit.c, not part of this TU) to
* resolve `info limit`'s name/all argument -- link-satisfying stub only,
* same rationale as kill_sched_job()/kill_sched_resval() above; this
* file's own fixtures never register the limit plugin, so NULL
* (limit_get_configured_limits()'s own documented "plugin absent" return)
* is also the behaviorally correct answer here, not just a link
* placeholder. repl_info_limit() itself is not yet wired into
* repl_cmd_info() (task 4), so no test in this file can reach it anyway. */
var limit_get_configured_limits(xce_sched_core_t* core)
{
(void)core;
return NULL;
}
/* resource-accounting.md's reconciliation (resource.c, not linked here --
* this file only #includes core_events.c). core_events.c's
* XCE_CORE_EVENT_JOB_RUSAGE handler calls this whenever job->accounts !=

View file

@ -115,6 +115,21 @@ void kill_sched_user(void* arg) { (void)arg; }
void kill_sched_project(void* arg) { (void)arg; }
void kill_sched_resval(xce_val_t* val) { (void)val; }
/* repl_info.c (scheduler-sim-diagnostics spec, task 2.1) now calls
* limit_get_configured_limits() (plugins/limit.c, not part of this TU) to
* resolve `info limit`'s name/all argument -- link-satisfying stub only,
* same rationale as kill_sched_job()/kill_sched_resval() above; this
* file's own fixtures never register the limit plugin, so NULL
* (limit_get_configured_limits()'s own documented "plugin absent" return)
* is also the behaviorally correct answer here, not just a link
* placeholder. repl_info_limit() itself is not yet wired into
* repl_cmd_info() (task 4), so no test in this file can reach it anyway. */
var limit_get_configured_limits(xce_sched_core_t* core)
{
(void)core;
return NULL;
}
/* resource-accounting.md's reconciliation (resource.c, not linked here --
* this file only #includes core_events.c). core_events.c's
* XCE_CORE_EVENT_JOB_RUSAGE handler calls this whenever job->accounts !=

View file

@ -110,6 +110,21 @@ void kill_sched_user(void* arg) { (void)arg; }
void kill_sched_project(void* arg) { (void)arg; }
void kill_sched_resval(xce_val_t* val) { (void)val; }
/* repl_info.c (scheduler-sim-diagnostics spec, task 2.1) now calls
* limit_get_configured_limits() (plugins/limit.c, not part of this TU) to
* resolve `info limit`'s name/all argument -- link-satisfying stub only,
* same rationale as kill_sched_job()/kill_sched_resval() above; this
* file's own fixtures never register the limit plugin, so NULL
* (limit_get_configured_limits()'s own documented "plugin absent" return)
* is also the behaviorally correct answer here, not just a link
* placeholder. repl_info_limit() itself is not yet wired into
* repl_cmd_info() (task 4), so no test in this file can reach it anyway. */
var limit_get_configured_limits(xce_sched_core_t* core)
{
(void)core;
return NULL;
}
/* resource-accounting.md's reconciliation (resource.c, not linked here --
* this file only #includes core_events.c). core_events.c's
* XCE_CORE_EVENT_JOB_RUSAGE handler calls this whenever job->accounts !=

View file

@ -0,0 +1,621 @@
/*
* test_repl_limit_table.c - contract test for the interactive simulation
* REPL's `info limit <name|all>` name/all resolution and absence messaging
* (scheduler-sim-diagnostics spec, Requirement Set 1, task 2.1, Req 1.3,
* 1.7, 4.1, 4.2).
*
* New white-box test file, sibling of test_repl_resource_table.c -- kept
* separate rather than added to that file, per design.md's own explicit
* build-wiring risk note (Implementation Notes, "REPL Limit Info Command"):
* test_repl_resource_table.c white-box #includes repl_info.c but
* deliberately does NOT link plugins/limit.c or resource.c ("resource.c,
* not linked here"). This file needs the REAL plugins/limit.c (for the
* real limit_get_configured_limits()/limit_init()/limit_update_config()
* repl_info_limit() and this file's own fixtures call) -- not stubbed,
* same bug-1762 precedent design.md cites for a different scheduler-sim-
* repl-verbosity command that hit the identical class of undefined-
* reference link failure.
*
* `repl_info_limit()` is NOT yet wired into repl_cmd_info() (that's task
* 4) -- every test below calls it directly, not through repl_dispatch().
*
* White-box #include set: identical to test_repl_resource_table.c's own
* (core.c, core_clock.c, core_events.c, core_session.c, decision.c,
* plugin.c, plugins/builtin_fcfs.c, recording.c, recording_session.c,
* repl.c, repl_fmt.c, repl_rollup.c, repl_break.c, repl_info.c,
* repl_params.c, sim.c, sim_loop.c, sim_picker.c, sim_record.c,
* sim_verify.c, snapshot.c, snapshot_load.c, snapshot_wire.c) PLUS the new
* ../src/plugins/limit.c under test. task 2.1's own scope never reads live
* usage/resource accounting (that's task 3), so resource.c is NOT linked
* here either -- the same minimal link-satisfying stubs
* test_limit_plugin.c already establishes for limit.c's unused
* limit_job_election()/limit_prepare_allocation() hook bodies
* (reset_sched_obj()/get_resvals()/put_resvals(), none of which task 2.1's
* own code path ever calls) are reused verbatim here, confirmed sufficient
* by actually attempting the build and reading the resulting undefined-
* reference errors rather than guessing blindly, per design.md's own risk
* note.
*
* Fixture strategy: unlike test_limit_plugin.c's own TU (which links
* neither core.c nor plugin.c, so its fixture_init()/
* fixture_register_plugin_in_core() hand-build a standalone core->plugins
* kvmgr), this file links the REAL ../src/core.c, so xce_sched_core_init()
* already creates a real, usable sim->core.plugins kvmgr on its own --
* register_limit_plugin() (below) key_add()s a real, limit_init()'d
* xce_sched_plugin_t directly into THAT kvmgr, and add_configured_limit()
* drives the real limit_update_config() (plugins/limit.c) against it,
* exactly the machinery Implementation Notes' "task 1" note predicted this
* file would have available and confirms here.
*/
#include <errno.h>
#include <limits.h>
#include <sys/wait.h>
#include <stdatomic.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <unity/unity.h>
#include "controller.capnp.h"
#include "group.h"
#include "kvmgr.h"
#include "scheduler.h"
#include "xce/types.h"
#include "xcelimit.h"
#include "xstring.h"
/* Pull in the real functions under test into this TU (white-box #include,
* same convention as test_repl_resource_table.c/test_repl_round_rollup.c/
* test_repl_event_echo.c). */
#include "../src/core.c"
#include "../src/core_clock.c"
#include "../src/core_events.c"
#include "../src/core_session.c"
#include "../src/decision.c"
#include "../src/plugin.c"
#include "../src/plugins/builtin_fcfs.c"
#include "../src/plugins/limit.c"
#include "../src/recording.c"
#include "../src/recording_session.c"
#include "../src/repl.c"
#include "../src/repl_fmt.c"
#include "../src/repl_rollup.c"
#include "../src/repl_break.c"
#include "../src/repl_info.c"
#include "../src/repl_params.c"
#include "../src/sim.c"
#include "../src/sim_loop.c"
#include "../src/sim_picker.c" /* bug-1567: sched_sim_driver_run() now calls sim_bootstrap_picker() (sim_loop.c-cap sibling) as an extern -- undefined reference at link time otherwise */
#include "../src/sim_record.c"
#include "../src/sim_verify.c"
#include "../src/snapshot.c"
#include "../src/snapshot_load.c"
#include "../src/snapshot_wire.c"
void kill_sched_job(void* arg) { (void)arg; }
void kill_sched_queue(void* arg) { (void)arg; }
void kill_sched_worker(void* arg) { (void)arg; }
void kill_sched_user(void* arg) { (void)arg; }
void kill_sched_project(void* arg) { (void)arg; }
void kill_sched_resval(xce_val_t* val) { (void)val; }
/* resource-accounting.md's reconciliation (resource.c, not linked here --
* this file only #includes core_events.c, same as test_repl_resource_table.c).
* core_events.c's XCE_CORE_EVENT_JOB_RUSAGE handler calls this whenever
* job->accounts != NULL; link-satisfying stub only, same rationale as every
* other stub in this block. */
int sched_reconcile_job_resource_usage(xce_sched_core_t* c,
xce_job_account_t* a,
xce_job_rusages_t* r)
{
(void)c; (void)a; (void)r; return 0;
}
void sched_worker_release_host_ctx(xce_sched_worker_t* w) { (void)w; }
int sched_fill_limit_requests(xce_sched_alloc_req_t* alloc_req,
xlist_t* limits, xlist_t* rusages, int nhosts,
int nslots)
{
(void)alloc_req;
(void)limits;
(void)rusages;
(void)nhosts;
(void)nslots;
return 0;
}
int sched_account_jobs(xce_sched_core_t* core)
{
(void)core;
return 0;
}
/* Real reimplementation of schedobj.c's sched_resolve_job_picker -- same
* copy test_repl_resource_table.c/test_repl_execution_control.c/
* test_sim_alt_events.c/etc. each carry (schedobj.c is not linked here). */
int sched_resolve_job_picker(xce_sched_core_t* core, xce_sched_plugin_t** out)
{
xce_sched_plugin_t* plugin = NULL;
int rc = 0;
if ((core == NULL) || (out == NULL)) {
return -EINVAL;
}
*out = NULL;
if (core->job_pick_plugin == NULL) {
return -EINVAL;
}
lock(core->plugins, RTTI_LOCK_READ);
rc = key_find(core->plugins, core->job_pick_plugin, (void**)&plugin);
unlock(core->plugins);
if (rc <= 0) {
return (rc < 0) ? rc : -ENOENT;
}
if ((plugin == NULL) || (plugin->picker_iface == NULL)
|| (plugin->picker_iface->next_job == NULL)
|| (plugin->picker_iface->begin_session == NULL)
|| (plugin->picker_iface->end_session == NULL)
|| (plugin->picker_iface->on_dispatch == NULL)
|| (plugin->picker_iface->on_pend == NULL)) {
return -EINVAL;
}
*out = plugin;
return 0;
}
/* plugins/limit.c's limit_job_election()/limit_prepare_allocation() (never
* exercised by any test in this file -- task 2.1's own scope never touches
* usage/accounting) reference reset_sched_obj() (../src/schedobj.c) and
* get_resvals()/put_resvals() (../src/resource.c), neither of which is part
* of this white-box TU. Stubbed as no-ops purely to satisfy the linker --
* same pattern test_limit_plugin.c already establishes for the identical
* symbols. */
void reset_sched_obj(xce_sched_obj_t* obj)
{
(void)obj;
}
int get_resvals(zarray_t* array, int nres, int* idxs, float* vals)
{
(void)array;
(void)nres;
(void)idxs;
(void)vals;
return 0;
}
int put_resvals(zarray_t* array, int nres, int* idxs, float* vals)
{
(void)array;
(void)nres;
(void)idxs;
(void)vals;
return 0;
}
void setUp(void) { return; }
void tearDown(void) { return; }
/* ---------------------------------------------------------------------- */
/* stdout-capture helper -- duplicated from test_repl_resource_table.c */
/* (same dup()/dup2()-around-STDOUT_FILENO technique that file's own */
/* header comment establishes), per this file family's own "duplicate, */
/* don't share" convention. */
/* ---------------------------------------------------------------------- */
static char* capture_stdout_around(void (*fn)(void))
{
char tmp[] = "/tmp/xce_repllimtbl_stdoutcap_XXXXXX";
int fd = mkstemp(tmp);
int saved_stdout;
off_t len;
char* buf;
TEST_ASSERT_TRUE_MESSAGE(fd >= 0, "mkstemp for stdout capture must "
"succeed");
fflush(stdout);
saved_stdout = dup(STDOUT_FILENO);
TEST_ASSERT_TRUE_MESSAGE(saved_stdout >= 0, "dup(STDOUT_FILENO) must "
"succeed");
TEST_ASSERT_TRUE_MESSAGE(dup2(fd, STDOUT_FILENO) >= 0,
"dup2 redirect of STDOUT_FILENO must succeed");
fn();
fflush(stdout);
dup2(saved_stdout, STDOUT_FILENO);
close(saved_stdout);
len = lseek(fd, 0, SEEK_CUR);
TEST_ASSERT_TRUE(len >= 0);
buf = (char*)calloc(1, (size_t)len + 1);
TEST_ASSERT_NOT_NULL(buf);
TEST_ASSERT_TRUE(lseek(fd, 0, SEEK_SET) == 0);
if (len > 0) {
ssize_t nread = read(fd, buf, (size_t)len);
TEST_ASSERT_TRUE(nread == len);
}
close(fd);
unlink(tmp);
return buf;
}
/* Captures the output of calling repl_info_limit(sim, arg) DIRECTLY --
* task 2.1's own scope calls it directly, not through repl_dispatch()
* (that wiring is task 4's job). */
static xce_sched_sim_driver_t* g_direct_sim;
static const char* g_direct_arg;
static void run_info_limit_for_capture(void)
{
repl_info_limit(g_direct_sim, g_direct_arg);
}
static char* capture_info_limit(xce_sched_sim_driver_t* sim, const char* arg)
{
g_direct_sim = sim;
g_direct_arg = arg;
return capture_stdout_around(run_info_limit_for_capture);
}
/* ---------------------------------------------------------------------- */
/* Limit configuration fixture helpers */
/* ---------------------------------------------------------------------- */
/*
* register_limit_plugin - registers a real, limit_init()'d xce_sched_plugin_t
* directly into `sim`'s own core->plugins kvmgr (xce_sched_core_init() --
* already called on `sim` by every test below -- creates that kvmgr for
* real, since this TU links ../src/core.c), so
* limit_get_configured_limits(&(sim->core))'s key_find(core->plugins,
* "xce_sched_limit", ...) genuinely finds it -- the exact real lookup path
* repl_info_limit() drives.
*
* `plugin`/`group_sched` are caller-owned (stack) storage, not static
* globals, so each test gets its own independent fixture. `group_sched` is
* a throwaway xce_scheduler_t existing purely so limit_update_config()
* (called separately by add_configured_limit() below) has real group
* managers to resolve each consumer's "all"-group fallback from
* (build_limit()/build_consumer(), xcelimit.c) -- the built xce_limit_t/
* xce_group_t values it produces are owned by plugin->data's own
* privdata->limits kvmgr, not by group_sched, so group_sched need not be
* (and is not) sim's own core. Same minimal group-manager technique
* test_limit_plugin.c's own fixture_init() already establishes
* (groupmgr_init() x4), reused here rather than re-derived, per
* Implementation Notes' own "task 1" note.
*/
static void register_limit_plugin(xce_sched_sim_driver_t* sim,
xce_sched_plugin_t* plugin,
xce_scheduler_t* group_sched)
{
int rc;
memset(group_sched, 0, sizeof(*group_sched));
groupmgr_init(&(group_sched->core.ugmgr), 4, 4);
groupmgr_init(&(group_sched->core.qgmgr), 4, 4);
groupmgr_init(&(group_sched->core.pgmgr), 4, 4);
groupmgr_init(&(group_sched->core.hgmgr), 4, 4);
TEST_ASSERT_NOT_NULL(group_sched->core.ugmgr);
TEST_ASSERT_NOT_NULL(group_sched->core.qgmgr);
TEST_ASSERT_NOT_NULL(group_sched->core.pgmgr);
TEST_ASSERT_NOT_NULL(group_sched->core.hgmgr);
memset(plugin, 0, sizeof(*plugin));
plugin->name = "xce_sched_limit";
plugin->sched = group_sched;
rc = limit_init(plugin);
TEST_ASSERT_EQUAL_INT(0, rc);
TEST_ASSERT_NOT_NULL(plugin->data);
rc = key_add(sim->core.plugins, plugin->name, (void*)plugin);
TEST_ASSERT_TRUE(rc >= 0);
}
/* A minimal, heap-allocated xce_limit_config_t -- identical shape to
* test_limit_plugin.c's own make_limit_config()/free_limit_config()
* (duplicated here per this file family's own "duplicate, don't share"
* convention): no per-consumer groups, so build_limit()'s build_consumer()
* falls back to get_group(mgr, "all") for every consumer. `name` is
* expected to be a string literal (build_limit() strdup()s it). */
static xce_limit_config_t* make_limit_config(const char* name)
{
xce_limit_config_t* cfg = (xce_limit_config_t*)calloc(1, sizeof(*cfg));
xce_limit_val_t* val = (xce_limit_val_t*)calloc(1, sizeof(*val));
TEST_ASSERT_NOT_NULL(cfg);
TEST_ASSERT_NOT_NULL(val);
val->resname = "mem";
val->percent = 0;
val->val = 10.0;
cfg->name = (char*)name;
cfg->val = val;
return cfg;
}
static void free_limit_config(xce_limit_config_t* cfg)
{
FREEUP(cfg->val);
FREEUP(cfg);
}
/* Drives the real limit_update_config() (plugins/limit.c) to configure ONE
* limit named `name` on `plugin` -- the exact production entry point a
* scheduler config update reaches this plugin through, not a hand-rolled
* xce_limit_t. */
static void add_configured_limit(xce_sched_plugin_t* plugin, const char* name)
{
xce_limit_config_t* limits[1];
xce_conf4sched_t config;
int rc;
limits[0] = make_limit_config(name);
memset(&config, 0, sizeof(config));
config.nlimits = 1;
config.limits = limits;
rc = limit_update_config(plugin, &config);
TEST_ASSERT_EQUAL_INT(0, rc);
free_limit_config(limits[0]);
}
/* ---------------------------------------------------------------------- */
/* Tests */
/* ---------------------------------------------------------------------- */
/*
* Requirement 1.7: `info limit all` against a fixture with zero configured
* limits (the limit plugin was never registered at all -- the realistic
* "nothing configured" scenario per design.md's Error Handling) must
* report that no limits are configured.
*/
static void
test_info_limit_all_reports_no_limits_configured_when_plugin_never_registered(
void)
{
xce_sched_sim_driver_t sim;
char* captured;
int rc;
memset(&sim, 0, sizeof(sim));
rc = xce_sched_core_init(&(sim.core));
TEST_ASSERT_EQUAL_INT(0, rc);
captured = capture_info_limit(&sim, "all");
TEST_ASSERT_NOT_NULL_MESSAGE(
strstr(captured, "no limits configured"),
"Requirement 1.7: 'info limit all' against a fixture with zero "
"configured limits must report that no limits are configured");
free(captured);
printf("test_info_limit_all_reports_no_limits_configured_when_plugin_"
"never_registered: PASS\n");
}
/*
* Requirement 1.7 / design.md's Error Handling section: a REGISTERED
* plugin with zero configured limits (privdata->limits is a real, non-NULL,
* empty kvmgr) must ALSO collapse to "no limits configured" on the `all`
* path -- not an empty listing with no explanation.
*/
static void
test_info_limit_all_reports_no_limits_configured_when_plugin_registered_with_zero_limits(
void)
{
xce_sched_sim_driver_t sim;
xce_sched_plugin_t plugin;
xce_scheduler_t group_sched;
char* captured;
int rc;
memset(&sim, 0, sizeof(sim));
rc = xce_sched_core_init(&(sim.core));
TEST_ASSERT_EQUAL_INT(0, rc);
register_limit_plugin(&sim, &plugin, &group_sched);
/* Deliberately no add_configured_limit() call -- plugin registered,
* privdata->limits real but empty. */
captured = capture_info_limit(&sim, "all");
TEST_ASSERT_NOT_NULL_MESSAGE(
strstr(captured, "no limits configured"),
"a registered plugin with zero configured limits must also report "
"'no limits configured' on the 'all' path");
free(captured);
printf("test_info_limit_all_reports_no_limits_configured_when_plugin_"
"registered_with_zero_limits: PASS\n");
}
/*
* Positive-path proof for the `all` resolution: once at least one limit is
* genuinely configured, the Requirement 1.7 message must NOT appear --
* proves the all-path iteration reaches the real, non-empty handle rather
* than misfiring the empty-case message unconditionally.
*/
static void
test_info_limit_all_does_not_report_no_limits_configured_when_limits_are_configured(
void)
{
xce_sched_sim_driver_t sim;
xce_sched_plugin_t plugin;
xce_scheduler_t group_sched;
char* captured;
int rc;
memset(&sim, 0, sizeof(sim));
rc = xce_sched_core_init(&(sim.core));
TEST_ASSERT_EQUAL_INT(0, rc);
register_limit_plugin(&sim, &plugin, &group_sched);
add_configured_limit(&plugin, "ug1_slots");
captured = capture_info_limit(&sim, "all");
TEST_ASSERT_NULL_MESSAGE(
strstr(captured, "no limits configured"),
"'info limit all' must NOT report 'no limits configured' once at "
"least one limit is genuinely configured");
free(captured);
printf("test_info_limit_all_does_not_report_no_limits_configured_when_"
"limits_are_configured: PASS\n");
}
/*
* Requirement 1.3 (this task's own Observable): a named lookup for a limit
* name that is NOT configured, against a fixture with OTHER limits
* configured, must report "no such limit" -- and must never report
* Requirement 1.7's all-only message.
*/
static void
test_info_limit_named_reports_no_such_limit_for_unconfigured_name_against_fixture_with_other_limits(
void)
{
xce_sched_sim_driver_t sim;
xce_sched_plugin_t plugin;
xce_scheduler_t group_sched;
char* captured;
int rc;
memset(&sim, 0, sizeof(sim));
rc = xce_sched_core_init(&(sim.core));
TEST_ASSERT_EQUAL_INT(0, rc);
register_limit_plugin(&sim, &plugin, &group_sched);
add_configured_limit(&plugin, "ug1_slots");
captured = capture_info_limit(&sim, "does_not_exist");
TEST_ASSERT_NOT_NULL_MESSAGE(
strstr(captured, "no such limit 'does_not_exist'"),
"Requirement 1.3: a named lookup for an unconfigured name, against "
"a fixture with other limits configured, must report 'no such "
"limit'");
TEST_ASSERT_NULL_MESSAGE(
strstr(captured, "no limits configured"),
"Requirement 1.7's message is reserved for the 'all' path -- a "
"named-lookup miss must never say 'no limits configured'");
free(captured);
printf("test_info_limit_named_reports_no_such_limit_for_unconfigured_"
"name_against_fixture_with_other_limits: PASS\n");
}
/*
* THE central scoping-regression guard (design.md's own explicit
* correction, called out by this task's brief): a NULL
* limit_get_configured_limits() handle on the NAMED path (the limit plugin
* was never registered at all) must report Requirement 1.3's "no such
* limit '<name>'" -- and must NEVER fall through to Requirement 1.7's
* all-only "no limits configured" message, even though both conditions
* stem from the identical underlying NULL handle.
*/
static void
test_info_limit_named_reports_no_such_limit_when_plugin_never_registered_not_no_limits_configured(
void)
{
xce_sched_sim_driver_t sim;
char* captured;
int rc;
memset(&sim, 0, sizeof(sim));
rc = xce_sched_core_init(&(sim.core));
TEST_ASSERT_EQUAL_INT(0, rc);
captured = capture_info_limit(&sim, "foo");
TEST_ASSERT_NOT_NULL_MESSAGE(
strstr(captured, "no such limit 'foo'"),
"a NULL limit_get_configured_limits() handle on the NAMED path "
"(plugin never registered) must report 'no such limit', never "
"Requirement 1.7's all-only message");
TEST_ASSERT_NULL_MESSAGE(
strstr(captured, "no limits configured"),
"a NULL handle on the named path must never be treated as 'no "
"limits configured' -- that message is exclusively the 'all' "
"path's, per its own acceptance criterion's scoping");
free(captured);
printf("test_info_limit_named_reports_no_such_limit_when_plugin_never_"
"registered_not_no_limits_configured: PASS\n");
}
/*
* Positive-path proof for the named-lookup resolution: a name that IS
* genuinely configured must never trigger the "no such limit" message --
* proves key_find() resolves a real hit, not a false miss (would fail if
* the resolution logic were broken or reversed).
*/
static void
test_info_limit_named_does_not_report_no_such_limit_for_configured_name(void)
{
xce_sched_sim_driver_t sim;
xce_sched_plugin_t plugin;
xce_scheduler_t group_sched;
char* captured;
int rc;
memset(&sim, 0, sizeof(sim));
rc = xce_sched_core_init(&(sim.core));
TEST_ASSERT_EQUAL_INT(0, rc);
register_limit_plugin(&sim, &plugin, &group_sched);
add_configured_limit(&plugin, "ug1_slots");
captured = capture_info_limit(&sim, "ug1_slots");
TEST_ASSERT_NULL_MESSAGE(
strstr(captured, "no such limit"),
"a named lookup for a limit that genuinely IS configured must "
"never report 'no such limit'");
free(captured);
printf("test_info_limit_named_does_not_report_no_such_limit_for_"
"configured_name: PASS\n");
}
int main(void)
{
UNITY_BEGIN();
RUN_TEST(
test_info_limit_all_reports_no_limits_configured_when_plugin_never_registered);
RUN_TEST(
test_info_limit_all_reports_no_limits_configured_when_plugin_registered_with_zero_limits);
RUN_TEST(
test_info_limit_all_does_not_report_no_limits_configured_when_limits_are_configured);
RUN_TEST(
test_info_limit_named_reports_no_such_limit_for_unconfigured_name_against_fixture_with_other_limits);
RUN_TEST(
test_info_limit_named_reports_no_such_limit_when_plugin_never_registered_not_no_limits_configured);
RUN_TEST(
test_info_limit_named_does_not_report_no_such_limit_for_configured_name);
return UNITY_END();
}

View file

@ -114,6 +114,21 @@ void kill_sched_user(void* arg) { (void)arg; }
void kill_sched_project(void* arg) { (void)arg; }
void kill_sched_resval(xce_val_t* val) { (void)val; }
/* repl_info.c (scheduler-sim-diagnostics spec, task 2.1) now calls
* limit_get_configured_limits() (plugins/limit.c, not part of this TU) to
* resolve `info limit`'s name/all argument -- link-satisfying stub only,
* same rationale as kill_sched_job()/kill_sched_resval() above; this
* file's own fixtures never register the limit plugin, so NULL
* (limit_get_configured_limits()'s own documented "plugin absent" return)
* is also the behaviorally correct answer here, not just a link
* placeholder. repl_info_limit() itself is not yet wired into
* repl_cmd_info() (task 4), so no test in this file can reach it anyway. */
var limit_get_configured_limits(xce_sched_core_t* core)
{
(void)core;
return NULL;
}
/* Link-satisfying stubs -- same rationale as every sibling in this file
* family (see test_repl_execution_control.c's own copies for the full
* per-stub doc comments). */

View file

@ -81,6 +81,21 @@ void kill_sched_user(void* arg) { (void)arg; }
void kill_sched_project(void* arg) { (void)arg; }
void kill_sched_resval(xce_val_t* val) { (void)val; }
/* repl_info.c (scheduler-sim-diagnostics spec, task 2.1) now calls
* limit_get_configured_limits() (plugins/limit.c, not part of this TU) to
* resolve `info limit`'s name/all argument -- link-satisfying stub only,
* same rationale as kill_sched_job()/kill_sched_resval() above; this
* file's own fixtures never register the limit plugin, so NULL
* (limit_get_configured_limits()'s own documented "plugin absent" return)
* is also the behaviorally correct answer here, not just a link
* placeholder. repl_info_limit() itself is not yet wired into
* repl_cmd_info() (task 4), so no test in this file can reach it anyway. */
var limit_get_configured_limits(xce_sched_core_t* core)
{
(void)core;
return NULL;
}
/* resource-accounting.md's reconciliation (resource.c, not linked here --
* this file only #includes core_events.c). core_events.c's
* XCE_CORE_EVENT_JOB_RUSAGE handler calls this whenever job->accounts !=

View file

@ -77,6 +77,21 @@ void kill_sched_user(void* arg) { (void)arg; }
void kill_sched_project(void* arg) { (void)arg; }
void kill_sched_resval(xce_val_t* val) { (void)val; }
/* repl_info.c (scheduler-sim-diagnostics spec, task 2.1) now calls
* limit_get_configured_limits() (plugins/limit.c, not part of this TU) to
* resolve `info limit`'s name/all argument -- link-satisfying stub only,
* same rationale as kill_sched_job()/kill_sched_resval() above; this
* file's own fixtures never register the limit plugin, so NULL
* (limit_get_configured_limits()'s own documented "plugin absent" return)
* is also the behaviorally correct answer here, not just a link
* placeholder. repl_info_limit() itself is not yet wired into
* repl_cmd_info() (task 4), so no test in this file can reach it anyway. */
var limit_get_configured_limits(xce_sched_core_t* core)
{
(void)core;
return NULL;
}
/* resource-accounting.md's reconciliation (resource.c, not linked here --
* this file only #includes core_events.c). core_events.c's
* XCE_CORE_EVENT_JOB_RUSAGE handler calls this whenever job->accounts !=

View file

@ -90,6 +90,21 @@ void kill_sched_user(void* arg) { (void)arg; }
void kill_sched_project(void* arg) { (void)arg; }
void kill_sched_resval(xce_val_t* val) { (void)val; }
/* repl_info.c (scheduler-sim-diagnostics spec, task 2.1) now calls
* limit_get_configured_limits() (plugins/limit.c, not part of this TU) to
* resolve `info limit`'s name/all argument -- link-satisfying stub only,
* same rationale as kill_sched_job()/kill_sched_resval() above; this
* file's own fixtures never register the limit plugin, so NULL
* (limit_get_configured_limits()'s own documented "plugin absent" return)
* is also the behaviorally correct answer here, not just a link
* placeholder. repl_info_limit() itself is not yet wired into
* repl_cmd_info() (task 4), so no test in this file can reach it anyway. */
var limit_get_configured_limits(xce_sched_core_t* core)
{
(void)core;
return NULL;
}
/* resource-accounting.md's reconciliation (resource.c, not linked here --
* this file only #includes core_events.c). core_events.c's
* XCE_CORE_EVENT_JOB_RUSAGE handler calls this whenever job->accounts !=

View file

@ -131,6 +131,21 @@ void kill_sched_user(void* arg) { (void)arg; }
void kill_sched_project(void* arg) { (void)arg; }
void kill_sched_resval(xce_val_t* val) { (void)val; }
/* repl_info.c (scheduler-sim-diagnostics spec, task 2.1) now calls
* limit_get_configured_limits() (plugins/limit.c, not part of this TU) to
* resolve `info limit`'s name/all argument -- link-satisfying stub only,
* same rationale as kill_sched_job()/kill_sched_resval() above; this
* file's own fixtures never register the limit plugin, so NULL
* (limit_get_configured_limits()'s own documented "plugin absent" return)
* is also the behaviorally correct answer here, not just a link
* placeholder. repl_info_limit() itself is not yet wired into
* repl_cmd_info() (task 4), so no test in this file can reach it anyway. */
var limit_get_configured_limits(xce_sched_core_t* core)
{
(void)core;
return NULL;
}
/* resource-accounting.md's reconciliation (resource.c, not linked here --
* this file only #includes core_events.c). core_events.c's
* XCE_CORE_EVENT_JOB_RUSAGE handler calls this whenever job->accounts !=

View file

@ -108,6 +108,21 @@ void kill_sched_user(void* arg) { (void)arg; }
void kill_sched_project(void* arg) { (void)arg; }
void kill_sched_resval(xce_val_t* val) { (void)val; }
/* repl_info.c (scheduler-sim-diagnostics spec, task 2.1) now calls
* limit_get_configured_limits() (plugins/limit.c, not part of this TU) to
* resolve `info limit`'s name/all argument -- link-satisfying stub only,
* same rationale as kill_sched_job()/kill_sched_resval() above; this
* file's own fixtures never register the limit plugin, so NULL
* (limit_get_configured_limits()'s own documented "plugin absent" return)
* is also the behaviorally correct answer here, not just a link
* placeholder. repl_info_limit() itself is not yet wired into
* repl_cmd_info() (task 4), so no test in this file can reach it anyway. */
var limit_get_configured_limits(xce_sched_core_t* core)
{
(void)core;
return NULL;
}
void sched_worker_release_host_ctx(xce_sched_worker_t* w) { (void)w; }
/* resource-accounting.md's reconciliation (resource.c, not linked here --

View file

@ -193,6 +193,21 @@ void kill_sched_user(void* arg) { (void)arg; }
void kill_sched_project(void* arg) { (void)arg; }
void kill_sched_resval(xce_val_t* val) { (void)val; }
/* repl_info.c (scheduler-sim-diagnostics spec, task 2.1) now calls
* limit_get_configured_limits() (plugins/limit.c, not part of this TU) to
* resolve `info limit`'s name/all argument -- link-satisfying stub only,
* same rationale as kill_sched_job()/kill_sched_resval() above; this
* file's own fixtures never register the limit plugin, so NULL
* (limit_get_configured_limits()'s own documented "plugin absent" return)
* is also the behaviorally correct answer here, not just a link
* placeholder. repl_info_limit() itself is not yet wired into
* repl_cmd_info() (task 4), so no test in this file can reach it anyway. */
var limit_get_configured_limits(xce_sched_core_t* core)
{
(void)core;
return NULL;
}
/* xce_sched_driver_on_decision()'s (driver.c) publish-side linker
* dependencies -- never actually invoked: this file never registers a
* decision callback. Same rationale test_sim_resource_contention.c's own

View file

@ -216,6 +216,21 @@ void kill_sched_user(void* arg) { (void)arg; }
void kill_sched_project(void* arg) { (void)arg; }
void kill_sched_resval(xce_val_t* val) { (void)val; }
/* repl_info.c (scheduler-sim-diagnostics spec, task 2.1) now calls
* limit_get_configured_limits() (plugins/limit.c, not part of this TU) to
* resolve `info limit`'s name/all argument -- link-satisfying stub only,
* same rationale as kill_sched_job()/kill_sched_resval() above; this
* file's own fixtures never register the limit plugin, so NULL
* (limit_get_configured_limits()'s own documented "plugin absent" return)
* is also the behaviorally correct answer here, not just a link
* placeholder. repl_info_limit() itself is not yet wired into
* repl_cmd_info() (task 4), so no test in this file can reach it anyway. */
var limit_get_configured_limits(xce_sched_core_t* core)
{
(void)core;
return NULL;
}
/* resource.c's sched_try_alloc_on_host_()'s own link-time dependency --
* never actually invoked (this file calls sched_check_host_satisfy()/
* sched_charge_account()/sched_commit_job_alloc() directly). Same stub

View file

@ -177,6 +177,21 @@ void kill_sched_user(void* arg) { (void)arg; }
void kill_sched_project(void* arg) { (void)arg; }
void kill_sched_resval(xce_val_t* val) { (void)val; }
/* repl_info.c (scheduler-sim-diagnostics spec, task 2.1) now calls
* limit_get_configured_limits() (plugins/limit.c, not part of this TU) to
* resolve `info limit`'s name/all argument -- link-satisfying stub only,
* same rationale as kill_sched_job()/kill_sched_resval() above; this
* file's own fixtures never register the limit plugin, so NULL
* (limit_get_configured_limits()'s own documented "plugin absent" return)
* is also the behaviorally correct answer here, not just a link
* placeholder. repl_info_limit() itself is not yet wired into
* repl_cmd_info() (task 4), so no test in this file can reach it anyway. */
var limit_get_configured_limits(xce_sched_core_t* core)
{
(void)core;
return NULL;
}
/* resource-accounting.md's reconciliation (resource.c, not linked here --
* this file only #includes core_events.c). core_events.c's
* XCE_CORE_EVENT_JOB_RUSAGE handler calls this whenever job->accounts !=

View file

@ -124,6 +124,21 @@ void kill_sched_user(void* arg) { (void)arg; }
void kill_sched_project(void* arg) { (void)arg; }
void kill_sched_resval(xce_val_t* val) { (void)val; }
/* repl_info.c (scheduler-sim-diagnostics spec, task 2.1) now calls
* limit_get_configured_limits() (plugins/limit.c, not part of this TU) to
* resolve `info limit`'s name/all argument -- link-satisfying stub only,
* same rationale as kill_sched_job()/kill_sched_resval() above; this
* file's own fixtures never register the limit plugin, so NULL
* (limit_get_configured_limits()'s own documented "plugin absent" return)
* is also the behaviorally correct answer here, not just a link
* placeholder. repl_info_limit() itself is not yet wired into
* repl_cmd_info() (task 4), so no test in this file can reach it anyway. */
var limit_get_configured_limits(xce_sched_core_t* core)
{
(void)core;
return NULL;
}
/* resource-accounting.md's reconciliation (resource.c, not linked here --
* this file only #includes core_events.c). core_events.c's
* XCE_CORE_EVENT_JOB_RUSAGE handler calls this whenever job->accounts !=

View file

@ -136,6 +136,21 @@ void kill_sched_user(void* arg) { (void)arg; }
void kill_sched_project(void* arg) { (void)arg; }
void kill_sched_resval(xce_val_t* val) { (void)val; }
/* repl_info.c (scheduler-sim-diagnostics spec, task 2.1) now calls
* limit_get_configured_limits() (plugins/limit.c, not part of this TU) to
* resolve `info limit`'s name/all argument -- link-satisfying stub only,
* same rationale as kill_sched_job()/kill_sched_resval() above; this
* file's own fixtures never register the limit plugin, so NULL
* (limit_get_configured_limits()'s own documented "plugin absent" return)
* is also the behaviorally correct answer here, not just a link
* placeholder. repl_info_limit() itself is not yet wired into
* repl_cmd_info() (task 4), so no test in this file can reach it anyway. */
var limit_get_configured_limits(xce_sched_core_t* core)
{
(void)core;
return NULL;
}
/* resource-accounting.md's reconciliation (resource.c, not linked here --
* this file only #includes core_events.c). core_events.c's
* XCE_CORE_EVENT_JOB_RUSAGE handler calls this whenever job->accounts !=

View file

@ -139,6 +139,21 @@ void kill_sched_user(void* arg) { (void)arg; }
void kill_sched_project(void* arg) { (void)arg; }
void kill_sched_resval(xce_val_t* val) { (void)val; }
/* repl_info.c (scheduler-sim-diagnostics spec, task 2.1) now calls
* limit_get_configured_limits() (plugins/limit.c, not part of this TU) to
* resolve `info limit`'s name/all argument -- link-satisfying stub only,
* same rationale as kill_sched_job()/kill_sched_resval() above; this
* file's own fixtures never register the limit plugin, so NULL
* (limit_get_configured_limits()'s own documented "plugin absent" return)
* is also the behaviorally correct answer here, not just a link
* placeholder. repl_info_limit() itself is not yet wired into
* repl_cmd_info() (task 4), so no test in this file can reach it anyway. */
var limit_get_configured_limits(xce_sched_core_t* core)
{
(void)core;
return NULL;
}
/* sched_worker_release_host_ctx() is now a REAL (non-stub) symbol pulled in
* from resource.c (task 2.1 addition, below) -- no local stand-in needed or
* permitted (a local definition here would collide at link time). Unused by

View file

@ -95,6 +95,21 @@ void kill_sched_user(void* arg) { (void)arg; }
void kill_sched_project(void* arg) { (void)arg; }
void kill_sched_resval(xce_val_t* val) { (void)val; }
/* repl_info.c (scheduler-sim-diagnostics spec, task 2.1) now calls
* limit_get_configured_limits() (plugins/limit.c, not part of this TU) to
* resolve `info limit`'s name/all argument -- link-satisfying stub only,
* same rationale as kill_sched_job()/kill_sched_resval() above; this
* file's own fixtures never register the limit plugin, so NULL
* (limit_get_configured_limits()'s own documented "plugin absent" return)
* is also the behaviorally correct answer here, not just a link
* placeholder. repl_info_limit() itself is not yet wired into
* repl_cmd_info() (task 4), so no test in this file can reach it anyway. */
var limit_get_configured_limits(xce_sched_core_t* core)
{
(void)core;
return NULL;
}
/* resource-accounting.md's reconciliation (resource.c, not linked here --
* this file only #includes core_events.c). core_events.c's
* XCE_CORE_EVENT_JOB_RUSAGE handler calls this whenever job->accounts !=

View file

@ -160,6 +160,21 @@ void kill_sched_user(void* arg) { (void)arg; }
void kill_sched_project(void* arg) { (void)arg; }
void kill_sched_resval(xce_val_t* val) { (void)val; }
/* repl_info.c (scheduler-sim-diagnostics spec, task 2.1) now calls
* limit_get_configured_limits() (plugins/limit.c, not part of this TU) to
* resolve `info limit`'s name/all argument -- link-satisfying stub only,
* same rationale as kill_sched_job()/kill_sched_resval() above; this
* file's own fixtures never register the limit plugin, so NULL
* (limit_get_configured_limits()'s own documented "plugin absent" return)
* is also the behaviorally correct answer here, not just a link
* placeholder. repl_info_limit() itself is not yet wired into
* repl_cmd_info() (task 4), so no test in this file can reach it anyway. */
var limit_get_configured_limits(xce_sched_core_t* core)
{
(void)core;
return NULL;
}
/* xce_sched_driver_run_normal_mode_round()'s (driver.c) linker dependency --
* a no-op stand-in, same rationale test_sim_equivalence.c's own copy
* documents (this file drives its own resource accounting directly via

View file

@ -128,6 +128,21 @@ void kill_sched_user(void* arg) { (void)arg; }
void kill_sched_project(void* arg) { (void)arg; }
void kill_sched_resval(xce_val_t* val) { (void)val; }
/* repl_info.c (scheduler-sim-diagnostics spec, task 2.1) now calls
* limit_get_configured_limits() (plugins/limit.c, not part of this TU) to
* resolve `info limit`'s name/all argument -- link-satisfying stub only,
* same rationale as kill_sched_job()/kill_sched_resval() above; this
* file's own fixtures never register the limit plugin, so NULL
* (limit_get_configured_limits()'s own documented "plugin absent" return)
* is also the behaviorally correct answer here, not just a link
* placeholder. repl_info_limit() itself is not yet wired into
* repl_cmd_info() (task 4), so no test in this file can reach it anyway. */
var limit_get_configured_limits(xce_sched_core_t* core)
{
(void)core;
return NULL;
}
/* resource.c's sched_try_alloc_on_host_()'s own link-time dependency --
* never actually invoked (this file calls sched_check_host_satisfy()
* directly, never sched_try_alloc_on_hosts()/sched_try_alloc_on_host_()

View file

@ -160,6 +160,21 @@ void kill_sched_user(void* arg) { (void)arg; }
void kill_sched_project(void* arg) { (void)arg; }
void kill_sched_resval(xce_val_t* val) { (void)val; }
/* repl_info.c (scheduler-sim-diagnostics spec, task 2.1) now calls
* limit_get_configured_limits() (plugins/limit.c, not part of this TU) to
* resolve `info limit`'s name/all argument -- link-satisfying stub only,
* same rationale as kill_sched_job()/kill_sched_resval() above; this
* file's own fixtures never register the limit plugin, so NULL
* (limit_get_configured_limits()'s own documented "plugin absent" return)
* is also the behaviorally correct answer here, not just a link
* placeholder. repl_info_limit() itself is not yet wired into
* repl_cmd_info() (task 4), so no test in this file can reach it anyway. */
var limit_get_configured_limits(xce_sched_core_t* core)
{
(void)core;
return NULL;
}
/* core_reset_workers()'s (core_session.c) linker dependency -- never
* invoked (no worker is ever added here). */
void sched_worker_release_host_ctx(xce_sched_worker_t* w) { (void)w; }

View file

@ -114,6 +114,21 @@ void kill_sched_user(void* arg) { (void)arg; }
void kill_sched_project(void* arg) { (void)arg; }
void kill_sched_resval(xce_val_t* val) { (void)val; }
/* repl_info.c (scheduler-sim-diagnostics spec, task 2.1) now calls
* limit_get_configured_limits() (plugins/limit.c, not part of this TU) to
* resolve `info limit`'s name/all argument -- link-satisfying stub only,
* same rationale as kill_sched_job()/kill_sched_resval() above; this
* file's own fixtures never register the limit plugin, so NULL
* (limit_get_configured_limits()'s own documented "plugin absent" return)
* is also the behaviorally correct answer here, not just a link
* placeholder. repl_info_limit() itself is not yet wired into
* repl_cmd_info() (task 4), so no test in this file can reach it anyway. */
var limit_get_configured_limits(xce_sched_core_t* core)
{
(void)core;
return NULL;
}
/* core_reset_workers()'s (core_session.c) linker dependency -- same stub
* test_sim_verify.c already establishes; never invoked (no worker is ever
* added here). */

View file

@ -115,6 +115,21 @@ void kill_sched_user(void* arg) { (void)arg; }
void kill_sched_project(void* arg) { (void)arg; }
void kill_sched_resval(xce_val_t* val) { (void)val; }
/* repl_info.c (scheduler-sim-diagnostics spec, task 2.1) now calls
* limit_get_configured_limits() (plugins/limit.c, not part of this TU) to
* resolve `info limit`'s name/all argument -- link-satisfying stub only,
* same rationale as kill_sched_job()/kill_sched_resval() above; this
* file's own fixtures never register the limit plugin, so NULL
* (limit_get_configured_limits()'s own documented "plugin absent" return)
* is also the behaviorally correct answer here, not just a link
* placeholder. repl_info_limit() itself is not yet wired into
* repl_cmd_info() (task 4), so no test in this file can reach it anyway. */
var limit_get_configured_limits(xce_sched_core_t* core)
{
(void)core;
return NULL;
}
/* resource-accounting.md's reconciliation (resource.c, not linked here --
* this file only #includes core_events.c). core_events.c's
* XCE_CORE_EVENT_JOB_RUSAGE handler calls this whenever job->accounts !=