feat(scheduler-sim-decision-parity): relocate resource accounting to core-level (task 1.1)
Relocates sched_account_jobs()/sched_charge_account()/sched_uncharge_account()/ sched_update_account()/sched_update_res_accounts()/sched_commit_job_alloc() from xce_scheduler_t* to xce_sched_core_t*, mirroring the sched_resolve_job_picker() precedent, so the simulation driver can call the same accounting service the normal-mode driver already uses. Pure signature relocation -- every body reference was already sched->core.*, no logic change. Updates the 3 real call sites (driver.c's normal-mode round, scheduler.c's sched_begin_session and sched_commit_decision) and 7 existing tests' link-satisfying stub signatures. Adds test_resource_accounting.c proving Requirement 1.4: the relocated accounting produces identical resInUse/sharedInUse output whether called against a core embedded in xce_scheduler_t or xce_sched_sim_driver_t. 43/44 scheduler tests pass; the 1 failure is pre-existing bug-1560 (unrelated recording.c sandbox-permission ordering issue). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
0b2c856d8b
commit
3106c82ed0
15 changed files with 498 additions and 75 deletions
|
|
@ -405,13 +405,14 @@ sched_driver_decision_cb_test = executable(
|
|||
# through a genuinely test-registered xce_sched_plugin_t whose
|
||||
# begin_session_fn/end_session_fn set/check an ordering flag -- per this
|
||||
# task's own suggested technique, this is a stronger proof than spying on
|
||||
# plugin_begin_session() itself. sched_account_jobs() (scheduler.c,
|
||||
# xce_scheduler_t*-coupled, pulls in resource.c's sched_charge_account())
|
||||
# is instead a SPY test double recording an order index -- this test's
|
||||
# target is the DRIVER's ordering discipline, not sched_account_jobs()'s
|
||||
# own resource-accounting correctness (out of this task's scope, same
|
||||
# "spy the xce_scheduler_t*-coupled collaborator" rationale
|
||||
# test_driver_decision_cb.c/test_driver_translate.c already established for
|
||||
# plugin_begin_session() itself. sched_account_jobs() (scheduler.c, defined
|
||||
# on xce_sched_core_t* as of scheduler-sim-decision-parity task 1.1, pulls
|
||||
# in resource.c's sched_charge_account()) is instead a SPY test double
|
||||
# recording an order index -- this test's target is the DRIVER's ordering
|
||||
# discipline, not sched_account_jobs()'s own resource-accounting
|
||||
# correctness (out of this task's scope, same "spy the collaborator"
|
||||
# rationale test_driver_decision_cb.c/test_driver_translate.c already
|
||||
# established for the xce_scheduler_t*-coupled
|
||||
# sched_publish_dispatch()/sched_publish_pend_reason()).
|
||||
sched_driver_session_ordering_test = executable(
|
||||
'sched_driver_session_ordering_test',
|
||||
|
|
@ -420,6 +421,23 @@ sched_driver_session_ordering_test = executable(
|
|||
dependencies: [scheduler_test_deps],
|
||||
install: false)
|
||||
|
||||
# Requirement 1.4 proof for the Core-Level Resource Accounting component
|
||||
# (scheduler-sim-decision-parity spec, task 1.1): sched_charge_account()/
|
||||
# sched_uncharge_account()/sched_commit_job_alloc() (resource.c, relocated
|
||||
# from xce_scheduler_t* to xce_sched_core_t* by this task) produce
|
||||
# byte-identical resInUse/sharedInUse output whether `core` came from an
|
||||
# xce_scheduler_t (normal-mode driver) or an xce_sched_sim_driver_t
|
||||
# (simulation driver, sim.h) -- see test_resource_accounting.c's own file
|
||||
# header comment for why sched_account_jobs() itself (scheduler.c) is not
|
||||
# also white-box #included here (no existing test in this directory
|
||||
# white-box #includes scheduler.c, for the same reason documented there).
|
||||
sched_resource_accounting_test = executable(
|
||||
'sched_resource_accounting_test',
|
||||
['test_resource_accounting.c'],
|
||||
include_directories:[incdir],
|
||||
dependencies: [scheduler_test_deps],
|
||||
install: false)
|
||||
|
||||
# Cross-core behavioral-equivalence proof for
|
||||
# xce_sched_core_save_snapshot()/xce_sched_core_load_snapshot()
|
||||
# (scheduler-core spec, task 8.1, Req 5 AC 21 / Req 6 AC 5): save immediately
|
||||
|
|
@ -996,6 +1014,9 @@ test('scheduler driver decision cb test',
|
|||
test('scheduler driver session ordering test',
|
||||
sched_driver_session_ordering_test, suite: 'scheduler',
|
||||
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
||||
test('scheduler resource accounting test',
|
||||
sched_resource_accounting_test, suite: 'scheduler',
|
||||
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
||||
test('scheduler snapshot save load test',
|
||||
sched_snapshot_save_load_test, suite: 'scheduler',
|
||||
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
||||
|
|
|
|||
|
|
@ -178,9 +178,9 @@ int plugin_end_session(void* arg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int sched_account_jobs(xce_scheduler_t* sched)
|
||||
int sched_account_jobs(xce_sched_core_t* core)
|
||||
{
|
||||
(void)sched;
|
||||
(void)core;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -142,9 +142,9 @@ int plugin_end_session(void* arg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int sched_account_jobs(xce_scheduler_t* sched)
|
||||
int sched_account_jobs(xce_sched_core_t* core)
|
||||
{
|
||||
(void)sched;
|
||||
(void)core;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -80,13 +80,16 @@
|
|||
* sched_account_jobs() (scheduler.c) is instead a SPY test double (this
|
||||
* file never links scheduler.c) -- same rationale
|
||||
* test_driver_decision_cb.c/test_driver_translate.c already established
|
||||
* for sched_publish_dispatch()/sched_publish_pend_reason(): it is
|
||||
* xce_scheduler_t*-coupled and pulls in resource.c's sched_charge_account()
|
||||
* machinery, whose OWN resource-accounting correctness is out of THIS
|
||||
* task's scope (this test's target is the DRIVER's ordering discipline --
|
||||
* does it call sched_account_jobs() at all, and in the right window --
|
||||
* not whether sched_account_jobs() itself charges resources correctly,
|
||||
* which is scheduler-allocation spec territory with its own coverage).
|
||||
* for sched_publish_dispatch()/sched_publish_pend_reason(): it pulls in
|
||||
* resource.c's sched_charge_account() machinery, whose OWN resource-
|
||||
* accounting correctness is out of THIS task's scope (this test's target
|
||||
* is the DRIVER's ordering discipline -- does it call sched_account_jobs()
|
||||
* at all, and in the right window -- not whether sched_account_jobs()
|
||||
* itself charges resources correctly, which is scheduler-allocation spec
|
||||
* territory, plus test_resource_accounting.c's own coverage as of
|
||||
* scheduler-sim-decision-parity task 1.1). As of that same task,
|
||||
* sched_account_jobs() takes xce_sched_core_t* (relocated from
|
||||
* xce_scheduler_t*) -- this spy's signature matches.
|
||||
*
|
||||
* White-box #include of ../src/core.c, ../src/core_clock.c,
|
||||
* ../src/core_events.c, ../src/core_session.c, ../src/decision.c,
|
||||
|
|
@ -346,8 +349,8 @@ int sched_resolve_job_picker(xce_sched_core_t* core, xce_sched_plugin_t** out)
|
|||
}
|
||||
|
||||
/* sched_account_jobs() itself is defined further below (SPY test double
|
||||
* section) -- its prototype already comes from scheduler.h, included
|
||||
* above. */
|
||||
* section) -- its prototype already comes from core.h (included above via
|
||||
* scheduler.h). */
|
||||
|
||||
void setUp(void) { return; }
|
||||
void tearDown(void) { return; }
|
||||
|
|
@ -409,9 +412,9 @@ static int find_log_index(ordering_event_tag_t tag)
|
|||
|
||||
static _Atomic int g_account_jobs_calls;
|
||||
|
||||
int sched_account_jobs(xce_scheduler_t* sched)
|
||||
int sched_account_jobs(xce_sched_core_t* core)
|
||||
{
|
||||
(void)sched;
|
||||
(void)core;
|
||||
|
||||
atomic_fetch_add(&g_account_jobs_calls, 1);
|
||||
log_event(EVT_ACCOUNT_JOBS);
|
||||
|
|
|
|||
|
|
@ -228,9 +228,9 @@ int plugin_end_session(void* arg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int sched_account_jobs(xce_scheduler_t* sched)
|
||||
int sched_account_jobs(xce_sched_core_t* core)
|
||||
{
|
||||
(void)sched;
|
||||
(void)core;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -143,9 +143,9 @@ int sched_fill_limit_requests(xce_scheduler_t* sched, xvec_idval_t* vec,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int sched_account_jobs(xce_scheduler_t* sched)
|
||||
int sched_account_jobs(xce_sched_core_t* core)
|
||||
{
|
||||
(void)sched;
|
||||
(void)core;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
359
src/scheduler/testsuite/test_resource_accounting.c
Normal file
359
src/scheduler/testsuite/test_resource_accounting.c
Normal file
|
|
@ -0,0 +1,359 @@
|
|||
/*
|
||||
* test_resource_accounting.c - Requirement 1.4 proof for the Core-Level
|
||||
* Resource Accounting component (scheduler-sim-decision-parity spec, task
|
||||
* 1.1; design.md's "Core-Level Resource Accounting" Unit Tests bullet):
|
||||
* "produces identical resInUse/sharedInUse output whether called with a
|
||||
* core obtained from xce_scheduler_t or from xce_sched_sim_driver_t."
|
||||
*
|
||||
* Task 1.1 itself is a pure signature relocation (xce_scheduler_t* ->
|
||||
* xce_sched_core_t*) of sched_account_jobs()/sched_charge_account()/
|
||||
* sched_uncharge_account()/sched_update_account()/
|
||||
* sched_update_res_accounts()/sched_commit_job_alloc() -- body unchanged,
|
||||
* every reference already `sched->core.*` before the move (confirmed via
|
||||
* `grep "sched->" resource.c | grep -v "sched->core"` returning zero
|
||||
* matches, design.md's Existing Architecture Analysis). Requirement 1.4 is
|
||||
* nonetheless a genuinely NEW observable property worth its own test (not
|
||||
* just "nothing broke"): now that these functions take xce_sched_core_t*
|
||||
* directly, they are usable identically regardless of which driver-level
|
||||
* container struct (xce_scheduler_t, the normal-mode driver's; or
|
||||
* xce_sched_sim_driver_t, the simulation driver's, sim.h) embeds the core.
|
||||
* This file drives the REAL sched_charge_account()/sched_uncharge_account()/
|
||||
* sched_commit_job_alloc() (resource.c) against two independently
|
||||
* initialized xce_sched_core_t instances -- one embedded in an
|
||||
* xce_scheduler_t, one embedded in an xce_sched_sim_driver_t -- with
|
||||
* identical worker/account state, and asserts byte-identical
|
||||
* resInUse/sharedInUse results.
|
||||
*
|
||||
* sched_account_jobs() itself (scheduler.c) is NOT white-box #included here
|
||||
* -- unlike this file's own sched_charge_account()/sched_commit_job_alloc()
|
||||
* targets (resource.c, a lightweight, already-proven-includable file per
|
||||
* test.c's own #include "../src/resource.c"), scheduler.c is a ~1400-line
|
||||
* file with a much larger link-time dependency surface (controller-join,
|
||||
* capnp decision publishing, HA candidate handling, picker/allocator thread
|
||||
* lifecycle) that no existing test in this directory white-box #includes for
|
||||
* exactly that reason (confirmed via grep across testsuite/ before writing
|
||||
* this file). sched_account_jobs() itself is a thin, ~20-line wrapper
|
||||
* (iterate core->jobs, call sched_charge_account() for each RUN-state job
|
||||
* with a known allocation) with no accounting logic of its own -- its
|
||||
* driver-ordering discipline (called at the right point in the round
|
||||
* boundary, on both drivers) is already proven by
|
||||
* test_driver_session_ordering.c (a spy, by design -- see that file's own
|
||||
* header comment) and this feature's later tasks (2.x/3.x, sim_loop.c's own
|
||||
* round-boundary integration). This file instead proves the actual
|
||||
* accounting *body* -- the part design.md's Testing Strategy bullet is
|
||||
* about -- via its real callees, exercised directly.
|
||||
*
|
||||
* White-box #include of ../src/core.c (for the real
|
||||
* xce_sched_core_init()/sched_add_worker()/sched_get_worker() the fixture
|
||||
* needs) and ../src/resource.c (the functions under test). Neither file
|
||||
* needs core_clock.c/core_events.c/core_session.c/decision.c/plugin.c --
|
||||
* this test never calls xce_core_push_events()/xce_core_begin_session()/
|
||||
* anything decision- or plugin-registration-related, only the plain
|
||||
* add-worker/charge-account entry points core.c/resource.c themselves
|
||||
* define. Stubs below (kill_sched_* family, plugin_unregister) are the
|
||||
* standard link-satisfying no-ops xce_sched_core_init()'s kvmgr datakillers
|
||||
* reference (never actually invoked -- this fixture is never torn down,
|
||||
* same convention as test_driver_session_ordering.c/
|
||||
* test_snapshot_save_load.c's identical stub set).
|
||||
* sched_worker_release_host_ctx() is the one real (non-stub) symbol this
|
||||
* pulls from resource.c itself, not from core_session.c -- unused here
|
||||
* (this test never calls it), listed only because resource.c defines it.
|
||||
*/
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <unity/unity.h>
|
||||
|
||||
#include "scheduler.h"
|
||||
#include "sim.h"
|
||||
|
||||
/* Pull in the real xce_sched_core_init()/sched_add_worker()/
|
||||
* sched_get_worker() (core.c) and sched_charge_account()/
|
||||
* sched_uncharge_account()/sched_commit_job_alloc()/get_resvals() (resource.c,
|
||||
* the functions under test) into this TU (white-box #include, same
|
||||
* convention as every other file in this directory). */
|
||||
#include "../src/core.c"
|
||||
#include "../src/resource.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; }
|
||||
void plugin_unregister(void* arg) { (void)arg; }
|
||||
|
||||
/* Link-satisfying stubs for resource.c's sched_try_alloc_on_host_() (its
|
||||
* OWN callees, plugin_prepare_allocation()/sched_ctx_get_uncomit_host(),
|
||||
* live in plugin.c/schedobj.c -- neither white-box #included here). Never
|
||||
* actually invoked: this file never calls sched_try_alloc_on_hosts()/
|
||||
* sched_try_alloc_on_host_(), only sched_charge_account()/
|
||||
* sched_uncharge_account()/sched_commit_job_alloc(). Same two stubs
|
||||
* test.c's own #include "../src/resource.c" already establishes needing. */
|
||||
int plugin_prepare_allocation(void* s, xce_sched_ctx_t* c)
|
||||
{
|
||||
(void)s;
|
||||
(void)c;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sched_ctx_get_uncomit_host(xvec_t** v, xce_sched_ctx_t* c, int i)
|
||||
{
|
||||
(void)v;
|
||||
(void)c;
|
||||
(void)i;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void setUp(void) { return; }
|
||||
void tearDown(void) { return; }
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Fixture helpers */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* setup_core_with_worker - real xce_sched_core_init() (core.c) plus one
|
||||
* real worker (sched_add_worker(), core.c), its resvals/resInUse zarrays
|
||||
* freshly zarray_init()'d exactly the way a real worker join would leave
|
||||
* them (sched_add_worker() itself does not do this -- callers own it, same
|
||||
* as every other white-box fixture in this directory that adds a worker
|
||||
* directly rather than through the JOBS_PUSH/WORKERS_PUSH event path).
|
||||
*/
|
||||
static void setup_core_with_worker(xce_sched_core_t* core,
|
||||
const char* worker_name)
|
||||
{
|
||||
xce_sched_worker_t* w;
|
||||
int rc;
|
||||
|
||||
rc = xce_sched_core_init(core);
|
||||
TEST_ASSERT_EQUAL_INT(0, rc);
|
||||
|
||||
w = (xce_sched_worker_t*)calloc(1, sizeof(*w));
|
||||
TEST_ASSERT_NOT_NULL(w);
|
||||
|
||||
w->name = strdup(worker_name);
|
||||
TEST_ASSERT_NOT_NULL(w->name);
|
||||
|
||||
rc = zarray_init(&(w->resvals), 8, NULL);
|
||||
TEST_ASSERT_EQUAL_INT(0, rc);
|
||||
rc = zarray_init(&(w->resInUse), 8, NULL);
|
||||
TEST_ASSERT_EQUAL_INT(0, rc);
|
||||
|
||||
rc = sched_add_worker(core, w);
|
||||
TEST_ASSERT_TRUE(rc >= 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* make_test_account - one shared-resource charge (residx `shared_residx`)
|
||||
* plus one per-host charge (residx `host_residx`, against `worker_name`) --
|
||||
* enough to exercise both of sched_update_account()'s two branches
|
||||
* (core->sharedInUse and a specific worker's resInUse). residx is set
|
||||
* non-negative directly (bypassing sched_update_res_accounts()'s
|
||||
* resmgr-lookup branch entirely) -- this test targets the charge/uncharge
|
||||
* arithmetic itself, not resource-name resolution, which is unrelated,
|
||||
* already-existing logic this task's relocation does not touch.
|
||||
*/
|
||||
static xce_job_account_t*
|
||||
make_test_account(const char* worker_name, int shared_residx,
|
||||
double shared_used, double shared_reserved, int host_residx,
|
||||
double host_used, double host_reserved)
|
||||
{
|
||||
xce_job_account_t* acct
|
||||
= (xce_job_account_t*)calloc(1, sizeof(*acct));
|
||||
TEST_ASSERT_NOT_NULL(acct);
|
||||
|
||||
acct->nres_shared = 1;
|
||||
acct->accounts_shared = (xce_res_account_t**)calloc(
|
||||
1, sizeof(*acct->accounts_shared));
|
||||
TEST_ASSERT_NOT_NULL(acct->accounts_shared);
|
||||
acct->accounts_shared[0]
|
||||
= (xce_res_account_t*)calloc(1, sizeof(xce_res_account_t));
|
||||
TEST_ASSERT_NOT_NULL(acct->accounts_shared[0]);
|
||||
acct->accounts_shared[0]->residx = shared_residx;
|
||||
acct->accounts_shared[0]->used = shared_used;
|
||||
acct->accounts_shared[0]->reserved = shared_reserved;
|
||||
|
||||
acct->nhosts = 1;
|
||||
acct->accounts = (xce_host_account_t**)calloc(1, sizeof(*acct->accounts));
|
||||
TEST_ASSERT_NOT_NULL(acct->accounts);
|
||||
acct->accounts[0]
|
||||
= (xce_host_account_t*)calloc(1, sizeof(xce_host_account_t));
|
||||
TEST_ASSERT_NOT_NULL(acct->accounts[0]);
|
||||
acct->accounts[0]->host = strdup(worker_name);
|
||||
acct->accounts[0]->naccount = 1;
|
||||
acct->accounts[0]->accounts
|
||||
= (xce_res_account_t**)calloc(1, sizeof(*acct->accounts[0]->accounts));
|
||||
TEST_ASSERT_NOT_NULL(acct->accounts[0]->accounts);
|
||||
acct->accounts[0]->accounts[0]
|
||||
= (xce_res_account_t*)calloc(1, sizeof(xce_res_account_t));
|
||||
TEST_ASSERT_NOT_NULL(acct->accounts[0]->accounts[0]);
|
||||
acct->accounts[0]->accounts[0]->residx = host_residx;
|
||||
acct->accounts[0]->accounts[0]->used = host_used;
|
||||
acct->accounts[0]->accounts[0]->reserved = host_reserved;
|
||||
|
||||
return acct;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Tests */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
#define WORKER_NAME "worker-a"
|
||||
#define SHARED_RESIDX 0
|
||||
#define HOST_RESIDX 1
|
||||
#define SHARED_USED 3.0
|
||||
#define SHARED_RESERVED 1.5
|
||||
#define HOST_USED 2.0
|
||||
#define HOST_RESERVED 0.5
|
||||
/* SHARED_USED + SHARED_RESERVED, HOST_USED + HOST_RESERVED */
|
||||
#define EXPECTED_SHARED_CHARGE 4.5f
|
||||
#define EXPECTED_HOST_CHARGE 2.5f
|
||||
|
||||
/*
|
||||
* test_charge_account_identical_across_core_containers - Requirement 1.4:
|
||||
* sched_charge_account()/sched_uncharge_account() (resource.c) produce
|
||||
* byte-identical resInUse/sharedInUse results whether `core` came from an
|
||||
* xce_scheduler_t (sched.core, the normal-mode driver's container) or an
|
||||
* xce_sched_sim_driver_t (sim.core, the simulation driver's container) --
|
||||
* the exact property that makes the simulation driver's build now able to
|
||||
* call the same accounting service the normal-mode driver already used.
|
||||
*/
|
||||
static void test_charge_account_identical_across_core_containers(void)
|
||||
{
|
||||
xce_scheduler_t sched;
|
||||
xce_sched_sim_driver_t sim;
|
||||
xce_job_account_t* acct;
|
||||
xce_sched_worker_t* w_sched;
|
||||
xce_sched_worker_t* w_sim;
|
||||
float shared_sched[1];
|
||||
float shared_sim[1];
|
||||
float host_sched[1];
|
||||
float host_sim[1];
|
||||
int shared_idx[1] = { SHARED_RESIDX };
|
||||
int host_idx[1] = { HOST_RESIDX };
|
||||
int rc;
|
||||
|
||||
memset(&sched, 0, sizeof(sched));
|
||||
memset(&sim, 0, sizeof(sim));
|
||||
|
||||
setup_core_with_worker(&(sched.core), WORKER_NAME);
|
||||
setup_core_with_worker(&(sim.core), WORKER_NAME);
|
||||
|
||||
/* Same account struct fed to both cores -- sched_charge_account() never
|
||||
* mutates it when residx is already non-negative (see
|
||||
* make_test_account()'s own comment), so reuse is safe and keeps the
|
||||
* two calls genuinely identical, not merely equal-by-construction. */
|
||||
acct = make_test_account(WORKER_NAME, SHARED_RESIDX, SHARED_USED,
|
||||
SHARED_RESERVED, HOST_RESIDX, HOST_USED,
|
||||
HOST_RESERVED);
|
||||
|
||||
rc = sched_charge_account(&(sched.core), acct);
|
||||
TEST_ASSERT_EQUAL_INT(0, rc);
|
||||
rc = sched_charge_account(&(sim.core), acct);
|
||||
TEST_ASSERT_EQUAL_INT(0, rc);
|
||||
|
||||
/* --- sharedInUse: identical across both containers, and correct --- */
|
||||
get_resvals(&(sched.core.sharedInUse), 1, shared_idx, shared_sched);
|
||||
get_resvals(&(sim.core.sharedInUse), 1, shared_idx, shared_sim);
|
||||
TEST_ASSERT_EQUAL_FLOAT(EXPECTED_SHARED_CHARGE, shared_sched[0]);
|
||||
TEST_ASSERT_EQUAL_FLOAT(shared_sched[0], shared_sim[0]);
|
||||
|
||||
/* --- per-worker resInUse: identical across both containers --- */
|
||||
w_sched = sched_get_worker(&(sched.core), WORKER_NAME);
|
||||
w_sim = sched_get_worker(&(sim.core), WORKER_NAME);
|
||||
TEST_ASSERT_NOT_NULL(w_sched);
|
||||
TEST_ASSERT_NOT_NULL(w_sim);
|
||||
|
||||
get_resvals(&(w_sched->resInUse), 1, host_idx, host_sched);
|
||||
get_resvals(&(w_sim->resInUse), 1, host_idx, host_sim);
|
||||
TEST_ASSERT_EQUAL_FLOAT(EXPECTED_HOST_CHARGE, host_sched[0]);
|
||||
TEST_ASSERT_EQUAL_FLOAT(host_sched[0], host_sim[0]);
|
||||
|
||||
/* --- sched_uncharge_account() mirrors this identically too --- */
|
||||
rc = sched_uncharge_account(&(sched.core), acct);
|
||||
TEST_ASSERT_EQUAL_INT(0, rc);
|
||||
rc = sched_uncharge_account(&(sim.core), acct);
|
||||
TEST_ASSERT_EQUAL_INT(0, rc);
|
||||
|
||||
get_resvals(&(sched.core.sharedInUse), 1, shared_idx, shared_sched);
|
||||
get_resvals(&(sim.core.sharedInUse), 1, shared_idx, shared_sim);
|
||||
TEST_ASSERT_EQUAL_FLOAT(0.0f, shared_sched[0]);
|
||||
TEST_ASSERT_EQUAL_FLOAT(shared_sched[0], shared_sim[0]);
|
||||
|
||||
get_resvals(&(w_sched->resInUse), 1, host_idx, host_sched);
|
||||
get_resvals(&(w_sim->resInUse), 1, host_idx, host_sim);
|
||||
TEST_ASSERT_EQUAL_FLOAT(0.0f, host_sched[0]);
|
||||
TEST_ASSERT_EQUAL_FLOAT(host_sched[0], host_sim[0]);
|
||||
}
|
||||
|
||||
/*
|
||||
* test_commit_job_alloc_identical_across_core_containers - Requirement 1.4
|
||||
* for sched_commit_job_alloc() specifically (the third relocated group
|
||||
* member scheduler.c's sched_commit_decision() calls, design.md's own File
|
||||
* Structure Plan entry for scheduler.c): both its no-op (job->accounts ==
|
||||
* NULL) and its charging path behave identically regardless of which
|
||||
* driver-level struct the core came from.
|
||||
*/
|
||||
static void test_commit_job_alloc_identical_across_core_containers(void)
|
||||
{
|
||||
xce_scheduler_t sched;
|
||||
xce_sched_sim_driver_t sim;
|
||||
xce_sched_job_t job_sched;
|
||||
xce_sched_job_t job_sim;
|
||||
xce_job_account_t* acct;
|
||||
float shared_sched[1];
|
||||
float shared_sim[1];
|
||||
int shared_idx[1] = { SHARED_RESIDX };
|
||||
int rc;
|
||||
|
||||
memset(&sched, 0, sizeof(sched));
|
||||
memset(&sim, 0, sizeof(sim));
|
||||
memset(&job_sched, 0, sizeof(job_sched));
|
||||
memset(&job_sim, 0, sizeof(job_sim));
|
||||
|
||||
setup_core_with_worker(&(sched.core), WORKER_NAME);
|
||||
setup_core_with_worker(&(sim.core), WORKER_NAME);
|
||||
|
||||
/* --- job->accounts == NULL: documented no-op, identical on both --- */
|
||||
job_sched.accounts = NULL;
|
||||
job_sim.accounts = NULL;
|
||||
|
||||
rc = sched_commit_job_alloc(&(sched.core), &job_sched);
|
||||
TEST_ASSERT_EQUAL_INT(0, rc);
|
||||
rc = sched_commit_job_alloc(&(sim.core), &job_sim);
|
||||
TEST_ASSERT_EQUAL_INT(0, rc);
|
||||
|
||||
get_resvals(&(sched.core.sharedInUse), 1, shared_idx, shared_sched);
|
||||
get_resvals(&(sim.core.sharedInUse), 1, shared_idx, shared_sim);
|
||||
TEST_ASSERT_EQUAL_FLOAT(0.0f, shared_sched[0]);
|
||||
TEST_ASSERT_EQUAL_FLOAT(shared_sched[0], shared_sim[0]);
|
||||
|
||||
/* --- job->accounts set: charges through sched_charge_account(),
|
||||
* identical on both --- */
|
||||
acct = make_test_account(WORKER_NAME, SHARED_RESIDX,
|
||||
SHARED_USED, SHARED_RESERVED,
|
||||
HOST_RESIDX, HOST_USED,
|
||||
HOST_RESERVED);
|
||||
job_sched.accounts = acct;
|
||||
job_sim.accounts = acct;
|
||||
|
||||
rc = sched_commit_job_alloc(&(sched.core), &job_sched);
|
||||
TEST_ASSERT_EQUAL_INT(0, rc);
|
||||
rc = sched_commit_job_alloc(&(sim.core), &job_sim);
|
||||
TEST_ASSERT_EQUAL_INT(0, rc);
|
||||
|
||||
get_resvals(&(sched.core.sharedInUse), 1, shared_idx, shared_sched);
|
||||
get_resvals(&(sim.core.sharedInUse), 1, shared_idx, shared_sim);
|
||||
TEST_ASSERT_EQUAL_FLOAT(EXPECTED_SHARED_CHARGE, shared_sched[0]);
|
||||
TEST_ASSERT_EQUAL_FLOAT(shared_sched[0], shared_sim[0]);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
UNITY_BEGIN();
|
||||
RUN_TEST(test_charge_account_identical_across_core_containers);
|
||||
RUN_TEST(test_commit_job_alloc_identical_across_core_containers);
|
||||
return UNITY_END();
|
||||
}
|
||||
|
|
@ -233,9 +233,9 @@ int plugin_end_session(void* arg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int sched_account_jobs(xce_scheduler_t* sched)
|
||||
int sched_account_jobs(xce_sched_core_t* core)
|
||||
{
|
||||
(void)sched;
|
||||
(void)core;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -195,9 +195,9 @@ int sched_fill_limit_requests(xce_scheduler_t* sched, xvec_idval_t* vec,
|
|||
* a no-op stand-in, same rationale test_record_lifecycle.c's own copy
|
||||
* documents (real resource accounting is scheduler.c/resource.c territory,
|
||||
* not exercised here). */
|
||||
int sched_account_jobs(xce_scheduler_t* sched)
|
||||
int sched_account_jobs(xce_sched_core_t* core)
|
||||
{
|
||||
(void)sched;
|
||||
(void)core;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue