test(scheduler-sim-decision-parity): prove capacity-aware parity under contention (task 4.1)

Adds an integration test comparing round-by-round resInUse and scheduling
outcomes between a real driven normal-mode recording and a simulation-mode
replay of the identical contention scenario (worker capacity 10.0, jobs
wanting 8.0/5.0/2.0, plus a 4th job proving cross-round persistence).

Confirmed (by direct read of sim_picker_thread_fn(), independently
re-verified in review) that sim's live picker is structurally PEND-only --
it has no capacity-check/dispatch path for a freshly-evaluated job. This
means task 1.2's single-round fixture cannot be literally replayed-and-
diffed for full parity: that comparison would be tautological for
freshly-arriving jobs (sim always PENDs them regardless of accounting
correctness) and can't prove multi-round persistence anyway. Built instead
as a real recording plus a hand-crafted sim fixture modeling the identical
facts, including an already-resolved-before-replay job to exercise
reconciliation -- the same documented-carve-out approach test_sim_equivalence.c
already established for PEND-only proofs, applied here to reconciled jobs too.

No production code touched (task 3 already completed the feature). RED
phase proven by temporarily reverting task 3's reconciliation call site:
new test failed with "Expected 10 Was 0", restored and green.

48/49 scheduler tests pass; the 1 failure is pre-existing bug-1560
(unrelated).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Rongsong Shen 2026-08-22 10:53:08 +00:00
parent 1264409478
commit b31907324c
No known key found for this signature in database
GPG key ID: 5BCDAAE0123E9FE2
3 changed files with 1399 additions and 1 deletions

View file

@ -62,7 +62,7 @@
- _Boundary: Sim Driver Round-Boundary Accounting, Recorded-Decision Reconciliation_
- [ ] 4. Validation
- [ ] 4.1 (P) Prove capacity-aware parity under contention
- [x] 4.1 (P) Prove capacity-aware parity under contention
- Using the resource-contention fixture (task 1.2), replay it in simulation mode and compare worker and shared resource-in-use totals against the equivalent normal-mode recording at every round
- Assert simulation mode never makes a scheduling decision (dispatch where normal mode pended, or vice versa) that the normal-mode recording of the same state did not also make
- Observable completion: the contention fixture replay produces byte-for-byte identical resource-in-use totals and scheduling outcomes to its normal-mode recording, at every round, not just the final one
@ -98,3 +98,4 @@
- (task 2.4) `xce_decision_t` objects built via `make_dispatch_decision()`/`make_pend_decision()` are never freed anywhere in this codebase on any live path (verified by grep across `scheduler/src/*.c`) -- this is an established, accepted pattern here, not something to "fix" if you see it under `detect_leaks=1`. Don't add a free for it; that would deviate from the codebase's own convention without a broader cleanup pass.
- (task 3) `get_resvals()` (resource.c) returns `nres` (the count filled in) on success, NOT `0` -- a test-authoring bug (bug-1622, not production) came from assuming the latter. If you write a test against `get_resvals()`, check its actual return-value contract first.
- (task 3) Feature is now end-to-end wired and independently confirmed working (reviewer removed the call site itself and watched both integration tests fail for the right reason, then restored and watched them pass). Tasks 4.1-4.3 (Validation) can now exercise the real, complete path -- no more "not fully wired yet" caveats apply.
- (task 4.1) `sim_picker_thread_fn()` is confirmed (by direct read, independently re-confirmed by the reviewer) to be structurally PEND-only -- it has no capacity-check/dispatch path for a job it evaluates fresh. This means task 1.2's fixture (or any single-round, freshly-arriving-jobs fixture) can NEVER be literally replayed-and-diffed for full dispatch/PEND parity -- sim's picker always PENDs a fresh job regardless of whether resource accounting is correct, so that comparison would be tautological for freshly-arriving jobs (though still meaningful for reconciled/already-resolved jobs). If a later task needs "real recording vs. sim replay" parity proof, build it the way task 4.1 did: a real driven normal-mode recording plus a hand-crafted sim-mode fixture modeling the identical facts (including at least one already-resolved-before-replay job to exercise reconciliation), not a literal single-file replay-and-diff. This is a real architectural limit, not a testing shortcut -- true dispatch-decision parity for freshly-arriving jobs is scheduler-allocation's (a separate, not-yet-designed spec) job, out of this feature's scope.

View file

@ -810,6 +810,29 @@ sched_sim_round_boundary_reconciliation_test = executable(
dependencies: [scheduler_test_deps],
install: false)
# Record-then-replay-and-diff parity proof for task 4.1 (Req 1.4, 2.1, 2.2):
# extends task 1.2's resource-contention scenario (worker capacity 10.0,
# jobs wanting 8.0/5.0/2.0) to an actual round-by-round comparison between a
# REAL, driven normal-mode recording (this file's own Part A: real
# builtin_fcfs picker + a capacity-aware allocator, same technique as
# sched_sim_resource_contention_test, extended across TWO real rounds) and
# a hand-crafted simulation-mode `.replay` fixture (Part B: same
# JOB_STATE_CHANGE-precedes-matching-DISPATCH-decision reconciliation
# trigger sched_sim_round_boundary_reconciliation_test establishes,
# extended to BOTH jobs A and C together). Links a REAL (not no-op)
# sched_account_jobs() reimplementation, augmented with a round-boundary
# resInUse snapshot side effect, giving genuine per-round observability
# into simulation mode's own accounting -- not just the final state. See
# this file's own header comment for the full two-fixture design and why a
# straight replay of task 1.2's own recorded file (unmodified) cannot prove
# this by itself.
sched_sim_contention_parity_test = executable(
'sched_sim_contention_parity_test',
['test_sim_contention_parity.c'],
include_directories:[incdir],
dependencies: [scheduler_test_deps],
install: false)
# Contract test for the interactive simulation REPL's execution-control slice
# (scheduler-core spec, task 12.1, Req 5 AC 22): starting simulation with
# --interactive pauses before any event is processed, and a `step N` command
@ -1146,6 +1169,9 @@ test('scheduler sim resource contention test',
test('scheduler sim round boundary reconciliation test',
sched_sim_round_boundary_reconciliation_test, suite: 'scheduler',
env: ['ASAN_OPTIONS=detect_leaks=0'])
test('scheduler sim contention parity test',
sched_sim_contention_parity_test, suite: 'scheduler',
env: ['ASAN_OPTIONS=detect_leaks=0'])
test('scheduler repl execution control test',
sched_repl_execution_control_test, suite: 'scheduler',
env: ['ASAN_OPTIONS=detect_leaks=0'])

File diff suppressed because it is too large Load diff