test(resreq-maxtasks-wiring): verify driver parity, update-immunity, cache
Extends test_maxtasks_wiring_ingest.c with two tests: (1) a resource- request update never changes a job's already-dispatched task count, because core_events.c's live JOB_UPDATE handler never rebuilds job->schedobj (Requirement 1.4); (2) two otherwise-identical jobs differing only in requested task count don't collide in the unsatisfiable-resource-request cache on the fresh-ingest path (Requirement 5.4). Adds a new file, test_maxtasks_wiring_sim_driver_parity.c, proving the simulation driver's real static translator chain (sim_process_replay_event_message()/replay_event_to_core_event()) applies this feature's wiring identically to the real driver -- a genuine white-box test of the real sim_loop.c code (following test_sim_event_loop.c's established #include technique), not a mirror of its logic. This was split into its own file because test_maxtasks_wiring_ingest.c already links the full scheduler_srcs object list for its own task-3.1 test, which collides at link time with white-box #include-ing core_events.c/sim_loop.c in one translation unit; see tasks.md's Implementation Notes. No production code changed. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XYdtrEWWZfKRRGED7raEYg
This commit is contained in:
parent
4644d20cf0
commit
c36014c072
4 changed files with 865 additions and 2 deletions
|
|
@ -112,6 +112,55 @@
|
|||
* All three lines were restored immediately afterward (git-verified clean
|
||||
* diff against core_events.c/snapshot_load.c) before this file's own
|
||||
* implementation was finalized.
|
||||
*
|
||||
* ── Task 3.2 addendum -- two more tests, same file/link technique ────────
|
||||
* Task 3.2 (Req 1.4, 5.4, and design.md's "Project Invariant Cross-Check")
|
||||
* appends two MORE tests to this same file, reusing every fixture helper
|
||||
* above. (A third task-3.2 test, proving driver/simulation ingest parity
|
||||
* via the REAL, `static` simulation-driver translator chain, lives in its
|
||||
* own separate file, test_maxtasks_wiring_sim_driver_parity.c -- see that
|
||||
* file's own header comment for why: an independent review rejected this
|
||||
* file's original mirrored version of that test and required white-box
|
||||
* #include-ing sim_loop.c's real translator instead, which cannot share a
|
||||
* translation unit with this file's own test 3, below, since that test
|
||||
* links the whole real scheduler_srcs object list.)
|
||||
*
|
||||
* 4. test_resource_request_update_never_changes_dispatched_task_count:
|
||||
* Req 1.4's structural regression test. A job is ingested fresh, then
|
||||
* a real XCE_CORE_EVENT_JOB_UPDATE is driven for the SAME jobid
|
||||
* carrying BOTH a different resreq string AND a different requested
|
||||
* task count. Confirms job->resreq WAS genuinely replaced (so the
|
||||
* immunity assertion below isn't vacuous), then confirms
|
||||
* job->schedobj->u.primary->resreq -- what the real allocator dispatch
|
||||
* reads -- is the EXACT SAME object with the EXACT SAME ingest-time
|
||||
* task count, because core_events.c's JOB_UPDATE case never reassigns
|
||||
* job->schedobj (grepped exhaustively: no such assignment exists in
|
||||
* that case block). This is a reasoned, not empirically red/green
|
||||
* -tested, proof -- see design.md's Existing Architecture Analysis:
|
||||
* the guarantee holds today for this structural reason (bug-1773),
|
||||
* independent of any new code this feature adds; there is no existing
|
||||
* production bug for a RED phase to catch here, only a future
|
||||
* regression (job->schedobj being reassigned on update) this test now
|
||||
* guards against.
|
||||
*
|
||||
* 5. test_differing_task_counts_do_not_collide_in_unsatisfiable_cache:
|
||||
* Req 5.4, fresh-ingest path only (snapshot-restore is the documented,
|
||||
* pre-existing bug-1772 exception, out of this test's scope). Two
|
||||
* otherwise-identical jobs, differing ONLY in requested task count,
|
||||
* are ingested fresh into the SAME core (so their resreq_fp's other
|
||||
* components -- select_node_id/rusage_hash -- are guaranteed
|
||||
* identical). Reuses scheduler-allocation's own test_alloc_cache.c
|
||||
* conventions (cache_insert()/cache_lookup() driven directly against
|
||||
* real primary schedobj pointers) combined with this file's own
|
||||
* fresh-ingest technique. Empirically verified meaningful: with
|
||||
* core_events.c's apply_job_task_count() call temporarily commented
|
||||
* out, both jobs collapse to the IDENTICAL resreq_fp and this test
|
||||
* then FAILS one assertion earlier than cache_lookup() itself -- at
|
||||
* its own fingerprint sanity check (job A's and job B's
|
||||
* resreq_fp.min_tasks, expected to differ, are instead both 1) --
|
||||
* confirmed by temporarily disabling the wiring, rebuilding this
|
||||
* binary in isolation, observing that failure, then reverting to a
|
||||
* git-clean state before finalizing this test.
|
||||
*/
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
|
|
@ -144,6 +193,15 @@ extern int scheduler_req_handler(xce_request_t*, void*);
|
|||
#define JOBID_PARITY ((uint64_t)910201ULL)
|
||||
#define JOBID_SINGLE_TASK ((uint64_t)910301ULL)
|
||||
|
||||
/* task 3.2 additions (Req 1.4, 5.4) -- see this file's own top-of-file
|
||||
* header comment's task-3.2 addendum, below the task-3.1 narrative, for
|
||||
* what each of these two tests proves. (The driver/simulation parity test,
|
||||
* design.md's "Project Invariant Cross-Check" commitment, now lives in its
|
||||
* own separate file, test_maxtasks_wiring_sim_driver_parity.c.) */
|
||||
#define JOBID_UPDATE_IMMUNE ((uint64_t)910501ULL)
|
||||
#define JOBID_CACHE_A ((uint64_t)910601ULL)
|
||||
#define JOBID_CACHE_B ((uint64_t)910602ULL)
|
||||
|
||||
/* ════════════════════════════════════════════════════════════════════════
|
||||
* __wrap_xcecli_start / __wrap_xcecli_join -- trivial always-succeed
|
||||
* doubles, identical rationale/shape to every other real-scheduler_srcs
|
||||
|
|
@ -782,6 +840,305 @@ test_single_task_job_dispatch_and_host_selection_unchanged_via_real_allocator(vo
|
|||
"exactly 1.0");
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Test 4 -- Req 1.4: an update never changes the already-ingested task */
|
||||
/* count (job->schedobj is never rebuilt by JOB_UPDATE) */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* Design.md's Existing Architecture Analysis: core_events.c's JOB_UPDATE
|
||||
* handler (live) replaces job->resreq with a freshly parse_resreq()'d
|
||||
* object when updated->submit->resreq is non-NULL, but never reassigns
|
||||
* job->schedobj (grepped exhaustively: no `job->schedobj =` assignment
|
||||
* anywhere in the JOB_UPDATE case, core_events.c:1174-1257) -- so
|
||||
* scheduler.c's real dispatch (job->schedobj->u.primary->resreq,
|
||||
* scheduler.c:315) never sees an update at all, for ANY field, not only
|
||||
* task count (bug-1773). Requirement 1.4's guarantee already holds today
|
||||
* for this structural reason, not because this feature actively re-wires
|
||||
* anything on update (design.md, Non-Goals) -- this test's job is to PROVE
|
||||
* the guarantee holds, not to add new production wiring.
|
||||
*
|
||||
* A real multi-task job (mintasks=4/maxtasks=7, deliberately distinct from
|
||||
* every other test's own fixture values in this file) is ingested fresh,
|
||||
* then a JOB_UPDATE event for the SAME jobid is driven with BOTH a
|
||||
* different resreq string ("rusage[mem=2]" instead of "type == any") AND a
|
||||
* different requested task count (mintasks=1/maxtasks=1) in its own
|
||||
* job_submit_data_t -- exactly the scenario Req 1.4 describes ("a job's
|
||||
* resource request is updated"). Confirms job->resreq WAS genuinely
|
||||
* replaced (proving the update was not silently a no-op, which would make
|
||||
* the immunity assertion below vacuous), and that job->schedobj->u.primary
|
||||
* ->resreq -- what the real allocator dispatch actually reads -- is the
|
||||
* EXACT SAME object, with the SAME minTasks/maxTasks, ingest originally
|
||||
* produced, completely unaffected by the update's own different task
|
||||
* count.
|
||||
*
|
||||
* Meaningfulness (reasoned, per this task's own brief, rather than
|
||||
* empirically red/green-tested -- the failure mode guarded against is a
|
||||
* future production change, not a bug present today): this test would fail
|
||||
* if a future change to the JOB_UPDATE case started reassigning
|
||||
* job->schedobj (e.g. rebuilding it via core_build_schedobj() the way
|
||||
* core_build_job() does), since apply_job_task_count() applied there would
|
||||
* then pick up the UPDATE's own (differing) mintasks/maxtasks rather than
|
||||
* ingest's -- the post-update assertions below would read 1/1 instead of
|
||||
* the expected 4/7.
|
||||
*/
|
||||
static void
|
||||
test_resource_request_update_never_changes_dispatched_task_count(void)
|
||||
{
|
||||
xce_sched_core_t core;
|
||||
xce_queue_t* queue;
|
||||
xce_core_event_t queue_event;
|
||||
xce_job_t* job;
|
||||
xce_job_t* job_ptrs[1];
|
||||
xce_core_event_t job_event;
|
||||
xce_sched_job_t* sjob;
|
||||
xce_primary_resreq_t* ingest_time_primary;
|
||||
xce_job_t* update_job;
|
||||
xce_core_event_t update_event;
|
||||
int rc;
|
||||
|
||||
rc = xce_sched_core_init(&core);
|
||||
TEST_ASSERT_TRUE_MESSAGE(rc >= 0, "fixture: xce_sched_core_init() must "
|
||||
"succeed");
|
||||
|
||||
queue = make_wire_queue("normal", 1);
|
||||
memset(&queue_event, 0, sizeof(queue_event));
|
||||
queue_event.type = XCE_CORE_EVENT_QUEUE_UPDATE;
|
||||
queue_event.u.queue_update.queue = queue;
|
||||
rc = xce_core_push_events(&core, &queue_event, 1);
|
||||
TEST_ASSERT_TRUE_MESSAGE(rc >= 0, "fixture: real QUEUE_UPDATE ingest "
|
||||
"must succeed");
|
||||
|
||||
job = make_push_job(JOBID_UPDATE_IMMUNE, "type == any", "alice", "normal",
|
||||
"proj1", 4, 7);
|
||||
job_ptrs[0] = job;
|
||||
|
||||
memset(&job_event, 0, sizeof(job_event));
|
||||
job_event.type = XCE_CORE_EVENT_JOBS_PUSH;
|
||||
job_event.u.jobs_push.njobs = 1;
|
||||
job_event.u.jobs_push.jobs = job_ptrs;
|
||||
|
||||
rc = xce_core_push_events(&core, &job_event, 1);
|
||||
TEST_ASSERT_TRUE_MESSAGE(rc >= 0, "fixture: real JOBS_PUSH ingest must "
|
||||
"succeed");
|
||||
|
||||
sjob = sched_get_job(&core, JOBID_UPDATE_IMMUNE);
|
||||
TEST_ASSERT_NOT_NULL(sjob);
|
||||
TEST_ASSERT_NOT_NULL(sjob->schedobj);
|
||||
TEST_ASSERT_EQUAL_INT(XCE_RESREQ_PRIMARY, sjob->schedobj->tag);
|
||||
ingest_time_primary = sjob->schedobj->u.primary->resreq;
|
||||
TEST_ASSERT_NOT_NULL(ingest_time_primary);
|
||||
TEST_ASSERT_EQUAL_INT_MESSAGE(
|
||||
4, ingest_time_primary->minTasks,
|
||||
"fixture: ingest must derive the job's real minTasks before the "
|
||||
"update is driven");
|
||||
TEST_ASSERT_EQUAL_INT_MESSAGE(
|
||||
7, ingest_time_primary->maxTasks,
|
||||
"fixture: ingest must derive the job's real maxTasks before the "
|
||||
"update is driven");
|
||||
|
||||
/* ── Drive a real JOB_UPDATE: a DIFFERENT resreq string AND a
|
||||
* DIFFERENT requested task count for the SAME job ─────────────────── */
|
||||
update_job = make_push_job(JOBID_UPDATE_IMMUNE, "rusage[mem=2]", "alice",
|
||||
"normal", "proj1", 1, 1);
|
||||
|
||||
memset(&update_event, 0, sizeof(update_event));
|
||||
update_event.type = XCE_CORE_EVENT_JOB_UPDATE;
|
||||
update_event.u.job_update.jobid = JOBID_UPDATE_IMMUNE;
|
||||
update_event.u.job_update.job = update_job;
|
||||
|
||||
rc = xce_core_push_events(&core, &update_event, 1);
|
||||
TEST_ASSERT_TRUE_MESSAGE(rc >= 0, "real JOB_UPDATE ingest must succeed");
|
||||
|
||||
sjob = sched_get_job(&core, JOBID_UPDATE_IMMUNE);
|
||||
TEST_ASSERT_NOT_NULL(sjob);
|
||||
|
||||
/* Sanity: the update DID genuinely replace job->resreq (not a silent
|
||||
* no-op) -- job->resreq is now a fresh object showing parse_resreq_
|
||||
* primary()'s own bare 1/1 default (JOB_UPDATE never calls apply_job_
|
||||
* task_count(), design.md), confirming the assertions below are a
|
||||
* meaningful immunity proof, not a vacuous one from an update that
|
||||
* never took effect. */
|
||||
TEST_ASSERT_NOT_NULL(sjob->resreq);
|
||||
TEST_ASSERT_EQUAL_INT(XCE_RESREQ_PRIMARY, sjob->resreq->tag);
|
||||
TEST_ASSERT_FALSE_MESSAGE(
|
||||
sjob->resreq->u.primary == ingest_time_primary,
|
||||
"fixture: JOB_UPDATE must have replaced job->resreq with a "
|
||||
"genuinely NEW object, not left the old one in place, for this "
|
||||
"test's immunity assertion to be meaningful");
|
||||
TEST_ASSERT_EQUAL_INT_MESSAGE(
|
||||
1, sjob->resreq->u.primary->minTasks,
|
||||
"fixture: job->resreq (freshly reparsed by JOB_UPDATE) must show "
|
||||
"parse_resreq_primary()'s own bare default, confirming JOB_UPDATE "
|
||||
"never calls apply_job_task_count()");
|
||||
|
||||
/* ── The Req 1.4 proof: job->schedobj->u.primary->resreq (what the
|
||||
* real allocator dispatch reads, scheduler.c:315) is the EXACT SAME
|
||||
* object, with the EXACT SAME ingest-time task count, unaffected by
|
||||
* the update -- because JOB_UPDATE never reassigns job->schedobj. ──── */
|
||||
TEST_ASSERT_NOT_NULL(sjob->schedobj);
|
||||
TEST_ASSERT_TRUE_MESSAGE(
|
||||
sjob->schedobj->u.primary->resreq == ingest_time_primary,
|
||||
"job->schedobj->u.primary->resreq must remain the EXACT SAME "
|
||||
"object ingest originally built -- JOB_UPDATE must never rebuild "
|
||||
"job->schedobj");
|
||||
TEST_ASSERT_EQUAL_INT_MESSAGE(
|
||||
4, sjob->schedobj->u.primary->resreq->minTasks,
|
||||
"Req 1.4: the job's dispatched minTasks must remain the "
|
||||
"ingest-time value (4), unaffected by the update's own different "
|
||||
"mintasks (1)");
|
||||
TEST_ASSERT_EQUAL_INT_MESSAGE(
|
||||
7, sjob->schedobj->u.primary->resreq->maxTasks,
|
||||
"Req 1.4: the job's dispatched maxTasks must remain the "
|
||||
"ingest-time value (7), unaffected by the update's own different "
|
||||
"maxtasks (1)");
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Test 5 -- Req 5.4: differing task counts never collide in the */
|
||||
/* unsatisfiable-resreq cache, on the fresh-ingest path */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* Req 5.4 (fresh-ingest path only; snapshot-restore is the documented,
|
||||
* pre-existing bug-1772 exception -- design.md's Testing Strategy). Two
|
||||
* otherwise-identical jobs (same resreq string, same user/queue/project)
|
||||
* that differ ONLY in requested task count must never collide in
|
||||
* scheduler-allocation's unsatisfiable-resreq cache (sched/alloc_cache.h).
|
||||
* core_build_primary_schedobj() (core_events.c) computes primary->
|
||||
* resreq_fp.min_tasks/max_tasks directly from resreq->minTasks/maxTasks --
|
||||
* the exact field this feature's apply_job_task_count() call
|
||||
* (core_events.c, immediately before core_build_schedobj()) sets from the
|
||||
* job's real requested count. Two such jobs, ingested fresh into the SAME
|
||||
* core/resmgr (so their resreq_fp's OTHER components -- select_node_id,
|
||||
* rusage_hash -- are guaranteed identical, isolating task count as the
|
||||
* only possible source of a difference), must therefore produce DIFFERENT
|
||||
* cache keys: an unsatisfiable outcome cached for one must not hit for the
|
||||
* other.
|
||||
*
|
||||
* This reuses scheduler-allocation's own alloc_cache test conventions
|
||||
* (test_alloc_cache.c: cache_insert()/cache_lookup() driven directly
|
||||
* against real primary schedobj pointers, a bare xce_scheduler_t with only
|
||||
* unsatisfiable_cache constructed) combined with REAL job ingest via
|
||||
* core_build_job() (this file's own established fresh-ingest technique)
|
||||
* rather than test_alloc_cache.c's own hand-built xce_primary_schedobj_t
|
||||
* fixtures -- this is the genuinely new combination this task adds.
|
||||
*
|
||||
* Empirically verified meaningful (not merely reasoned): with
|
||||
* core_events.c's apply_job_task_count() call temporarily commented out
|
||||
* (the pre-fix always-1/1 behavior bug-1770 describes), both jobs below
|
||||
* collapse to the IDENTICAL resreq_fp (min_tasks=max_tasks=1 for both,
|
||||
* regardless of their different requested counts), and this test's own
|
||||
* cache_lookup() assertion for job B FAILS (a real collision: rc==1, a
|
||||
* false hit) -- confirmed by temporarily commenting out that one line,
|
||||
* rebuilding this binary in isolation, observing the failure, then
|
||||
* reverting the file to a git-clean state before finalizing this test.
|
||||
*/
|
||||
static void
|
||||
test_differing_task_counts_do_not_collide_in_unsatisfiable_cache(void)
|
||||
{
|
||||
xce_scheduler_t sched;
|
||||
xce_queue_t* queue;
|
||||
xce_core_event_t queue_event;
|
||||
xce_job_t* job_a;
|
||||
xce_job_t* job_b;
|
||||
xce_job_t* job_ptrs[2];
|
||||
xce_core_event_t job_event;
|
||||
xce_sched_job_t* sjob_a;
|
||||
xce_sched_job_t* sjob_b;
|
||||
int out_reason = -1;
|
||||
int rc;
|
||||
|
||||
memset(&sched, 0, sizeof(sched));
|
||||
rc = xce_sched_core_init(&(sched.core));
|
||||
TEST_ASSERT_TRUE_MESSAGE(rc >= 0, "fixture: xce_sched_core_init() must "
|
||||
"succeed");
|
||||
|
||||
cache_clear(&sched);
|
||||
TEST_ASSERT_NOT_NULL_MESSAGE(
|
||||
sched.unsatisfiable_cache,
|
||||
"fixture: cache_clear() must construct a real unsatisfiable_cache "
|
||||
"table (mirrors the real per-session construction, main.c's "
|
||||
"xce_core_set_cache_clear_cb() registration)");
|
||||
|
||||
queue = make_wire_queue("normal", 1);
|
||||
memset(&queue_event, 0, sizeof(queue_event));
|
||||
queue_event.type = XCE_CORE_EVENT_QUEUE_UPDATE;
|
||||
queue_event.u.queue_update.queue = queue;
|
||||
rc = xce_core_push_events(&(sched.core), &queue_event, 1);
|
||||
TEST_ASSERT_TRUE_MESSAGE(rc >= 0, "fixture: real QUEUE_UPDATE ingest "
|
||||
"must succeed");
|
||||
|
||||
/* Same resreq string/user/queue/project -- differ ONLY in requested
|
||||
* task count. Both ingested into the SAME core/resmgr, so their
|
||||
* resreq_fp's select_node_id/rusage_hash components are guaranteed
|
||||
* identical -- isolating task count as the only possible source of a
|
||||
* fingerprint difference. */
|
||||
job_a = make_push_job(JOBID_CACHE_A, "rusage[mem=1]", "cache_user",
|
||||
"normal", "cache_proj", 2, 2);
|
||||
job_b = make_push_job(JOBID_CACHE_B, "rusage[mem=1]", "cache_user",
|
||||
"normal", "cache_proj", 3, 3);
|
||||
job_ptrs[0] = job_a;
|
||||
job_ptrs[1] = job_b;
|
||||
|
||||
memset(&job_event, 0, sizeof(job_event));
|
||||
job_event.type = XCE_CORE_EVENT_JOBS_PUSH;
|
||||
job_event.u.jobs_push.njobs = 2;
|
||||
job_event.u.jobs_push.jobs = job_ptrs;
|
||||
|
||||
rc = xce_core_push_events(&(sched.core), &job_event, 1);
|
||||
TEST_ASSERT_TRUE_MESSAGE(rc >= 0, "real JOBS_PUSH ingest must succeed "
|
||||
"for both jobs");
|
||||
|
||||
sjob_a = sched_get_job(&(sched.core), JOBID_CACHE_A);
|
||||
sjob_b = sched_get_job(&(sched.core), JOBID_CACHE_B);
|
||||
TEST_ASSERT_NOT_NULL(sjob_a);
|
||||
TEST_ASSERT_NOT_NULL(sjob_b);
|
||||
TEST_ASSERT_NOT_NULL(sjob_a->schedobj);
|
||||
TEST_ASSERT_NOT_NULL(sjob_b->schedobj);
|
||||
TEST_ASSERT_EQUAL_INT(XCE_RESREQ_PRIMARY, sjob_a->schedobj->tag);
|
||||
TEST_ASSERT_EQUAL_INT(XCE_RESREQ_PRIMARY, sjob_b->schedobj->tag);
|
||||
|
||||
/* Sanity: the two jobs' real, ingest-derived fingerprints DO differ in
|
||||
* exactly (and only) their task-count component -- confirms this
|
||||
* test's premise before exercising the cache itself. */
|
||||
TEST_ASSERT_EQUAL_INT_MESSAGE(
|
||||
2, sjob_a->schedobj->u.primary->resreq_fp.min_tasks,
|
||||
"job A's real ingest-derived resreq_fp.min_tasks must reflect its "
|
||||
"own requested task count");
|
||||
TEST_ASSERT_EQUAL_INT_MESSAGE(
|
||||
3, sjob_b->schedobj->u.primary->resreq_fp.min_tasks,
|
||||
"job B's real ingest-derived resreq_fp.min_tasks must reflect its "
|
||||
"own (different) requested task count");
|
||||
TEST_ASSERT_EQUAL_UINT64_MESSAGE(
|
||||
sjob_a->schedobj->u.primary->resreq_fp.rusage_hash,
|
||||
sjob_b->schedobj->u.primary->resreq_fp.rusage_hash,
|
||||
"fixture: both jobs share the identical resreq string, so their "
|
||||
"rusage_hash fingerprint component must be identical -- isolating "
|
||||
"task count as the only differing component");
|
||||
|
||||
/* ── The Req 5.4 proof: an unsatisfiable outcome cached for job A
|
||||
* must NOT produce a cache hit for job B. ──────────────────────────── */
|
||||
rc = cache_insert(&sched, sjob_a->schedobj, 7 /* arbitrary category */);
|
||||
TEST_ASSERT_EQUAL_INT_MESSAGE(
|
||||
0, rc, "fixture: cache_insert() for job A must succeed");
|
||||
|
||||
rc = cache_lookup(&sched, sjob_b->schedobj, &out_reason);
|
||||
TEST_ASSERT_EQUAL_INT_MESSAGE(
|
||||
0, rc,
|
||||
"Req 5.4: job B (a different requested task count, otherwise "
|
||||
"identical) must NOT hit job A's cached unsatisfiable outcome");
|
||||
|
||||
/* Sanity: the cache mechanism itself genuinely works -- job A's OWN
|
||||
* key IS a hit, with the SAME reason category given at insert time.
|
||||
* Without this, the miss above could just as easily mean the cache is
|
||||
* dead altogether, not that it correctly distinguishes task counts. */
|
||||
rc = cache_lookup(&sched, sjob_a->schedobj, &out_reason);
|
||||
TEST_ASSERT_EQUAL_INT_MESSAGE(
|
||||
1, rc, "sanity: job A's own key must hit its own cached entry");
|
||||
TEST_ASSERT_EQUAL_INT(7, out_reason);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
UNITY_BEGIN();
|
||||
|
|
@ -790,5 +1147,7 @@ int main(void)
|
|||
test_fresh_ingest_and_snapshot_restore_derive_identical_task_count_for_equivalent_job);
|
||||
RUN_TEST(
|
||||
test_single_task_job_dispatch_and_host_selection_unchanged_via_real_allocator);
|
||||
RUN_TEST(test_resource_request_update_never_changes_dispatched_task_count);
|
||||
RUN_TEST(test_differing_task_counts_do_not_collide_in_unsatisfiable_cache);
|
||||
return UNITY_END();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue