test(scheduler-core): REPL step/continue equivalence to batch simulation (task 12.4)

Adds the final task of "Core: Interactive REPL" (Req 5 AC 22): proves
the REPL's own documented invariant -- "step/continue to completion
produces byte-identical output to batch --sim" (design.md SimDriver
Invariants).

test_repl_equivalence.c runs the same sched_sim_driver_run() on the
same 3-session/9-decision fixture twice: once batch (interactive=
false), once REPL-driven via freopen()'d scripted "step 1\ncontinue\n"
stdin into the real repl_command_loop()/readline() path (same
mechanism test_repl_execution_control.c established) -- then
structurally decodes both runs' --sim-output and compares decision
content. Test-only; zero production code changed.

RED-phase probe (planted in xce_repl_on_event(), reverted, zero
residue) confirmed the comparison is real: corrupting one job's id
under interactive mode broke exactly this test plus the 3 other REPL
tests that share the same hook, none else.

Scheduler suite: 37/37 clean (was 36/36). Task group 12 (Interactive
REPL, tasks 12.1-12.4) is now complete.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JPPXeKSUXUqcqvzNXY1rzJ
This commit is contained in:
Rongsong Shen 2026-08-07 10:49:08 +00:00
parent 2329dbf2a8
commit 829fbe41dc
Signed by: rshen
SSH key fingerprint: SHA256:8Vf2pZ3h6rJa7EhGK+WaAQ9Mta/apZvteW6g9U/WKKk
4 changed files with 717 additions and 1 deletions

View file

@ -736,6 +736,31 @@ sched_repl_snapshot_params_test = executable(
dependencies: [scheduler_test_deps, libedit_dep],
install: false)
# Contract test for REPL step/continue-to-completion vs batch simulation
# equivalence (scheduler-core spec, task 12.4, Req 5 AC 22 "Deterministic
# replay is preserved"): running a fixture through the REPL via a scripted
# `step`/`continue` command sequence to completion must produce the SAME
# decision sequence as running the identical fixture through batch
# (non-interactive) simulation mode. Unlike task 11.6's
# test_sim_equivalence.c (which compares the NORMAL-mode driver against the
# SIMULATION driver), this compares the SAME sched_sim_driver_run() against
# itself, differing only in `sim->interactive` -- proving the REPL only
# controls WHEN events are processed, never WHAT. Same white-box #include
# pattern as sched_repl_execution_control_test (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_record.c, sim_verify.c,
# snapshot.c/snapshot_wire.c/snapshot_load.c, repl.c, repl_break.c,
# repl_info.c, repl_params.c) -- no driver.c: both runs are pure
# simulation-driver replays of one hand-built fixture, never a real
# normal-mode recording session.
sched_repl_equivalence_test = executable(
'sched_repl_equivalence_test',
['test_repl_equivalence.c'],
include_directories:[incdir],
dependencies: [scheduler_test_deps, libedit_dep],
install: false)
# Register as meson tests so `meson test --suite scheduler` runs them all.
# detect_leaks=0 matches the suite convention (fixtures are not torn down).
test('scheduler test', scheduler_test, suite: 'scheduler',
@ -835,3 +860,6 @@ test('scheduler repl breakpoints inspection test',
test('scheduler repl snapshot params test',
sched_repl_snapshot_params_test, suite: 'scheduler',
env: ['ASAN_OPTIONS=detect_leaks=0'])
test('scheduler repl equivalence test',
sched_repl_equivalence_test, suite: 'scheduler',
env: ['ASAN_OPTIONS=detect_leaks=0'])