fix(scheduler): sim mode picker never learns about the initial snapshot's own jobs/queues (bug-1567)
xce_scheduler -i -s <replay>: WARN "failed to resolve job picker plugin (rc=-2)" on load, and every job already present in the replay file's INITIAL snapshot stayed PEND forever -- never even reached the picker, let alone got dispatched. Root cause: sched_sim_driver_start() (sim.c) loads the initial snapshot via xce_sched_core_load_snapshot() BEFORE any picker plugin is registered (sim.h's own documented "Known scope boundary" -- only the picker's NAME is threaded through from the ReplayHeader). sched_resolve_job_picker() therefore always returns -ENOENT there, and xce_sched_core_load_snapshot()'s own picker-rebuild walk (on_queue_update/on_job_push per queue/job) is silently skipped. The real builtin_fcfs picker only gets registered moments later in sched_sim_driver_run() -- but nothing then replayed that rebuild walk, so any job/queue from the INITIAL snapshot (as opposed to one arriving later via a ReplayEvent, which correctly reaches the picker through xce_core_push_events()'s own picker!=NULL check) was permanently invisible to next_job(). Fixed by a new file, sim_picker.c: sim_bootstrap_picker() (replacing sim_loop.c's sim_register_default_picker(), moved out because sim_loop.c was already at its own documented 800-line "zero line-budget headroom" cap) registers the picker AND then replays the missed rebuild walk against it. Wired into scheduler_srcs, sched_sim_isolation_lib, and all 9 white-box test TUs that #include sim_loop.c directly. New regression test (test_sim_event_loop.c): a job baked into a fixture's INITIAL snapshot (not a ReplayEvent) now gets a live PEND decision. RED confirmed by temporarily no-op'ing the rebuild walk (test failed as expected), GREEN with the real fix. Full scheduler suite green (41/41, excluding the pre-existing unrelated bug-1560). Note: sim mode still never DISPATCHes (only PENDs) -- that is a separate, intentionally out-of-scope gap (real resource-matching allocation belongs to the not-yet-designed scheduler-allocation spec), not addressed here. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
0f1df4998e
commit
0c8e417bda
14 changed files with 395 additions and 93 deletions
|
|
@ -524,7 +524,8 @@ sched_sim_event_loop_test = executable(
|
|||
# boundary doc comment legitimately names xcecli_ctx_t/xce_cluster_config_t
|
||||
# in prose). link_with establishes the build-order dependency on
|
||||
# sched_sim_isolation_lib (parent meson.build -- sim.c + sim_loop.c +
|
||||
# sim_record.c compiled together, isolated from the rest of the scheduler);
|
||||
# sim_picker.c (bug-1567's sim_loop.c-cap-driven sibling) + sim_record.c
|
||||
# compiled together, isolated from the rest of the scheduler);
|
||||
# XCE_SIM_*_PATH bake in absolute paths the same way XCE_CORE_*_PATH does
|
||||
# above.
|
||||
sched_sim_isolation_test = executable(
|
||||
|
|
@ -542,6 +543,9 @@ sched_sim_isolation_test = executable(
|
|||
'-DXCE_SIM_LOOP_C_PATH="'
|
||||
+ (meson.current_source_dir() / '..' / 'src' / 'sim_loop.c')
|
||||
+ '"',
|
||||
'-DXCE_SIM_PICKER_C_PATH="'
|
||||
+ (meson.current_source_dir() / '..' / 'src' / 'sim_picker.c')
|
||||
+ '"',
|
||||
'-DXCE_SIM_RECORD_C_PATH="'
|
||||
+ (meson.current_source_dir() / '..' / 'src' / 'sim_record.c')
|
||||
+ '"',
|
||||
|
|
|
|||
|
|
@ -84,6 +84,7 @@
|
|||
#include "../src/repl_params.c"
|
||||
#include "../src/sim.c"
|
||||
#include "../src/sim_loop.c"
|
||||
#include "../src/sim_picker.c" /* bug-1567: sched_sim_driver_run() now calls sim_bootstrap_picker() (sim_loop.c-cap sibling) as an extern -- undefined reference at link time otherwise */
|
||||
#include "../src/sim_record.c"
|
||||
#include "../src/sim_verify.c"
|
||||
#include "../src/snapshot.c"
|
||||
|
|
|
|||
|
|
@ -133,6 +133,7 @@
|
|||
#include "../src/repl_params.c"
|
||||
#include "../src/sim.c"
|
||||
#include "../src/sim_loop.c"
|
||||
#include "../src/sim_picker.c" /* bug-1567: sched_sim_driver_run() now calls sim_bootstrap_picker() (sim_loop.c-cap sibling) as an extern -- undefined reference at link time otherwise */
|
||||
#include "../src/sim_record.c"
|
||||
#include "../src/sim_verify.c"
|
||||
#include "../src/snapshot.c"
|
||||
|
|
|
|||
|
|
@ -99,6 +99,7 @@
|
|||
#include "../src/repl_params.c"
|
||||
#include "../src/sim.c"
|
||||
#include "../src/sim_loop.c"
|
||||
#include "../src/sim_picker.c" /* bug-1567: sched_sim_driver_run() now calls sim_bootstrap_picker() (sim_loop.c-cap sibling) as an extern -- undefined reference at link time otherwise */
|
||||
#include "../src/sim_record.c"
|
||||
#include "../src/sim_verify.c"
|
||||
#include "../src/snapshot.c"
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@
|
|||
#include "../src/repl_params.c"
|
||||
#include "../src/sim.c"
|
||||
#include "../src/sim_loop.c"
|
||||
#include "../src/sim_picker.c" /* bug-1567: sched_sim_driver_run() now calls sim_bootstrap_picker() (sim_loop.c-cap sibling) as an extern -- undefined reference at link time otherwise */
|
||||
#include "../src/sim_record.c"
|
||||
#include "../src/sim_verify.c"
|
||||
#include "../src/snapshot.c"
|
||||
|
|
|
|||
|
|
@ -92,6 +92,7 @@
|
|||
#include "../src/repl_params.c"
|
||||
#include "../src/sim.c"
|
||||
#include "../src/sim_loop.c"
|
||||
#include "../src/sim_picker.c" /* bug-1567: sched_sim_driver_run() now calls sim_bootstrap_picker() (sim_loop.c-cap sibling) as an extern -- undefined reference at link time otherwise */
|
||||
#include "../src/sim_record.c"
|
||||
#include "../src/sim_verify.c"
|
||||
#include "../src/snapshot.c"
|
||||
|
|
|
|||
|
|
@ -161,6 +161,7 @@
|
|||
#include "../src/repl_params.c"
|
||||
#include "../src/sim.c"
|
||||
#include "../src/sim_loop.c"
|
||||
#include "../src/sim_picker.c" /* bug-1567: sched_sim_driver_run() now calls sim_bootstrap_picker() (sim_loop.c-cap sibling) as an extern -- undefined reference at link time otherwise */
|
||||
#include "../src/sim_record.c"
|
||||
#include "../src/sim_verify.c"
|
||||
#include "../src/snapshot.c"
|
||||
|
|
|
|||
|
|
@ -82,6 +82,7 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <unity/unity.h>
|
||||
|
||||
|
|
@ -107,6 +108,7 @@
|
|||
#include "../src/repl_params.c"
|
||||
#include "../src/sim.c"
|
||||
#include "../src/sim_loop.c"
|
||||
#include "../src/sim_picker.c" /* bug-1567: sched_sim_driver_run() now calls sim_bootstrap_picker() (sim_loop.c-cap sibling) as an extern -- undefined reference at link time otherwise */
|
||||
#include "../src/sim_record.c"
|
||||
#include "../src/sim_verify.c"
|
||||
#include "../src/snapshot.c"
|
||||
|
|
@ -551,6 +553,179 @@ test_run_processes_multiple_sessions_in_order_and_no_longer_returns_enosys(void)
|
|||
"returns_enosys: PASS\n");
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Test 3 (bug-1567 regression): a job/queue already present in the */
|
||||
/* INITIAL snapshot -- as opposed to arriving later via a ReplayEvent -- */
|
||||
/* must still reach the real picker and get a live decision. */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
/* Same fixture technique as write_header_and_snapshot() above, but (a)
|
||||
* records schedPolicy="builtin_fcfs" (test_sim_verify.c's own
|
||||
* build_fixture_scheduler() precedent -- this file's own copy deliberately
|
||||
* uses a non-matching stub name instead, so it cannot be reused here
|
||||
* unmodified) so sim_bootstrap_picker() (sim_picker.c) registers the REAL
|
||||
* builtin_fcfs plugin, not a no-op stub, and (b) adds one real queue and
|
||||
* one real PEND job directly to core->queues/core->jobs (core_build_queue()/
|
||||
* core_build_job() + sched_add_queue()/sched_add_job(), core_events.c,
|
||||
* already white-box #included above) BEFORE calling sched_record_start() --
|
||||
* so xce_sched_core_save_snapshot() (snapshot.c) captures both into the
|
||||
* INITIAL snapshot itself, not as a later ReplayEvent. */
|
||||
static FILE* write_header_and_snapshot_with_pending_job(char* out_path,
|
||||
size_t out_path_len,
|
||||
const char* suffix,
|
||||
const char* queue_name,
|
||||
uint64_t jobid)
|
||||
{
|
||||
char record_dir[PATH_MAX];
|
||||
xce_scheduler_t sched;
|
||||
xce_queue_t wire_queue;
|
||||
xce_sched_queue_t* q;
|
||||
job_submit_data_t submit;
|
||||
xce_job_t wire_job;
|
||||
xce_sched_job_t* job;
|
||||
int rc;
|
||||
|
||||
make_tmp_dir(record_dir, sizeof(record_dir), suffix);
|
||||
|
||||
memset(&sched, 0, sizeof(sched));
|
||||
mylock_init(&(sched.record_lock));
|
||||
rc = xce_sched_core_init(&(sched.core));
|
||||
TEST_ASSERT_EQUAL_INT(0, rc);
|
||||
sched.core.job_pick_plugin = (char*)"builtin_fcfs";
|
||||
sched.record_dir = record_dir;
|
||||
|
||||
memset(&wire_queue, 0, sizeof(wire_queue));
|
||||
wire_queue.queue = (char*)queue_name;
|
||||
wire_queue.status = QUEUE_STAT_OPEN;
|
||||
wire_queue.priority = 1;
|
||||
q = core_build_queue(&wire_queue);
|
||||
TEST_ASSERT_NOT_NULL(q);
|
||||
TEST_ASSERT_GREATER_OR_EQUAL(0, sched_add_queue(&(sched.core), q));
|
||||
|
||||
memset(&submit, 0, sizeof(submit));
|
||||
submit.queue = (char*)queue_name;
|
||||
submit.user = (char*)"alice";
|
||||
submit.mintasks = 1;
|
||||
submit.maxtasks = 1;
|
||||
|
||||
memset(&wire_job, 0, sizeof(wire_job));
|
||||
wire_job.jobid = jobid;
|
||||
wire_job.state = JOB_STAT_PEND;
|
||||
wire_job.submit = &submit;
|
||||
job = core_build_job(&(sched.core), &wire_job);
|
||||
TEST_ASSERT_NOT_NULL(job);
|
||||
TEST_ASSERT_GREATER_OR_EQUAL(0, sched_add_job(&(sched.core), job));
|
||||
|
||||
rc = sched_record_start(&sched, "fixture.replay");
|
||||
TEST_ASSERT_EQUAL_INT(0, rc);
|
||||
TEST_ASSERT_TRUE(strlen(sched.record_file_path) < out_path_len);
|
||||
strcpy(out_path, sched.record_file_path);
|
||||
|
||||
return sched.record_file;
|
||||
}
|
||||
|
||||
/* Same dup()/dup2() STDOUT_FILENO capture technique test_sim_verify.c's own
|
||||
* run_sim_and_capture_stdout() establishes (this file's white-box TU does
|
||||
* not #include that file, so a plain copy is needed here rather than a
|
||||
* cross-file static call). */
|
||||
static char* run_sim_and_capture_stdout(const char* path, int* out_rc)
|
||||
{
|
||||
sched_sim_args_t args;
|
||||
xce_sched_sim_driver_t sim;
|
||||
char tmp[] = "/tmp/xce_simloop_run_XXXXXX";
|
||||
int fd = mkstemp(tmp);
|
||||
int saved_stdout;
|
||||
off_t len;
|
||||
char* buf;
|
||||
|
||||
TEST_ASSERT_TRUE_MESSAGE(fd >= 0, "mkstemp for stdout capture must "
|
||||
"succeed");
|
||||
|
||||
fflush(stdout);
|
||||
saved_stdout = dup(STDOUT_FILENO);
|
||||
TEST_ASSERT_TRUE_MESSAGE(saved_stdout >= 0, "dup(STDOUT_FILENO) must "
|
||||
"succeed");
|
||||
TEST_ASSERT_TRUE_MESSAGE(dup2(fd, STDOUT_FILENO) >= 0,
|
||||
"dup2 redirect of STDOUT_FILENO must succeed");
|
||||
|
||||
memset(&args, 0, sizeof(args));
|
||||
args.replay_path = path;
|
||||
args.sim_start_ts = SCHED_SIM_START_TS_LATEST;
|
||||
args.sim_speed = 0; /* frozen -- deterministic, no wall-clock wait */
|
||||
|
||||
*out_rc = sched_sim_driver_run(&sim, &args);
|
||||
|
||||
fflush(stdout);
|
||||
dup2(saved_stdout, STDOUT_FILENO);
|
||||
close(saved_stdout);
|
||||
|
||||
len = lseek(fd, 0, SEEK_CUR);
|
||||
TEST_ASSERT_TRUE(len >= 0);
|
||||
|
||||
buf = (char*)calloc(1, (size_t)len + 1);
|
||||
TEST_ASSERT_NOT_NULL(buf);
|
||||
TEST_ASSERT_TRUE(lseek(fd, 0, SEEK_SET) == 0);
|
||||
if (len > 0) {
|
||||
ssize_t nread = read(fd, buf, (size_t)len);
|
||||
TEST_ASSERT_TRUE(nread == len);
|
||||
}
|
||||
close(fd);
|
||||
unlink(tmp);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*
|
||||
* bug-1567: before this fix, sched_sim_driver_start() (sim.c) loaded the
|
||||
* initial snapshot while no picker plugin was registered yet (sim.h's own
|
||||
* "Known scope boundary"), so xce_sched_core_load_snapshot()'s
|
||||
* picker-rebuild walk (on_queue_update/on_job_push) was skipped for the
|
||||
* job/queue this fixture bakes into the INITIAL snapshot -- and nothing
|
||||
* ever replayed that walk once sim_bootstrap_picker() registered the real
|
||||
* picker moments later. The job was therefore invisible to next_job()
|
||||
* forever: no PEND, no DISPATCH, nothing -- exactly the user report this
|
||||
* bug tracks ("no job will be scheduled and all jobs in pend state").
|
||||
* After the fix, sim_bootstrap_picker() (sim_picker.c) replays that walk
|
||||
* itself, so this job -- despite never appearing in a single ReplayEvent
|
||||
* -- still reaches the picker and gets a live PEND decision (this driver
|
||||
* never DISPATCHes at all, a separate, intentionally out-of-scope gap --
|
||||
* see sim_picker_thread_fn()'s own doc comment, sim_loop.c).
|
||||
*/
|
||||
static void
|
||||
test_job_present_only_in_initial_snapshot_still_reaches_the_picker(void)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
FILE* f;
|
||||
int rc;
|
||||
char* captured;
|
||||
|
||||
f = write_header_and_snapshot_with_pending_job(path, sizeof(path),
|
||||
"_initsnap", "normal",
|
||||
4242ULL);
|
||||
TEST_ASSERT_NOT_NULL(f);
|
||||
|
||||
/* One session boundary is enough to trigger one scheduling round --
|
||||
* the job under test arrives via the INITIAL SNAPSHOT, not via any
|
||||
* ReplayEvent appended here (deliberately: zero jobs/queues events in
|
||||
* this stream is the whole point of this regression). */
|
||||
append_replay_session(f, 1000ULL);
|
||||
append_end_of_stream_marker(f);
|
||||
fclose(f);
|
||||
|
||||
captured = run_sim_and_capture_stdout(path, &rc);
|
||||
|
||||
TEST_ASSERT_EQUAL_INT(0, rc);
|
||||
TEST_ASSERT_NOT_NULL_MESSAGE(
|
||||
strstr(captured, "PEND jobid=4242"),
|
||||
"a job present only in the replay file's INITIAL snapshot must "
|
||||
"still reach the real picker and receive a live PEND decision "
|
||||
"(bug-1567)");
|
||||
|
||||
free(captured);
|
||||
printf("test_job_present_only_in_initial_snapshot_still_reaches_the_"
|
||||
"picker: PASS\n");
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
UNITY_BEGIN();
|
||||
|
|
@ -559,6 +734,8 @@ int main(void)
|
|||
test_process_replay_event_advances_virtual_clock_to_exact_event_ts_in_file_order);
|
||||
RUN_TEST(
|
||||
test_run_processes_multiple_sessions_in_order_and_no_longer_returns_enosys);
|
||||
RUN_TEST(
|
||||
test_job_present_only_in_initial_snapshot_still_reaches_the_picker);
|
||||
|
||||
return UNITY_END();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,25 +4,27 @@
|
|||
* or structural check confirms no controller-facing symbol is reachable
|
||||
* from the simulation driver's compiled object" -- plus the AC's own
|
||||
* "confirmed by the struct definition itself, not runtime checks alone"
|
||||
* clause. Scope: sim.h + sim.c + sim_loop.c + sim_record.c + repl.c/repl.h/
|
||||
* repl_break.c/repl_info.c/repl_internal.h/repl_params.c together (task
|
||||
* 11.1 + task 11.2's sibling file + task 11.5's sibling file, the
|
||||
* --sim-output writer + task 12.1's REPL files + task 12.2's own
|
||||
* clause. Scope: sim.h + sim.c + sim_loop.c + sim_picker.c + sim_record.c +
|
||||
* repl.c/repl.h/repl_break.c/repl_info.c/repl_internal.h/repl_params.c
|
||||
* together (task 11.1 + task 11.2's sibling file + task 11.5's sibling
|
||||
* file, the --sim-output writer + task 12.1's REPL files + task 12.2's own
|
||||
* repl_break.c/repl_info.c/repl_internal.h + task 12.3's own repl_params.c,
|
||||
* each an 800-line-cap split of repl.c -- see repl_internal.h's own "Why a
|
||||
* split at all" section) -- NOT a re-audit of core.c (task 4.1's own
|
||||
* territory, test_core_isolation.c) and NOT plugin.c/builtin_fcfs.c (shared
|
||||
* normal-mode infra, out of this task's boundary). sim_verify.c (task 11.4)
|
||||
* is likewise out of scope here -- it is never compiled into
|
||||
* sched_sim_isolation_lib below and carries no isolation-sensitive logic of
|
||||
* its own (pure struct comparison, no I/O); extending this guard to it was
|
||||
* not part of task 11.4's own text and is left as-is. repl.c/repl.h were
|
||||
* added per task 12.1's own text (extending this exact 3-file precedent to
|
||||
* a 5-file one); repl_break.c/repl_info.c/repl_internal.h extended it again
|
||||
* (task 12.2, to an 8-file one); repl_params.c extends it once more (task
|
||||
* 12.3, to a 9-file one) -- all touch xce_sched_sim_driver_t directly or
|
||||
* read/write stdin/stdout, the same category of driver-level code this
|
||||
* guard already covers.
|
||||
* split at all" section -- + bug-1567's own sim_picker.c, the identical
|
||||
* split applied to sim_loop.c once IT hit the same cap) -- NOT a re-audit
|
||||
* of core.c (task 4.1's own territory, test_core_isolation.c) and NOT
|
||||
* plugin.c/builtin_fcfs.c (shared normal-mode infra, out of this task's
|
||||
* boundary). sim_verify.c (task 11.4) is likewise out of scope here -- it
|
||||
* is never compiled into sched_sim_isolation_lib below and carries no
|
||||
* isolation-sensitive logic of its own (pure struct comparison, no I/O);
|
||||
* extending this guard to it was not part of task 11.4's own text and is
|
||||
* left as-is. repl.c/repl.h were added per task 12.1's own text (extending
|
||||
* this exact 3-file precedent to a 5-file one); repl_break.c/repl_info.c/
|
||||
* repl_internal.h extended it again (task 12.2, to an 8-file one);
|
||||
* repl_params.c extends it once more (task 12.3, to a 9-file one);
|
||||
* sim_picker.c extends it a final time (bug-1567, to a 10-file one) -- all
|
||||
* touch xce_sched_sim_driver_t directly or read/write stdin/stdout, the
|
||||
* same category of driver-level code this guard already covers.
|
||||
*
|
||||
* Three layers, extending test_core_isolation.c's two-layer pattern (same
|
||||
* genre: source-text scans of the real, current on-disk files, not a frozen
|
||||
|
|
@ -90,6 +92,10 @@
|
|||
#error \
|
||||
"XCE_SIM_LOOP_C_PATH must be defined by meson.build to sim_loop.c's absolute path"
|
||||
#endif
|
||||
#ifndef XCE_SIM_PICKER_C_PATH
|
||||
#error \
|
||||
"XCE_SIM_PICKER_C_PATH must be defined by meson.build to sim_picker.c's absolute path"
|
||||
#endif
|
||||
#ifndef XCE_SIM_RECORD_C_PATH
|
||||
#error \
|
||||
"XCE_SIM_RECORD_C_PATH must be defined by meson.build to sim_record.c's absolute path"
|
||||
|
|
@ -120,7 +126,7 @@
|
|||
#endif
|
||||
#ifndef XCE_SIM_LIB_PATH
|
||||
#error \
|
||||
"XCE_SIM_LIB_PATH must be defined by meson.build to the absolute path of sim.c+sim_loop.c+sim_record.c+repl.c+repl_break.c+repl_info.c+repl_params.c's isolated static_library() archive"
|
||||
"XCE_SIM_LIB_PATH must be defined by meson.build to the absolute path of sim.c+sim_loop.c+sim_picker.c+sim_record.c+repl.c+repl_break.c+repl_info.c+repl_params.c's isolated static_library() archive"
|
||||
#endif
|
||||
|
||||
/* Forbidden headers (design.md "Allowed Dependencies", same list
|
||||
|
|
@ -393,6 +399,7 @@ static void test_sim_source_paths_are_readable(void)
|
|||
char* h = read_whole_file(XCE_SIM_H_PATH);
|
||||
char* c = read_whole_file(XCE_SIM_C_PATH);
|
||||
char* loop = read_whole_file(XCE_SIM_LOOP_C_PATH);
|
||||
char* picker = read_whole_file(XCE_SIM_PICKER_C_PATH);
|
||||
char* record = read_whole_file(XCE_SIM_RECORD_C_PATH);
|
||||
char* repl_c = read_whole_file(XCE_SIM_REPL_C_PATH);
|
||||
char* repl_h = read_whole_file(XCE_SIM_REPL_H_PATH);
|
||||
|
|
@ -404,6 +411,7 @@ static void test_sim_source_paths_are_readable(void)
|
|||
TEST_ASSERT_NOT_NULL_MESSAGE(h, XCE_SIM_H_PATH);
|
||||
TEST_ASSERT_NOT_NULL_MESSAGE(c, XCE_SIM_C_PATH);
|
||||
TEST_ASSERT_NOT_NULL_MESSAGE(loop, XCE_SIM_LOOP_C_PATH);
|
||||
TEST_ASSERT_NOT_NULL_MESSAGE(picker, XCE_SIM_PICKER_C_PATH);
|
||||
TEST_ASSERT_NOT_NULL_MESSAGE(record, XCE_SIM_RECORD_C_PATH);
|
||||
TEST_ASSERT_NOT_NULL_MESSAGE(repl_c, XCE_SIM_REPL_C_PATH);
|
||||
TEST_ASSERT_NOT_NULL_MESSAGE(repl_h, XCE_SIM_REPL_H_PATH);
|
||||
|
|
@ -415,6 +423,7 @@ static void test_sim_source_paths_are_readable(void)
|
|||
free(h);
|
||||
free(c);
|
||||
free(loop);
|
||||
free(picker);
|
||||
free(record);
|
||||
free(repl_c);
|
||||
free(repl_h);
|
||||
|
|
@ -429,6 +438,7 @@ static void test_sim_never_includes_forbidden_headers(void)
|
|||
char* h_raw = read_whole_file(XCE_SIM_H_PATH);
|
||||
char* c_raw = read_whole_file(XCE_SIM_C_PATH);
|
||||
char* loop_raw = read_whole_file(XCE_SIM_LOOP_C_PATH);
|
||||
char* picker_raw = read_whole_file(XCE_SIM_PICKER_C_PATH);
|
||||
char* record_raw = read_whole_file(XCE_SIM_RECORD_C_PATH);
|
||||
char* repl_c_raw = read_whole_file(XCE_SIM_REPL_C_PATH);
|
||||
char* repl_h_raw = read_whole_file(XCE_SIM_REPL_H_PATH);
|
||||
|
|
@ -439,6 +449,7 @@ static void test_sim_never_includes_forbidden_headers(void)
|
|||
char* h;
|
||||
char* c;
|
||||
char* loop;
|
||||
char* picker;
|
||||
char* record;
|
||||
char* repl_c;
|
||||
char* repl_h;
|
||||
|
|
@ -450,6 +461,7 @@ static void test_sim_never_includes_forbidden_headers(void)
|
|||
TEST_ASSERT_NOT_NULL(h_raw);
|
||||
TEST_ASSERT_NOT_NULL(c_raw);
|
||||
TEST_ASSERT_NOT_NULL(loop_raw);
|
||||
TEST_ASSERT_NOT_NULL(picker_raw);
|
||||
TEST_ASSERT_NOT_NULL(record_raw);
|
||||
TEST_ASSERT_NOT_NULL(repl_c_raw);
|
||||
TEST_ASSERT_NOT_NULL(repl_h_raw);
|
||||
|
|
@ -461,6 +473,7 @@ static void test_sim_never_includes_forbidden_headers(void)
|
|||
h = strip_c_comments(h_raw);
|
||||
c = strip_c_comments(c_raw);
|
||||
loop = strip_c_comments(loop_raw);
|
||||
picker = strip_c_comments(picker_raw);
|
||||
record = strip_c_comments(record_raw);
|
||||
repl_c = strip_c_comments(repl_c_raw);
|
||||
repl_h = strip_c_comments(repl_h_raw);
|
||||
|
|
@ -471,6 +484,7 @@ static void test_sim_never_includes_forbidden_headers(void)
|
|||
TEST_ASSERT_NOT_NULL(h);
|
||||
TEST_ASSERT_NOT_NULL(c);
|
||||
TEST_ASSERT_NOT_NULL(loop);
|
||||
TEST_ASSERT_NOT_NULL(picker);
|
||||
TEST_ASSERT_NOT_NULL(record);
|
||||
TEST_ASSERT_NOT_NULL(repl_c);
|
||||
TEST_ASSERT_NOT_NULL(repl_h);
|
||||
|
|
@ -482,6 +496,7 @@ static void test_sim_never_includes_forbidden_headers(void)
|
|||
assert_no_forbidden_includes(h, "sim.h");
|
||||
assert_no_forbidden_includes(c, "sim.c");
|
||||
assert_no_forbidden_includes(loop, "sim_loop.c");
|
||||
assert_no_forbidden_includes(picker, "sim_picker.c");
|
||||
assert_no_forbidden_includes(record, "sim_record.c");
|
||||
assert_no_forbidden_includes(repl_c, "repl.c");
|
||||
assert_no_forbidden_includes(repl_h, "repl.h");
|
||||
|
|
@ -493,6 +508,7 @@ static void test_sim_never_includes_forbidden_headers(void)
|
|||
free(h_raw);
|
||||
free(c_raw);
|
||||
free(loop_raw);
|
||||
free(picker_raw);
|
||||
free(record_raw);
|
||||
free(repl_c_raw);
|
||||
free(repl_h_raw);
|
||||
|
|
@ -503,6 +519,7 @@ static void test_sim_never_includes_forbidden_headers(void)
|
|||
free(h);
|
||||
free(c);
|
||||
free(loop);
|
||||
free(picker);
|
||||
free(record);
|
||||
free(repl_c);
|
||||
free(repl_h);
|
||||
|
|
@ -517,6 +534,7 @@ static void test_sim_never_calls_forbidden_symbols(void)
|
|||
char* h_raw = read_whole_file(XCE_SIM_H_PATH);
|
||||
char* c_raw = read_whole_file(XCE_SIM_C_PATH);
|
||||
char* loop_raw = read_whole_file(XCE_SIM_LOOP_C_PATH);
|
||||
char* picker_raw = read_whole_file(XCE_SIM_PICKER_C_PATH);
|
||||
char* record_raw = read_whole_file(XCE_SIM_RECORD_C_PATH);
|
||||
char* repl_c_raw = read_whole_file(XCE_SIM_REPL_C_PATH);
|
||||
char* repl_h_raw = read_whole_file(XCE_SIM_REPL_H_PATH);
|
||||
|
|
@ -527,6 +545,7 @@ static void test_sim_never_calls_forbidden_symbols(void)
|
|||
char* h;
|
||||
char* c;
|
||||
char* loop;
|
||||
char* picker;
|
||||
char* record;
|
||||
char* repl_c;
|
||||
char* repl_h;
|
||||
|
|
@ -538,6 +557,7 @@ static void test_sim_never_calls_forbidden_symbols(void)
|
|||
TEST_ASSERT_NOT_NULL(h_raw);
|
||||
TEST_ASSERT_NOT_NULL(c_raw);
|
||||
TEST_ASSERT_NOT_NULL(loop_raw);
|
||||
TEST_ASSERT_NOT_NULL(picker_raw);
|
||||
TEST_ASSERT_NOT_NULL(record_raw);
|
||||
TEST_ASSERT_NOT_NULL(repl_c_raw);
|
||||
TEST_ASSERT_NOT_NULL(repl_h_raw);
|
||||
|
|
@ -549,6 +569,7 @@ static void test_sim_never_calls_forbidden_symbols(void)
|
|||
h = strip_c_comments(h_raw);
|
||||
c = strip_c_comments(c_raw);
|
||||
loop = strip_c_comments(loop_raw);
|
||||
picker = strip_c_comments(picker_raw);
|
||||
record = strip_c_comments(record_raw);
|
||||
repl_c = strip_c_comments(repl_c_raw);
|
||||
repl_h = strip_c_comments(repl_h_raw);
|
||||
|
|
@ -559,6 +580,7 @@ static void test_sim_never_calls_forbidden_symbols(void)
|
|||
TEST_ASSERT_NOT_NULL(h);
|
||||
TEST_ASSERT_NOT_NULL(c);
|
||||
TEST_ASSERT_NOT_NULL(loop);
|
||||
TEST_ASSERT_NOT_NULL(picker);
|
||||
TEST_ASSERT_NOT_NULL(record);
|
||||
TEST_ASSERT_NOT_NULL(repl_c);
|
||||
TEST_ASSERT_NOT_NULL(repl_h);
|
||||
|
|
@ -570,6 +592,7 @@ static void test_sim_never_calls_forbidden_symbols(void)
|
|||
assert_no_forbidden_symbols(h, "sim.h");
|
||||
assert_no_forbidden_symbols(c, "sim.c");
|
||||
assert_no_forbidden_symbols(loop, "sim_loop.c");
|
||||
assert_no_forbidden_symbols(picker, "sim_picker.c");
|
||||
assert_no_forbidden_symbols(record, "sim_record.c");
|
||||
assert_no_forbidden_symbols(repl_c, "repl.c");
|
||||
assert_no_forbidden_symbols(repl_h, "repl.h");
|
||||
|
|
@ -581,6 +604,7 @@ static void test_sim_never_calls_forbidden_symbols(void)
|
|||
free(h_raw);
|
||||
free(c_raw);
|
||||
free(loop_raw);
|
||||
free(picker_raw);
|
||||
free(record_raw);
|
||||
free(repl_c_raw);
|
||||
free(repl_h_raw);
|
||||
|
|
@ -591,6 +615,7 @@ static void test_sim_never_calls_forbidden_symbols(void)
|
|||
free(h);
|
||||
free(c);
|
||||
free(loop);
|
||||
free(picker);
|
||||
free(record);
|
||||
free(repl_c);
|
||||
free(repl_h);
|
||||
|
|
@ -641,9 +666,10 @@ static void test_sim_driver_struct_has_no_forbidden_fields(void)
|
|||
|
||||
/*
|
||||
* test_sim_object_has_no_forbidden_undefined_symbols - the literal
|
||||
* build-time/link-time proof: sim.c + sim_loop.c + sim_record.c + repl.c +
|
||||
* repl_break.c + repl_info.c + repl_params.c, compiled together in
|
||||
* isolation into sched_sim_isolation_lib (meson.build), must not reference
|
||||
* build-time/link-time proof: sim.c + sim_loop.c + sim_picker.c +
|
||||
* sim_record.c + repl.c + repl_break.c + repl_info.c + repl_params.c,
|
||||
* compiled together in isolation into sched_sim_isolation_lib
|
||||
* (meson.build), must not reference
|
||||
* (as an undefined external symbol in the compiled archive) anything
|
||||
* matching the forbidden prefixes above. Independent of what any header
|
||||
* transitively declares -- reflects only what this driver's compiled code
|
||||
|
|
@ -672,9 +698,9 @@ static void test_sim_object_has_no_forbidden_undefined_symbols(void)
|
|||
/* posix format for an undefined symbol: "<name> U" (no
|
||||
* value/size columns). Skip anything that doesn't parse as
|
||||
* exactly that -- e.g. a blank line, or an archive member header
|
||||
* some nm versions print (this archive has seven member objects,
|
||||
* sim.c.o, sim_loop.c.o, sim_record.c.o, repl.c.o, repl_break.c.o,
|
||||
* repl_info.c.o, and repl_params.c.o). */
|
||||
* some nm versions print (this archive has eight member objects,
|
||||
* sim.c.o, sim_loop.c.o, sim_picker.c.o, sim_record.c.o, repl.c.o,
|
||||
* repl_break.c.o, repl_info.c.o, and repl_params.c.o). */
|
||||
if (sscanf(line, "%511s %c", symbol, &type) != 2) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,6 +79,7 @@
|
|||
#include "../src/repl_params.c"
|
||||
#include "../src/sim.c"
|
||||
#include "../src/sim_loop.c"
|
||||
#include "../src/sim_picker.c" /* bug-1567: sched_sim_driver_run() now calls sim_bootstrap_picker() (sim_loop.c-cap sibling) as an extern -- undefined reference at link time otherwise */
|
||||
#include "../src/sim_record.c"
|
||||
#include "../src/sim_verify.c"
|
||||
#include "../src/snapshot.c"
|
||||
|
|
|
|||
|
|
@ -99,6 +99,7 @@
|
|||
#include "../src/repl_params.c"
|
||||
#include "../src/sim.c"
|
||||
#include "../src/sim_loop.c"
|
||||
#include "../src/sim_picker.c" /* bug-1567: sched_sim_driver_run() now calls sim_bootstrap_picker() (sim_loop.c-cap sibling) as an extern -- undefined reference at link time otherwise */
|
||||
#include "../src/sim_record.c"
|
||||
#include "../src/sim_verify.c"
|
||||
#include "../src/snapshot.c"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue