feat(scheduler): show event time/session in sim echo, total sessions on replay load

repl_print_event_summary() (interactive REPL event echo) now prefixes
each echoed event with "[sim] t=<ns> (<human>) session=<N>", using the
same xce_core_now()/repl_format_ts_human()/session_count sources "info
session" already reports. Uses session_count+1, not the raw count:
events stream in and are echoed individually before the ReplaySession/
begin_round message that increments session_count is even read (file
order is event, event, ..., ReplaySession), so an echoed event always
belongs to the session about to begin.

Add sim_prescan_session_count() (sim.c): scans the replay file from the
current position via shape-only classification (mirroring sim_loop.c's
own ReplayEvent/ReplaySession/SnapshotEntry dispatch), counts
ReplaySession messages, then rewinds via fseek back to the exact ftell()
position -- same rewind technique sim_locate_and_load_snapshot() already
uses. Wired into sched_sim_driver_start(): prints "[sim] replay file
contains N sessions" once at load, non-fatal on scan failure.

Add test_replay_load_reports_total_session_count; extend
test_step_echoes_events_before_session_decisions with t=/session=1
assertions.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Rongsong Shen 2026-08-20 07:48:43 +00:00
parent 4e3e6332c5
commit 8abab049f4
No known key found for this signature in database
GPG key ID: 5BCDAAE0123E9FE2
4 changed files with 221 additions and 3 deletions

View file

@ -1779,11 +1779,74 @@ static void test_step_echoes_events_before_session_decisions(void)
"events must be echoed BEFORE the session's "
"resulting decision (bug-1595)");
{
char* ts_line_pos = strstr(captured, "[sim] t=");
TEST_ASSERT_NOT_NULL_MESSAGE(
ts_line_pos,
"each echoed event must be preceded by a t=.../session=... "
"line so an operator can tell when/which session it happened "
"in");
TEST_ASSERT_TRUE_MESSAGE(
ts_line_pos < jobpush_pos,
"the t=.../session=... line must precede the event it "
"describes");
TEST_ASSERT_NOT_NULL_MESSAGE(
strstr(captured, "session=1"),
"the first (and only) session's events must be tagged "
"session=1 -- xce_repl_on_begin_round() increments "
"session_count before this session's event batch is pushed");
}
free(captured);
printf("test_step_echoes_events_before_session_decisions: PASS\n");
}
/*
* New requirement (2026-08-20): loading a replay file reports its total
* session count up front (sim.c's sched_sim_driver_start(), via
* sim_prescan_session_count()'s ftell/fseek pre-scan), so an operator knows
* how many `step`s exist before starting to walk through them.
*/
static void test_replay_load_reports_total_session_count(void)
{
char replay_path[PATH_MAX];
char aux_dir[PATH_MAX];
char script_path[PATH_MAX];
char capture_path[PATH_MAX];
FILE* f;
char* captured;
f = write_header_and_snapshot(replay_path, sizeof(replay_path),
"_sessioncount");
TEST_ASSERT_NOT_NULL(f);
append_jobs_push_event(f, 1000ULL, 8181ULL, "normal");
append_replay_session(f, 1500ULL);
append_jobs_push_event(f, 2000ULL, 8182ULL, "normal");
append_replay_session(f, 2500ULL);
append_end_of_stream_marker(f);
fclose(f);
make_tmp_dir(aux_dir, sizeof(aux_dir), "_sessioncountaux");
snprintf(script_path, sizeof(script_path), "%s/script.txt", aux_dir);
snprintf(capture_path, sizeof(capture_path), "%s/capture.out", aux_dir);
write_text_file(script_path, "quit\n");
captured = run_group_d_and_capture(replay_path, script_path,
capture_path);
TEST_ASSERT_NOT_NULL_MESSAGE(
strstr(captured, "[sim] replay file contains 2 sessions"),
"loading a 2-session replay file must report the total session "
"count up front, before any step/continue command runs");
free(captured);
printf("test_replay_load_reports_total_session_count: PASS\n");
}
int main(void)
{
UNITY_BEGIN();
@ -1818,6 +1881,7 @@ int main(void)
RUN_TEST(test_event_breakpoint_pauses_repl_at_matching_event);
RUN_TEST(test_decision_breakpoint_pauses_after_decision_output);
RUN_TEST(test_step_echoes_events_before_session_decisions);
RUN_TEST(test_replay_load_reports_total_session_count);
return UNITY_END();
}