diff --git a/src/scheduler/testsuite/meson.build b/src/scheduler/testsuite/meson.build index c90a240e..b4fbe3c9 100644 --- a/src/scheduler/testsuite/meson.build +++ b/src/scheduler/testsuite/meson.build @@ -37,6 +37,213 @@ scheduler_test = executable('sched_test', dependencies: [scheduler_test_deps], install: false) +# sched_unit_test: the testsuite-aggregation runner (build/de-nix). The 28 +# zero-#include white-box tests below were one standalone executable EACH, +# each statically linking all of scheduler_srcs -- 120+ executables whose +# compile+link dominated the suite wall clock. This suite aggregates them +# into ONE process (same pattern as controller/testsuite/controller_test.c): +# the production scheduler sources are compiled once here as separate TUs, +# each test file keeps only its own suite entry (void test_sched_*(void) +# { UnitySetTestFile(__FILE__); RUN_TEST(...); }), and +# sched_unit_runner.c provides main()/setUp()/tearDown() dispatching through +# its SUITES registry. The per-file transformations were done by hand, one +# file at a time, with every file compiled+run in the aggregate before the +# next was touched. +# +# Only tests with NO textual #include of ../src/*.c qualify: a test that +# #includes a scheduler source textually duplicates its symbols and cannot +# coexist with the aggregate's own real TUs (those tests stay standalone, +# exactly as before). Tests needing -Wl,--wrap= link interposition, +# #define-shaping of the allocator, or that spawn XCE_SCHEDULER_BIN as a +# subprocess also stay standalone for the same reason. +# +# -Werror=incompatible-pointer-types preserves the picker-iface compile-time +# contract the standalone sched_picker_iface_test used to carry as its own +# c_args (every TU here compiles clean under it). The baked-in path defines +# are the union of the standalone targets' c_args (XCE_CORE_LIB_PATH / +# XCE_SIM_LIB_PATH point at the isolation archives, which stay build-only +# fixtures: test_core_isolation/test_sim_isolation nm(1)-inspect them, and +# link_with here would duplicate the aggregate's own core/sim TUs -- +# instead `depends:` orders their build). +sched_unit_test_srcs = ['sched_unit_runner.c'] +foreach f : scheduler_srcs + if f != 'src/main.c' + sched_unit_test_srcs += ['../' + f] + endif +endforeach +foreach f : ['test_sched_election_null_schedobj.c', + 'test_picker_iface.c', + 'test_picker_pendreason_factory_audit.c', + 'test_picker_core_loop_boundary.c', + 'test_no_bare_printf.c', + 'test_core_isolation.c', + 'test_sim_isolation.c', + 'test_scheduler_connect.c', + 'test_repl_output_compression.c', + 'test_repl_resource_formatting.c', + 'test_sim_cache_clear_isolation.c', + 'test_host_admin_close.c', + 'test_host_unavail_reconciling.c', + 'test_limit_host_dedup.c', + 'test_queue_admin_control.c', + 'test_job_move_priority.c', + 'test_config_push_deferred.c', + 'test_sim_group_limit_parity.c', + 'test_sim_limit_config_push_parity.c', + 'test_sim_live_allocation.c', + 'test_sim_e2e_limit_visibility.c', + 'test_sim_contention_resource_driver_parity.c', + 'test_sim_contention_limit_driver_parity.c', + 'test_sched_election_sim_fixture.c', + 'test_scheduler_dispatch_commit.c', + 'test_repl_trace_emit.c', + 'test_snapshot_sparse_resvals.c', + 'test_sim_alloc_limit_fanout.c'] + sched_unit_test_srcs += [f] +endforeach + +sched_unit_test = executable( + 'sched_unit_test', + sched_unit_test_srcs, + include_directories:[incdir], + dependencies: [scheduler_test_deps], + c_args: ['-Werror=incompatible-pointer-types', + '-DXCE_SCHEDULER_ROOT_PATH="' + + (meson.current_source_dir() / '..') + + '"', + '-DXCE_SCHED_ELECTION_C_PATH="' + + (meson.current_source_dir() / '..' / 'src' / 'sched_election.c') + + '"', + '-DXCE_CORE_H_PATH="' + + (meson.current_source_dir() / '..' / 'include' / 'core.h') + + '"', + '-DXCE_CORE_C_PATH="' + + (meson.current_source_dir() / '..' / 'src' / 'core.c') + + '"', + '-DXCE_CORE_EVENTS_C_PATH="' + + (meson.current_source_dir() / '..' / 'src' / 'core_events.c') + + '"', + '-DXCE_CORE_SESSION_C_PATH="' + + (meson.current_source_dir() / '..' / 'src' / 'core_session.c') + + '"', + '-DXCE_CORE_CLOCK_C_PATH="' + + (meson.current_source_dir() / '..' / 'src' / 'core_clock.c') + + '"', + '-DXCE_SCHED_TRACE_C_PATH="' + + (meson.current_source_dir() / '..' / 'src' / 'sched_trace.c') + + '"', + '-DXCE_SCHED_TRACE_CAPTURE_C_PATH="' + + (meson.current_source_dir() / '..' / 'src' + / 'sched_trace_capture.c') + + '"', + '-DXCE_SCHED_TRACE_SCAN_C_PATH="' + + (meson.current_source_dir() / '..' / 'src' + / 'sched_trace_scan.c') + + '"', + '-DXCE_SCHED_TRACE_OUTCOME_C_PATH="' + + (meson.current_source_dir() / '..' / 'src' + / 'sched_trace_outcome.c') + + '"', + '-DXCE_SCHED_TRACE_INTERNAL_H_PATH="' + + (meson.current_source_dir() / '..' / 'src' + / 'sched_trace_internal.h') + + '"', + '-DXCE_SCHEDULER_SRC_DIR="' + + (meson.current_source_dir() / '..' / 'src') + + '"', + '-DXCE_SCHEDULER_PLUGINS_DIR="' + + (meson.current_source_dir() / '..' / 'src' / 'plugins') + + '"', + '-DXCE_SCHEDULER_C_PATH="' + + (meson.current_source_dir() / '..' / 'src' / 'scheduler.c') + + '"', + '-DXCE_DRIVER_C_PATH="' + + (meson.current_source_dir() / '..' / 'src' / 'driver.c') + + '"', + '-DXCE_MAIN_C_PATH="' + + (meson.current_source_dir() / '..' / 'src' / 'main.c') + + '"', + '-DXCE_CORE_LIB_PATH="' + + sched_core_isolation_lib.full_path() + + '"', + '-DXCE_SIM_H_PATH="' + + (meson.current_source_dir() / '..' / 'include' / 'sim.h') + + '"', + '-DXCE_SIM_C_PATH="' + + (meson.current_source_dir() / '..' / 'src' / 'sim.c') + + '"', + '-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') + + '"', + '-DXCE_SIM_REPL_C_PATH="' + + (meson.current_source_dir() / '..' / 'src' / 'repl.c') + + '"', + '-DXCE_SIM_REPL_H_PATH="' + + (meson.current_source_dir() / '..' / 'include' / 'repl.h') + + '"', + '-DXCE_SIM_REPL_BREAK_C_PATH="' + + (meson.current_source_dir() / '..' / 'src' / 'repl_break.c') + + '"', + '-DXCE_SIM_REPL_INFO_C_PATH="' + + (meson.current_source_dir() / '..' / 'src' / 'repl_info.c') + + '"', + '-DXCE_SIM_REPL_INTERNAL_H_PATH="' + + (meson.current_source_dir() / '..' / 'src' + / 'repl_internal.h') + + '"', + '-DXCE_SIM_REPL_PARAMS_C_PATH="' + + (meson.current_source_dir() / '..' / 'src' / 'repl_params.c') + + '"', + '-DXCE_SIM_REPL_ROLLUP_C_PATH="' + + (meson.current_source_dir() / '..' / 'src' / 'repl_rollup.c') + + '"', + '-DXCE_SIM_REPL_FMT_C_PATH="' + + (meson.current_source_dir() / '..' / 'src' / 'repl_fmt.c') + + '"', + '-DXCE_SIM_REPL_TRACE_C_PATH="' + + (meson.current_source_dir() / '..' / 'src' / 'repl_trace.c') + + '"', + '-DXCE_SIM_REPL_TRACE_STORE_C_PATH="' + + (meson.current_source_dir() / '..' / 'src' + / 'repl_trace_store.c') + + '"', + '-DXCE_SIM_REPL_TRACE_RENDER_C_PATH="' + + (meson.current_source_dir() / '..' / 'src' + / 'repl_trace_render.c') + + '"', + '-DXCE_SIM_REPL_TRACE_RENDER_OUTCOME_C_PATH="' + + (meson.current_source_dir() / '..' / 'src' + / 'repl_trace_render_outcome.c') + + '"', + '-DXCE_SIM_REPL_TRACE_RENDER_H_PATH="' + + (meson.current_source_dir() / '..' / 'src' + / 'repl_trace_render.h') + + '"', + '-DXCE_SIM_REPL_TRACE_EMIT_C_PATH="' + + (meson.current_source_dir() / '..' / 'src' + / 'repl_trace_emit.c') + + '"', + '-DXCE_SIM_LIB_PATH="' + + sched_sim_isolation_lib.full_path() + + '"'], + install: false) + +# detect_leaks=0 matches the suite convention: test_repl_trace_emit's own +# setUp holds settings for the suite scope, and the runner holds one +# process-wide Unity state across all 28 suites (the standalone runs of the +# other 27 keep leak detection on via their own registrations below). +# `depends:` builds the two isolation archives the aggregate's +# XCE_CORE_LIB_PATH/XCE_SIM_LIB_PATH text-scan tests nm(1)-inspect. +test('scheduler unit test', sched_unit_test, suite: 'scheduler', + env: ['ASAN_OPTIONS=detect_leaks=0'], + depends: [sched_core_isolation_lib, sched_sim_isolation_lib]) + # White-box test for the notify single-job in-place update path # (sched_update_existing_job). It #includes ../src/schedobj.c directly, so it # is a standalone TU with its own main() — built as a separate executable. @@ -83,15 +290,11 @@ sched_job_array_wire_e2e_test = executable('sched_job_array_wire_e2e_test', # Compile-check for the job picker plugin contract, xce_job_picker_iface_t # (scheduler-core spec, task 1.1). Only #includes plugin.h -- no picker -# implementation exists yet (that's task 2.x). -Werror on incompatible -# pointer types so a hook signature drift in plugin.h fails the build, not -# just an assertion: the test's real content is "this compiles at all". -sched_picker_iface_test = executable('sched_picker_iface_test', - ['test_picker_iface.c'], - include_directories:[incdir], - dependencies: [scheduler_test_deps], - c_args: ['-Werror=incompatible-pointer-types'], - install: false) +# implementation exists yet (that's task 2.x). Lives in the sched_unit_test +# aggregate now, which carries the same -Werror=incompatible-pointer-types +# c_args suite-wide: a hook signature drift in plugin.h still fails the +# build, not just an assertion -- the test's real content is "this compiles +# at all". # White-box test for the picker plugin registration category and the # job_elect_fn compatibility wrapper (scheduler-core spec, task 1.2). It @@ -185,17 +388,8 @@ sched_picker_wiring_test = executable('sched_picker_wiring_test', # meson.current_source_dir() so the check has no dependency on the test's # cwd at run time. Repointed from scheduler.c to sched_election.c # (scheduler-sim-live-allocation spec, task 3.1): sched_job_picker() moved -# there, unchanged in body -- see that file's own header comment. -sched_picker_core_loop_boundary_test = executable( - 'sched_picker_core_loop_boundary_test', - ['test_picker_core_loop_boundary.c'], - include_directories:[incdir], - dependencies: [scheduler_test_deps], - c_args: ['-DXCE_SCHED_ELECTION_C_PATH="' - + (meson.current_source_dir() / '..' / 'src' - / 'sched_election.c') - + '"'], - install: false) +# there, unchanged in body -- see that file's own header comment. Lives in +# the sched_unit_test aggregate now. # Regression guard for Req 6 AC 2 (scheduler-core spec, task 2.6): "All pend # reason allocation shall go through make_pendreason() (lib/preason.c). @@ -206,16 +400,9 @@ sched_picker_core_loop_boundary_test = executable( # src/scheduler for the forbidden pattern rather than one function's body. # XCE_SCHEDULER_ROOT_PATH bakes in src/scheduler's absolute path; # the scanned file list itself lives in the test source (see that file's -# header comment for why a fixed list, not a directory walk). -sched_pendreason_factory_audit_test = executable( - 'sched_pendreason_factory_audit_test', - ['test_picker_pendreason_factory_audit.c'], - include_directories:[incdir], - dependencies: [scheduler_test_deps], - c_args: ['-DXCE_SCHEDULER_ROOT_PATH="' - + (meson.current_source_dir() / '..') - + '"'], - install: false) +# header comment for why a fixed list, not a directory walk). Lives in the +# sched_unit_test aggregate now (XCE_SCHEDULER_ROOT_PATH comes from the +# aggregate's own c_args). # Regression guard for task 4.1's Observable (scheduler-core spec, Req # 5.1/5.2): "the core structure compiles and links with zero symbols from @@ -227,70 +414,20 @@ sched_pendreason_factory_audit_test = executable( # meson.build -- core.c compiled alone, isolated from the rest of the # scheduler). link_with establishes the build-order dependency so that # archive exists before this test runs; XCE_CORE_LIB_PATH bakes in its -# absolute path the same way XCE_SCHEDULER_C_PATH does above. -sched_core_isolation_test = executable( - 'sched_core_isolation_test', - ['test_core_isolation.c'], - include_directories:[incdir], - dependencies: [scheduler_test_deps], - link_with: [sched_core_isolation_lib], - c_args: ['-DXCE_CORE_H_PATH="' - + (meson.current_source_dir() / '..' / 'include' / 'core.h') - + '"', - '-DXCE_CORE_C_PATH="' - + (meson.current_source_dir() / '..' / 'src' / 'core.c') - + '"', - '-DXCE_CORE_EVENTS_C_PATH="' - + (meson.current_source_dir() / '..' / 'src' / 'core_events.c') - + '"', - '-DXCE_CORE_SESSION_C_PATH="' - + (meson.current_source_dir() / '..' / 'src' / 'core_session.c') - + '"', - '-DXCE_CORE_CLOCK_C_PATH="' - + (meson.current_source_dir() / '..' / 'src' / 'core_clock.c') - + '"', - '-DXCE_SCHED_TRACE_C_PATH="' - + (meson.current_source_dir() / '..' / 'src' / 'sched_trace.c') - + '"', - '-DXCE_SCHED_TRACE_CAPTURE_C_PATH="' - + (meson.current_source_dir() / '..' / 'src' - / 'sched_trace_capture.c') - + '"', - '-DXCE_SCHED_TRACE_SCAN_C_PATH="' - + (meson.current_source_dir() / '..' / 'src' - / 'sched_trace_scan.c') - + '"', - '-DXCE_SCHED_TRACE_OUTCOME_C_PATH="' - + (meson.current_source_dir() / '..' / 'src' - / 'sched_trace_outcome.c') - + '"', - '-DXCE_SCHED_TRACE_INTERNAL_H_PATH="' - + (meson.current_source_dir() / '..' / 'src' - / 'sched_trace_internal.h') - + '"', - '-DXCE_CORE_LIB_PATH="' - + sched_core_isolation_lib.full_path() - + '"'], - install: false) +# absolute path the same way XCE_SCHEDULER_C_PATH does above. Lives in the +# sched_unit_test aggregate now: XCE_CORE_LIB_PATH (and +# sched_sim_isolation_lib's XCE_SIM_LIB_PATH below) are still built -- the +# aggregate `depends:` on them, since link_with there would duplicate its +# own core/sim TUs. # Regression guard (2026-08-20) for the "PEND/DISPATCH/PREEMPT lines carried # an unexpected tlog prefix" bug -- see test_no_bare_printf.c's own header # comment for the full rationale (xce_scheduler link-wraps printf via # wrap_link_args above; fprintf(stdout, ...) is the required convention). # Directory-path defines (not one per file, like XCE_CORE_C_PATH above) so -# a future new .c file in either directory is automatically covered. -sched_no_bare_printf_test = executable( - 'sched_no_bare_printf_test', - ['test_no_bare_printf.c'], - include_directories:[incdir], - dependencies: [scheduler_test_deps], - c_args: ['-DXCE_SCHEDULER_SRC_DIR="' - + (meson.current_source_dir() / '..' / 'src') - + '"', - '-DXCE_SCHEDULER_PLUGINS_DIR="' - + (meson.current_source_dir() / '..' / 'src' / 'plugins') - + '"'], - install: false) +# a future new .c file in either directory is automatically covered. Lives +# in the sched_unit_test aggregate now (its directory defines come from the +# aggregate's own c_args). # Regression guard for task 4.2's jbuf-capacity half (scheduler-core spec, # Req 5 AC 7): "cbuf capacity=1 serialization ... this capacity is a @@ -665,74 +802,9 @@ sched_sim_event_loop_test = executable( # 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( - 'sched_sim_isolation_test', - ['test_sim_isolation.c'], - include_directories:[incdir], - dependencies: [scheduler_test_deps], - link_with: [sched_sim_isolation_lib], - c_args: ['-DXCE_SIM_H_PATH="' - + (meson.current_source_dir() / '..' / 'include' / 'sim.h') - + '"', - '-DXCE_SIM_C_PATH="' - + (meson.current_source_dir() / '..' / 'src' / 'sim.c') - + '"', - '-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') - + '"', - '-DXCE_SIM_REPL_C_PATH="' - + (meson.current_source_dir() / '..' / 'src' / 'repl.c') - + '"', - '-DXCE_SIM_REPL_H_PATH="' - + (meson.current_source_dir() / '..' / 'include' / 'repl.h') - + '"', - '-DXCE_SIM_REPL_BREAK_C_PATH="' - + (meson.current_source_dir() / '..' / 'src' / 'repl_break.c') - + '"', - '-DXCE_SIM_REPL_INFO_C_PATH="' - + (meson.current_source_dir() / '..' / 'src' / 'repl_info.c') - + '"', - '-DXCE_SIM_REPL_INTERNAL_H_PATH="' - + (meson.current_source_dir() / '..' / 'src' / 'repl_internal.h') - + '"', - '-DXCE_SIM_REPL_PARAMS_C_PATH="' - + (meson.current_source_dir() / '..' / 'src' / 'repl_params.c') - + '"', - '-DXCE_SIM_REPL_ROLLUP_C_PATH="' - + (meson.current_source_dir() / '..' / 'src' / 'repl_rollup.c') - + '"', - '-DXCE_SIM_REPL_FMT_C_PATH="' - + (meson.current_source_dir() / '..' / 'src' / 'repl_fmt.c') - + '"', - '-DXCE_SIM_REPL_TRACE_C_PATH="' - + (meson.current_source_dir() / '..' / 'src' / 'repl_trace.c') - + '"', - '-DXCE_SIM_REPL_TRACE_STORE_C_PATH="' - + (meson.current_source_dir() / '..' / 'src' / 'repl_trace_store.c') - + '"', - '-DXCE_SIM_REPL_TRACE_RENDER_C_PATH="' - + (meson.current_source_dir() / '..' / 'src' / 'repl_trace_render.c') - + '"', - '-DXCE_SIM_REPL_TRACE_RENDER_OUTCOME_C_PATH="' - + (meson.current_source_dir() / '..' / 'src' / 'repl_trace_render_outcome.c') - + '"', - '-DXCE_SIM_REPL_TRACE_RENDER_H_PATH="' - + (meson.current_source_dir() / '..' / 'src' / 'repl_trace_render.h') - + '"', - '-DXCE_SIM_REPL_TRACE_EMIT_C_PATH="' - + (meson.current_source_dir() / '..' / 'src' / 'repl_trace_emit.c') - + '"', - '-DXCE_SIM_LIB_PATH="' - + sched_sim_isolation_lib.full_path() - + '"'], - install: false) +# above. Lives in the sched_unit_test aggregate now -- see +# test_core_isolation.c's own comment above for the isolation-archive +# build-order note. # Contract test for decision verification (scheduler-core spec, task 11.4, # Req 5 AC 15/18): each core-emitted decision is compared against the @@ -1340,20 +1412,8 @@ sched_repl_equivalence_test = executable( # scheduler_connect_test_srcs below, so it can never drift from the # production source list. No `-Wl,--wrap=` or `-DXCE_SCHEDULER_C_PATH` is # needed here: this test never calls sched_init() or reaches networking -# code, it only exercises the pure repl_fmt_jobid_range() formatter. -repl_output_compression_test_srcs = ['test_repl_output_compression.c'] -foreach f : scheduler_srcs - if f != 'src/main.c' - repl_output_compression_test_srcs += ['../' + f] - endif -endforeach - -sched_repl_output_compression_test = executable( - 'sched_repl_output_compression_test', - repl_output_compression_test_srcs, - include_directories:[incdir], - dependencies: [scheduler_deps, unity_dep], - install: false) +# code, it only exercises the pure repl_fmt_jobid_range() formatter. Lives +# in the sched_unit_test aggregate now. # Contract test for the REPL's resource-value byte/megabyte classification # and adaptive human-scaling helpers (scheduler-sim-repl-verbosity spec, task @@ -1367,23 +1427,8 @@ sched_repl_output_compression_test = executable( # repl_output_compression_test_srcs above (repl.c's own dependency surface # pulls in undefined cross-references to sibling files this test does not # need). Same "link the real scheduler_srcs object list instead of textually -# including one" technique, for the identical reason: task 7.2 has not -# landed yet, so this target is expected to fail at LINK time (undefined -# reference to both symbols) until it does -- that failure is task 7.1's own -# Observable evidence. -repl_resource_formatting_test_srcs = ['test_repl_resource_formatting.c'] -foreach f : scheduler_srcs - if f != 'src/main.c' - repl_resource_formatting_test_srcs += ['../' + f] - endif -endforeach - -sched_repl_resource_formatting_test = executable( - 'sched_repl_resource_formatting_test', - repl_resource_formatting_test_srcs, - include_directories:[incdir], - dependencies: [scheduler_deps, unity_dep], - install: false) +# including one" technique, for the identical reason. Lives in the +# sched_unit_test aggregate now. # Tests for the scheduler's unified candidate-list connect/rejoin pipeline # (component-failover-adoption, task 3.1, boundary: SchedulerControllerClient). @@ -1398,22 +1443,8 @@ sched_repl_resource_formatting_test = executable( # scheduler_srcs (defined in the parent meson.build) minus src/main.c (this # test file supplies its own main()) -- built via a loop rather than a # hand-duplicated list so it can never drift from the production source list. -scheduler_connect_test_srcs = ['test_scheduler_connect.c'] -foreach f : scheduler_srcs - if f != 'src/main.c' - scheduler_connect_test_srcs += ['../' + f] - endif -endforeach - -sched_scheduler_connect_test = executable( - 'sched_scheduler_connect_test', - scheduler_connect_test_srcs, - include_directories:[incdir], - dependencies: [scheduler_deps, unity_dep], - c_args: ['-DXCE_SCHEDULER_C_PATH="' - + (meson.current_source_dir() / '..' / 'src' / 'scheduler.c') - + '"'], - install: false) +# Lives in the sched_unit_test aggregate now (XCE_SCHEDULER_C_PATH comes +# from the aggregate's own c_args). # Tests for the scheduler's decision-publish retry-until-success-or-shutdown # wrapper, composed with rejoin retry-on-failure (component-failover-adoption, @@ -1523,20 +1554,7 @@ sched_scheduler_decision_redelivery_test = executable( # job->accounts. Same real-scheduler_srcs link technique as # sched_scheduler_connect_test above, but no `-Wl,--wrap=` is needed: this # file never calls sched_init()/sched_fini(), so none of the xcecli_* calls -# those make are ever reached. -scheduler_dispatch_commit_test_srcs = ['test_scheduler_dispatch_commit.c'] -foreach f : scheduler_srcs - if f != 'src/main.c' - scheduler_dispatch_commit_test_srcs += ['../' + f] - endif -endforeach - -sched_scheduler_dispatch_commit_test = executable( - 'sched_scheduler_dispatch_commit_test', - scheduler_dispatch_commit_test_srcs, - include_directories:[incdir], - dependencies: [scheduler_deps, unity_dep], - install: false) +# those make are ever reached. Lives in the sched_unit_test aggregate now. # scheduler-snapshot-job-allocation spec, task 4.1 (Req 2 AC 2/AC 4): direct # regression test proving a PENDING job restored via the real @@ -1751,18 +1769,13 @@ sched_core_session_cache_clear_test = executable( # separate-compiled-sources technique as sched_core_session_cache_clear_test # above, for the same reason: this test needs the real, strong # cache_clear() actually present in the binary to prove the NULL-hook path -# still never calls it. -sched_sim_cache_clear_isolation_test = executable( - 'sched_sim_cache_clear_isolation_test', - ['test_sim_cache_clear_isolation.c', - '../src/core.c', - '../src/core_clock.c', - '../src/core_session.c', - '../src/decision.c', - '../src/alloc_cache.c'], - include_directories:[incdir], - dependencies: [scheduler_test_deps], - install: false) +# still never calls it. Lives in the sched_unit_test aggregate now -- the +# aggregate's own separately-compiled core.c/core_clock.c/core_session.c/ +# decision.c/alloc_cache.c TUs preserve exactly the separate-object-file +# property this test's design requires, and its kill_sched_*/plugin_ +# unregister/sched_worker_release_host_ctx link stubs resolve against the +# aggregate's real core.c/plugin.c/resource.c definitions (same resolution +# the standalone run had). # Task 3.1 (scheduler-allocation spec, Req 9.1, 4.6): seqjob_allocator.c's # rewrap onto the shared plan_iter/host_iter interfaces, plus the new @@ -1918,8 +1931,6 @@ test('scheduler job-array expand test', sched_job_array_test, suite: 'scheduler' env: ['ASAN_OPTIONS=detect_leaks=0']) test('scheduler job-array wire e2e test', sched_job_array_wire_e2e_test, suite: 'scheduler', env: ['ASAN_OPTIONS=detect_leaks=0']) -test('scheduler picker iface test', sched_picker_iface_test, suite: 'scheduler', - env: ['ASAN_OPTIONS=detect_leaks=0']) test('scheduler picker registration test', sched_picker_registration_test, suite: 'scheduler', env: ['ASAN_OPTIONS=detect_leaks=0']) test('scheduler plugin hook dispatch test', sched_plugin_hook_dispatch_test, suite: 'scheduler', @@ -1932,18 +1943,6 @@ test('scheduler picker fcfs session test', sched_picker_fcfs_session_test, suite env: ['ASAN_OPTIONS=detect_leaks=0']) test('scheduler picker wiring test', sched_picker_wiring_test, suite: 'scheduler', env: ['ASAN_OPTIONS=detect_leaks=0']) -test('scheduler picker core loop boundary test', - sched_picker_core_loop_boundary_test, suite: 'scheduler', - env: ['ASAN_OPTIONS=detect_leaks=0']) -test('scheduler pendreason factory audit test', - sched_pendreason_factory_audit_test, suite: 'scheduler', - env: ['ASAN_OPTIONS=detect_leaks=0']) -test('scheduler core isolation test', - sched_core_isolation_test, suite: 'scheduler', - env: ['ASAN_OPTIONS=detect_leaks=0']) -test('scheduler no bare printf test', - sched_no_bare_printf_test, suite: 'scheduler', - env: ['ASAN_OPTIONS=detect_leaks=0']) test('scheduler core jbuf capacity pin test', sched_core_jbuf_capacity_pin_test, suite: 'scheduler', env: ['ASAN_OPTIONS=detect_leaks=0']) @@ -1995,9 +1994,6 @@ test('scheduler sim startup test', test('scheduler sim event loop test', sched_sim_event_loop_test, suite: 'scheduler', env: ['ASAN_OPTIONS=detect_leaks=0']) -test('scheduler sim isolation test', - sched_sim_isolation_test, suite: 'scheduler', - env: ['ASAN_OPTIONS=detect_leaks=0']) test('scheduler sim verify test', sched_sim_verify_test, suite: 'scheduler', env: ['ASAN_OPTIONS=detect_leaks=0']) @@ -2067,15 +2063,6 @@ test('scheduler repl snapshot params test', test('scheduler repl equivalence test', sched_repl_equivalence_test, suite: 'scheduler', env: ['ASAN_OPTIONS=detect_leaks=0']) -test('scheduler repl output compression test', - sched_repl_output_compression_test, suite: 'scheduler', - env: ['ASAN_OPTIONS=detect_leaks=0']) -test('scheduler repl resource formatting test', - sched_repl_resource_formatting_test, suite: 'scheduler', - env: ['ASAN_OPTIONS=detect_leaks=0']) -test('scheduler connect pipeline test', - sched_scheduler_connect_test, suite: 'scheduler', - env: ['ASAN_OPTIONS=detect_leaks=0']) # bug-1882 regression: sched_make_allocs() must fail the whole array when # make_alloc() cannot build a record. Real scheduler_srcs (as @@ -2108,9 +2095,6 @@ test('scheduler backpressure test', test('scheduler decision redelivery test', sched_scheduler_decision_redelivery_test, suite: 'scheduler', env: ['ASAN_OPTIONS=detect_leaks=0']) -test('scheduler dispatch commit test', - sched_scheduler_dispatch_commit_test, suite: 'scheduler', - env: ['ASAN_OPTIONS=detect_leaks=0']) test('scheduler snapshot load allocator regression test', sched_snapshot_load_allocator_regression_test, suite: 'scheduler', env: ['ASAN_OPTIONS=detect_leaks=0']) @@ -2131,9 +2115,6 @@ test('scheduler alloc cache test', test('scheduler core session cache clear test', sched_core_session_cache_clear_test, suite: 'scheduler', env: ['ASAN_OPTIONS=detect_leaks=0']) -test('scheduler sim cache clear isolation test', - sched_sim_cache_clear_isolation_test, suite: 'scheduler', - env: ['ASAN_OPTIONS=detect_leaks=0']) test('scheduler seqjob allocator test', sched_seqjob_allocator_test, suite: 'scheduler', env: ['ASAN_OPTIONS=detect_leaks=0']) @@ -2277,45 +2258,13 @@ test('scheduler maxtasks wiring sim driver parity test', # it can never drift from the production source list) -- no `-Wl,--wrap=` # needed since this file never calls sched_init() (see the test file's own # header comment for why a real, but never-sched_init()'d, xce_scheduler_t -# is still used incidentally during setup). -sched_election_sim_fixture_test_srcs = ['test_sched_election_sim_fixture.c'] -foreach f : scheduler_srcs - if f != 'src/main.c' - sched_election_sim_fixture_test_srcs += ['../' + f] - endif -endforeach - -sched_election_sim_fixture_test = executable( - 'sched_election_sim_fixture_test', - sched_election_sim_fixture_test_srcs, - include_directories:[incdir], - dependencies: [scheduler_test_deps], - install: false) - -test('scheduler election sim fixture test', - sched_election_sim_fixture_test, suite: 'scheduler', - env: ['ASAN_OPTIONS=detect_leaks=0']) +# is still used incidentally during setup). Lives in the sched_unit_test +# aggregate now. # bug-1897: sched_allocator() must skip a picked job whose schedobj is NULL # (resreq failed to parse on snapshot load) instead of dereferencing it. -# Same real-scheduler_srcs link technique as the fixture test above. -sched_election_null_schedobj_test_srcs = ['test_sched_election_null_schedobj.c'] -foreach f : scheduler_srcs - if f != 'src/main.c' - sched_election_null_schedobj_test_srcs += ['../' + f] - endif -endforeach - -sched_election_null_schedobj_test = executable( - 'sched_election_null_schedobj_test', - sched_election_null_schedobj_test_srcs, - include_directories:[incdir], - dependencies: [scheduler_test_deps], - install: false) - -test('scheduler election null schedobj test', - sched_election_null_schedobj_test, suite: 'scheduler', - env: ['ASAN_OPTIONS=detect_leaks=0']) +# Same real-scheduler_srcs link technique as the fixture test above. Lives +# in the sched_unit_test aggregate now. # scheduler-sim-live-allocation spec, task 4.1 (Req 1.1, 1.2, 3.3, 4.2, 4.3, # 5.1, boundary: Unified Picker/Allocator Threads, Sim Driver): proves @@ -2328,24 +2277,7 @@ test('scheduler election null schedobj test', # sched_election_sim_fixture_test immediately above: sched_allocator() # (sched_election.c) reaches the real sched_make_allocation()/ # seqjob_allocator.c chain, none of which is reachable via a white-box -# #include of sim_loop.c alone. -sched_sim_live_allocation_test_srcs = ['test_sim_live_allocation.c'] -foreach f : scheduler_srcs - if f != 'src/main.c' - sched_sim_live_allocation_test_srcs += ['../' + f] - endif -endforeach - -sched_sim_live_allocation_test = executable( - 'sched_sim_live_allocation_test', - sched_sim_live_allocation_test_srcs, - include_directories:[incdir], - dependencies: [scheduler_test_deps], - install: false) - -test('scheduler sim live allocation test', - sched_sim_live_allocation_test, suite: 'scheduler', - env: ['ASAN_OPTIONS=detect_leaks=0']) +# #include of sim_loop.c alone. Lives in the sched_unit_test aggregate now. # scheduler-sim-live-allocation spec, task 4.3 (Req 2.2, boundary: Unified # Picker/Allocator Threads, Limit Plugin Core-Safe Matching): proves a @@ -2357,23 +2289,7 @@ test('scheduler sim live allocation test', # plugin->core pointed at a throwaway wrapper's separate registry, never # sim.core.plugins). Same real-scheduler_srcs link technique as # sched_election_sim_fixture_test/sched_sim_live_allocation_test above. -sched_sim_alloc_limit_fanout_test_srcs = ['test_sim_alloc_limit_fanout.c'] -foreach f : scheduler_srcs - if f != 'src/main.c' - sched_sim_alloc_limit_fanout_test_srcs += ['../' + f] - endif -endforeach - -sched_sim_alloc_limit_fanout_test = executable( - 'sched_sim_alloc_limit_fanout_test', - sched_sim_alloc_limit_fanout_test_srcs, - include_directories:[incdir], - dependencies: [scheduler_test_deps], - install: false) - -test('scheduler sim alloc limit fanout test', - sched_sim_alloc_limit_fanout_test, suite: 'scheduler', - env: ['ASAN_OPTIONS=detect_leaks=0']) +# Lives in the sched_unit_test aggregate now. # scheduler-sim-live-allocation spec, task 5.1 (Req 3.1, 3.2): drives the # real, unmodified sched_job_picker()/sched_allocator() pair against a @@ -2383,25 +2299,7 @@ test('scheduler sim alloc limit fanout test', # outcomes and identical final resource-accounting state. Same real- # scheduler_srcs link technique as sched_election_sim_fixture_test/ # sched_sim_live_allocation_test/sched_sim_alloc_limit_fanout_test above. -sched_sim_contention_resource_driver_parity_test_srcs = [ - 'test_sim_contention_resource_driver_parity.c' -] -foreach f : scheduler_srcs - if f != 'src/main.c' - sched_sim_contention_resource_driver_parity_test_srcs += ['../' + f] - endif -endforeach - -sched_sim_contention_resource_driver_parity_test = executable( - 'sched_sim_contention_resource_driver_parity_test', - sched_sim_contention_resource_driver_parity_test_srcs, - include_directories:[incdir], - dependencies: [scheduler_test_deps], - install: false) - -test('scheduler sim contention resource driver parity test', - sched_sim_contention_resource_driver_parity_test, suite: 'scheduler', - env: ['ASAN_OPTIONS=detect_leaks=0']) +# Lives in the sched_unit_test aggregate now. # scheduler-sim-live-allocation spec, task 5.1 (Req 3.1, 3.2): sibling of # sched_sim_contention_resource_driver_parity_test above, adding a host- @@ -2410,74 +2308,22 @@ test('scheduler sim contention resource driver parity test', # scheduler-driver-equivalence.md's testing discipline), confirming both # the admission outcome AND the limit-usage-instance accounting state match # between drivers. Same real-scheduler_srcs link technique as the test -# immediately above. -sched_sim_contention_limit_driver_parity_test_srcs = [ - 'test_sim_contention_limit_driver_parity.c' -] -foreach f : scheduler_srcs - if f != 'src/main.c' - sched_sim_contention_limit_driver_parity_test_srcs += ['../' + f] - endif -endforeach - -sched_sim_contention_limit_driver_parity_test = executable( - 'sched_sim_contention_limit_driver_parity_test', - sched_sim_contention_limit_driver_parity_test_srcs, - include_directories:[incdir], - dependencies: [scheduler_test_deps], - install: false) - -test('scheduler sim contention limit driver parity test', - sched_sim_contention_limit_driver_parity_test, suite: 'scheduler', - env: ['ASAN_OPTIONS=detect_leaks=0']) +# immediately above. Lives in the sched_unit_test aggregate now. # bug-1846: a host-scoped limit must be staged once per (job, worker) no # matter how many allocation attempts the job makes there -- # match_job_host_limit_() used to append a fresh copy to obj->hlimits on # every attempt, inflating the DISPATCH host allocation (72 vs 3 entries in # a real captured replay). Links every scheduler source except main.c, same -# as the driver-parity fixture above. -sched_limit_host_dedup_test_srcs = ['test_limit_host_dedup.c'] -foreach f : scheduler_srcs - if f != 'src/main.c' - sched_limit_host_dedup_test_srcs += ['../' + f] - endif -endforeach - -sched_limit_host_dedup_test = executable( - 'sched_limit_host_dedup_test', - sched_limit_host_dedup_test_srcs, - include_directories:[incdir], - dependencies: [scheduler_test_deps], - install: false) - -test('scheduler limit host dedup test', - sched_limit_host_dedup_test, suite: 'scheduler', - env: ['ASAN_OPTIONS=detect_leaks=0']) +# as the driver-parity fixture above. Lives in the sched_unit_test +# aggregate now. # bug-1846 part 2: a config push (sent by the controller on every scheduler # join, including a rejoin triggered mid-round from the decision publish # path) must be deferred to the round boundary -- applying it on the handler # thread reset the fcfs cursor and ended the live round early. Real # scheduler_req_handler() + real builtin_fcfs; every scheduler source except -# main.c. -sched_config_push_deferred_test_srcs = ['test_config_push_deferred.c'] -foreach f : scheduler_srcs - if f != 'src/main.c' - sched_config_push_deferred_test_srcs += ['../' + f] - endif -endforeach - -sched_config_push_deferred_test = executable( - 'sched_config_push_deferred_test', - sched_config_push_deferred_test_srcs, - include_directories:[incdir], - dependencies: [scheduler_test_deps], - install: false) - -test('scheduler config push deferred test', - sched_config_push_deferred_test, suite: 'scheduler', - env: ['ASAN_OPTIONS=detect_leaks=0']) +# main.c. Lives in the sched_unit_test aggregate now. # scheduler-sim-live-allocation spec, task 5.2 (Req 2.1, 2.2, 2.3, 2.4): the # feature's concrete, original acceptance test (bug-1826) -- a real global @@ -2488,26 +2334,8 @@ test('scheduler config push deferred test', # instances()) show real, non-zero usage for both, where before this # feature they showed none for either. Same real-scheduler_srcs link # technique as sched_sim_live_allocation_test/sched_sim_alloc_limit_fanout_ -# test/sched_sim_contention_limit_driver_parity_test above. -sched_sim_e2e_limit_visibility_test_srcs = [ - 'test_sim_e2e_limit_visibility.c' -] -foreach f : scheduler_srcs - if f != 'src/main.c' - sched_sim_e2e_limit_visibility_test_srcs += ['../' + f] - endif -endforeach - -sched_sim_e2e_limit_visibility_test = executable( - 'sched_sim_e2e_limit_visibility_test', - sched_sim_e2e_limit_visibility_test_srcs, - include_directories:[incdir], - dependencies: [scheduler_test_deps], - install: false) - -test('scheduler sim e2e limit visibility test', - sched_sim_e2e_limit_visibility_test, suite: 'scheduler', - env: ['ASAN_OPTIONS=detect_leaks=0']) +# test/sched_sim_contention_limit_driver_parity_test above. Lives in the +# sched_unit_test aggregate now. # libxce-alloc-preason-equality spec, task 3.2 (Req 4.1, 4.4, 6.5): every # allocation of one session -- normal mode (real sched_init()) and @@ -2679,24 +2507,8 @@ test('scheduler trace capture test', # resource indices survive snapshot save and load, in memory and through # the real sched_record_start() -> .replay -> sched_sim_driver_start() seam # (where a NULL resval host decodes as ""). Same real-scheduler_srcs link -# technique as sched_sim_e2e_limit_visibility_test. -sched_snapshot_sparse_resvals_test_srcs = ['test_snapshot_sparse_resvals.c'] -foreach f : scheduler_srcs - if f != 'src/main.c' - sched_snapshot_sparse_resvals_test_srcs += ['../' + f] - endif -endforeach - -sched_snapshot_sparse_resvals_test = executable( - 'sched_snapshot_sparse_resvals_test', - sched_snapshot_sparse_resvals_test_srcs, - include_directories:[incdir], - dependencies: [scheduler_test_deps], - install: false) - -test('scheduler snapshot sparse resvals test', - sched_snapshot_sparse_resvals_test, suite: 'scheduler', - env: ['ASAN_OPTIONS=detect_leaks=0']) +# technique as sched_sim_e2e_limit_visibility_test. Lives in the +# sched_unit_test aggregate now. # scheduler-sim-decision-trace task 1.8: the core trace gate and the # SCHED_TRACE hook macro (design.md "TraceModel", Testing Strategy 3; @@ -2903,23 +2715,9 @@ test('scheduler repl trace file test', # session begin; the file copy byte-equal to the console. Links every # scheduler source except main.c, so the emitter calls the real collapsed- # range flush (repl_rollup.c) and echo printer (sim_loop.c). Leak detection -# stays on. -sched_repl_trace_emit_test_srcs = ['test_repl_trace_emit.c'] -foreach f : scheduler_srcs - if f != 'src/main.c' - sched_repl_trace_emit_test_srcs += ['../' + f] - endif -endforeach - -sched_repl_trace_emit_test = executable( - 'sched_repl_trace_emit_test', - sched_repl_trace_emit_test_srcs, - include_directories:[incdir], - dependencies: [scheduler_deps, unity_dep], - install: false) - -test('scheduler repl trace emit test', - sched_repl_trace_emit_test, suite: 'scheduler') +# stays on. Lives in the sched_unit_test aggregate now -- its +# trace_emit_setup()/trace_emit_teardown() are the one suite in the runner +# with per-suite hooks, registered via SUITE_H. # scheduler-sim-decision-trace task 5.2: the trace commands wired into the # REPL (design.md "ReplIntegration", "SimIntegration" (repl.h gates), @@ -3083,128 +2881,31 @@ test('scheduler trace equivalence test', # bug-1938: admin queue control reaches dispatch (an inactive queue holds its # pending jobs, a closed queue still dispatches them) on both the # normal-mode and sim-mode fixture shapes. Real-scheduler_srcs link -# technique of sched_sim_contention_limit_driver_parity_test. -sched_queue_admin_control_test_srcs = ['test_queue_admin_control.c'] -foreach f : scheduler_srcs - if f != 'src/main.c' - sched_queue_admin_control_test_srcs += ['../' + f] - endif -endforeach - -sched_queue_admin_control_test = executable( - 'sched_queue_admin_control_test', - sched_queue_admin_control_test_srcs, - include_directories:[incdir], - dependencies: [scheduler_test_deps], - install: false) - -test('scheduler queue admin control test', - sched_queue_admin_control_test, suite: 'scheduler', - env: ['ASAN_OPTIONS=detect_leaks=0']) +# technique of sched_sim_contention_limit_driver_parity_test. Lives in the +# sched_unit_test aggregate now. # bug-1939: a host closed by an admin gets no new jobs from either the # serial or the parallel allocator, on both the normal-mode and sim-mode -# fixture shapes. Same real-scheduler_srcs link technique as above. -sched_host_admin_close_test_srcs = ['test_host_admin_close.c'] -foreach f : scheduler_srcs - if f != 'src/main.c' - sched_host_admin_close_test_srcs += ['../' + f] - endif -endforeach - -sched_host_admin_close_test = executable( - 'sched_host_admin_close_test', - sched_host_admin_close_test_srcs, - include_directories:[incdir], - dependencies: [scheduler_test_deps], - install: false) - -test('scheduler host admin close test', - sched_host_admin_close_test, suite: 'scheduler', - env: ['ASAN_OPTIONS=detect_leaks=0']) +# fixture shapes. Same real-scheduler_srcs link technique as above. Lives +# in the sched_unit_test aggregate now. # bug-1963: an unavailable or reconciling host gets no new jobs from either # the serial or the parallel allocator, on both the normal-mode and sim-mode -# fixture shapes. Same real-scheduler_srcs link technique as above. -sched_host_unavail_reconciling_test_srcs = ['test_host_unavail_reconciling.c'] -foreach f : scheduler_srcs - if f != 'src/main.c' - sched_host_unavail_reconciling_test_srcs += ['../' + f] - endif -endforeach - -sched_host_unavail_reconciling_test = executable( - 'sched_host_unavail_reconciling_test', - sched_host_unavail_reconciling_test_srcs, - include_directories:[incdir], - dependencies: [scheduler_test_deps], - install: false) - -test('scheduler host unavail reconciling test', - sched_host_unavail_reconciling_test, suite: 'scheduler', - env: ['ASAN_OPTIONS=detect_leaks=0']) +# fixture shapes. Same real-scheduler_srcs link technique as above. Lives +# in the sched_unit_test aggregate now. # bug-1943: the simulator loads the config's named user/host groups the way # the live scheduler does (snapshot config and CONFIG_PUSH event), so a # user-group-scoped limit matches the same job on both drivers. Same -# real-scheduler_srcs link technique as above. -sched_sim_group_limit_parity_test_srcs = ['test_sim_group_limit_parity.c'] -foreach f : scheduler_srcs - if f != 'src/main.c' - sched_sim_group_limit_parity_test_srcs += ['../' + f] - endif -endforeach - -sched_sim_group_limit_parity_test = executable( - 'sched_sim_group_limit_parity_test', - sched_sim_group_limit_parity_test_srcs, - include_directories:[incdir], - dependencies: [scheduler_test_deps], - install: false) - -test('scheduler sim group limit parity test', - sched_sim_group_limit_parity_test, suite: 'scheduler', - env: ['ASAN_OPTIONS=detect_leaks=0']) +# real-scheduler_srcs link technique as above. Lives in the sched_unit_test +# aggregate now. # bug-1964: a CONFIG_PUSH during a replay reaches the simulator's limit # plugin as the live scheduler's sched_init_config() does. Same -# real-scheduler_srcs link technique as above. -sched_sim_limit_config_push_parity_test_srcs = [ - 'test_sim_limit_config_push_parity.c'] -foreach f : scheduler_srcs - if f != 'src/main.c' - sched_sim_limit_config_push_parity_test_srcs += ['../' + f] - endif -endforeach - -sched_sim_limit_config_push_parity_test = executable( - 'sched_sim_limit_config_push_parity_test', - sched_sim_limit_config_push_parity_test_srcs, - include_directories:[incdir], - dependencies: [scheduler_test_deps], - install: false) - -test('scheduler sim limit config push parity test', - sched_sim_limit_config_push_parity_test, suite: 'scheduler', - env: ['ASAN_OPTIONS=detect_leaks=0']) +# real-scheduler_srcs link technique as above. Lives in the sched_unit_test +# aggregate now. # bug-1944: a job moved to another queue (core JOB_UPDATE event) keeps its # own priority and does not overtake jobs already pending in the target -# queue. Same real-scheduler_srcs link technique as above. -sched_job_move_priority_test_srcs = ['test_job_move_priority.c'] -foreach f : scheduler_srcs - if f != 'src/main.c' - sched_job_move_priority_test_srcs += ['../' + f] - endif -endforeach - -sched_job_move_priority_test = executable( - 'sched_job_move_priority_test', - sched_job_move_priority_test_srcs, - include_directories:[incdir], - dependencies: [scheduler_test_deps], - install: false) - -test('scheduler job move priority test', - sched_job_move_priority_test, suite: 'scheduler', - env: ['ASAN_OPTIONS=detect_leaks=0']) +# queue. Same real-scheduler_srcs link technique as above. Lives in the +# sched_unit_test aggregate now. diff --git a/src/scheduler/testsuite/sched_unit_runner.c b/src/scheduler/testsuite/sched_unit_runner.c new file mode 100644 index 00000000..369d277e --- /dev/null +++ b/src/scheduler/testsuite/sched_unit_runner.c @@ -0,0 +1,196 @@ +/* + * sched_unit_runner.c - single-process Unity runner for the scheduler + * white-box unit suites (controller_unit_test.c pattern). + * + * One process runs every suite that previously shipped as its own + * standalone test executable. Each transformed test file contributes a + * suite entry function (void test_sched_(void)) plus optional + * per-suite setUp/tearDown hooks; the runner's global Unity setUp()/ + * tearDown() (invoked by UnityDefaultTestRun around EVERY case) dispatch + * to the current suite's hooks, preserving per-exe fixture semantics. + * + * -t runs only the named suites (name = suite function name, + * e.g. -t test_sched_election_null_schedobj); no -t runs everything. + */ +#include +#include +#include +#include + +#include + +/* Per-suite fixture hooks (each transformed test file; NULL = no-op). */ +typedef struct { + const char* name; + void (*suite)(void); + void (*setup)(void); /* replaces the file's old setUp() */ + void (*teardown)(void); /* replaces the file's old tearDown() */ +} suite_entry_t; + +/* Runner state used by the global setUp/tearDown below. */ +static const suite_entry_t* g_current = NULL; +static int g_nsel = 0; +static const char* g_sel[512]; + +/* Set to 1 from main() once the registry is wired; lets setUp/tearDown + * no-op safely when Unity runs outside this runner (defensive). */ +static int g_ready = 0; + +/* ---- Global Unity hooks: dispatch to the current suite's hooks ---- */ + +void setUp(void) +{ + if (g_ready && g_current != NULL && g_current->setup != NULL) { + g_current->setup(); + } +} + +void tearDown(void) +{ + if (g_ready && g_current != NULL && g_current->teardown != NULL) { + g_current->teardown(); + } +} + +/* ---- Suite registry (extern decls; one block per transformed file) ---- */ + +/* Suites without fixture hooks (trivial setUp/tearDown in the old exes). */ +#define SUITE(fn) {#fn, fn, NULL, NULL} + +/* Suites with per-suite hooks (the file's old setUp/tearDown, now static). */ +#define SUITE_H(fn, setup, teardown) {#fn, fn, setup, teardown} + +/* Transformee suite entries (extern decls). */ +extern void test_sched_election_null_schedobj(void); +extern void test_sched_picker_iface(void); +extern void test_sched_picker_pendreason_factory_audit(void); +extern void test_sched_picker_core_loop_boundary(void); +extern void test_sched_no_bare_printf(void); +extern void test_sched_core_isolation(void); +extern void test_sched_sim_isolation(void); +extern void test_sched_scheduler_connect(void); +extern void test_sched_repl_output_compression(void); +extern void test_sched_repl_resource_formatting(void); +extern void test_sched_sim_cache_clear_isolation(void); +extern void test_sched_host_admin_close(void); +extern void test_sched_host_unavail_reconciling(void); +extern void test_sched_limit_host_dedup(void); +extern void test_sched_queue_admin_control(void); +extern void test_sched_job_move_priority(void); +extern void test_sched_config_push_deferred(void); +extern void test_sched_sim_group_limit_parity(void); +extern void test_sched_sim_limit_config_push_parity(void); +extern void test_sched_sim_live_allocation(void); +extern void test_sched_sim_e2e_limit_visibility(void); +extern void test_sched_sim_contention_resource_driver_parity(void); +extern void test_sched_sim_contention_limit_driver_parity(void); +extern void test_sched_election_sim_fixture(void); +extern void test_sched_scheduler_dispatch_commit(void); +extern void test_sched_repl_trace_emit(void); +extern void test_sched_snapshot_sparse_resvals(void); +extern void test_sched_sim_alloc_limit_fanout(void); + +/* transformee per-suite hooks (test_repl_trace_emit.c) */ +extern void trace_emit_setup(void); +extern void trace_emit_teardown(void); + +static const suite_entry_t SUITES[] = { +/* %%SUITES%% — populated by the aggregation batches below */ + SUITE(test_sched_election_null_schedobj), + SUITE(test_sched_picker_iface), + SUITE(test_sched_picker_pendreason_factory_audit), + SUITE(test_sched_picker_core_loop_boundary), + SUITE(test_sched_no_bare_printf), + SUITE(test_sched_core_isolation), + SUITE(test_sched_sim_isolation), + SUITE(test_sched_scheduler_connect), + SUITE(test_sched_repl_output_compression), + SUITE(test_sched_repl_resource_formatting), + SUITE(test_sched_sim_cache_clear_isolation), + SUITE(test_sched_host_admin_close), + SUITE(test_sched_host_unavail_reconciling), + SUITE(test_sched_limit_host_dedup), + SUITE(test_sched_queue_admin_control), + SUITE(test_sched_job_move_priority), + SUITE(test_sched_config_push_deferred), + SUITE(test_sched_sim_group_limit_parity), + SUITE(test_sched_sim_limit_config_push_parity), + SUITE(test_sched_sim_live_allocation), + SUITE(test_sched_sim_e2e_limit_visibility), + SUITE(test_sched_sim_contention_resource_driver_parity), + SUITE(test_sched_sim_contention_limit_driver_parity), + SUITE(test_sched_election_sim_fixture), + SUITE(test_sched_scheduler_dispatch_commit), + SUITE_H(test_sched_repl_trace_emit, trace_emit_setup, trace_emit_teardown), + SUITE(test_sched_snapshot_sparse_resvals), + SUITE(test_sched_sim_alloc_limit_fanout), +}; + +#define N_SUITES (sizeof(SUITES) / sizeof(SUITES[0])) + +static error_t parse_opt(int key, char* arg, struct argp_state* state) +{ + switch (key) { + case 't': + if (g_nsel >= (int)(sizeof(g_sel) / sizeof(g_sel[0]))) { + fprintf(stderr, "too many -t selections\n"); + exit(-1); + } + g_sel[g_nsel++] = arg; + break; + default: + return ARGP_ERR_UNKNOWN; + } + return 0; +} + +static struct argp_option options[] = { + {"run", 't', "SUITE", 0, "run only named suite(s)", 0}, + {0} +}; + +static struct argp argp = {options, parse_opt, NULL, + "scheduler unit test runner"}; + +static int selected(const char* name) +{ + int i; + + if (g_nsel == 0) { + return 1; + } + for (i = 0; i < g_nsel; i++) { + if (strcmp(name, g_sel[i]) == 0) { + return 1; + } + } + return 0; +} + +/* bug-1429 lesson (controller_unit_test): stdout is fully buffered when + * meson pipes it, so a FAIL line was lost whenever the run later hung or + * aborted -- line-buffer it so the first failure is always visible. */ +int main(int argc, char* argv[]) +{ + size_t i; + + argp_parse(&argp, argc, argv, 0, 0, NULL); + setvbuf(stdout, NULL, _IOLBF, 0); + + g_ready = 1; + + UNITY_BEGIN(); + + for (i = 0; i < N_SUITES; i++) { + if (!selected(SUITES[i].name)) { + continue; + } + printf("=== suite: %s ===\n", SUITES[i].name); + g_current = &SUITES[i]; + UnitySetTestFile(SUITES[i].name); + SUITES[i].suite(); + } + + g_current = NULL; + return UNITY_END(); +} diff --git a/src/scheduler/testsuite/test_config_push_deferred.c b/src/scheduler/testsuite/test_config_push_deferred.c index b6a76c71..7d9c3ddb 100644 --- a/src/scheduler/testsuite/test_config_push_deferred.c +++ b/src/scheduler/testsuite/test_config_push_deferred.c @@ -54,9 +54,6 @@ extern int scheduler_req_handler(xce_request_t* request, void* args); #define JOBB_ID ((uint64_t)518472ULL) #define JOBC_ID ((uint64_t)518473ULL) -void setUp(void) { return; } -void tearDown(void) { return; } - static void register_slots_resource(var resmgr) { xce_resource_t res; @@ -325,11 +322,11 @@ static void test_config_reapply_updates_queue_in_place_and_frees_old(void) #endif } -int main(void) +/* ---- suite entry for the sched_unit_test aggregate ---------------------- */ +void test_sched_config_push_deferred(void) { - UNITY_BEGIN(); + UnitySetTestFile(__FILE__); RUN_TEST(test_config_push_mid_session_does_not_end_round); RUN_TEST(test_applied_config_push_is_recorded); RUN_TEST(test_config_reapply_updates_queue_in_place_and_frees_old); - return UNITY_END(); } diff --git a/src/scheduler/testsuite/test_core_isolation.c b/src/scheduler/testsuite/test_core_isolation.c index b44a8154..0e44c563 100644 --- a/src/scheduler/testsuite/test_core_isolation.c +++ b/src/scheduler/testsuite/test_core_isolation.c @@ -215,9 +215,6 @@ static char* read_whole_file(const char* path) return buf; } -void setUp(void) { return; } -void tearDown(void) { return; } - /* Sanity check: both source paths baked in by meson.build must actually be * readable -- without this, a stale path would make every scan below * silently pass on zero bytes of text (the exact false-confidence failure @@ -794,9 +791,10 @@ static void test_core_object_has_no_forbidden_undefined_symbols(void) "vacuously)"); } -int main(void) +/* ---- suite entry for the sched_unit_test aggregate ---------------------- */ +void test_sched_core_isolation(void) { - UNITY_BEGIN(); + UnitySetTestFile(__FILE__); RUN_TEST(test_core_source_paths_are_readable); RUN_TEST(test_core_never_includes_forbidden_headers); RUN_TEST(test_core_never_calls_forbidden_symbols); @@ -804,5 +802,4 @@ int main(void) RUN_TEST(test_trace_io_scan_detects_and_ignores); RUN_TEST(test_trace_sources_do_no_stdio_or_file_io); RUN_TEST(test_core_object_has_no_forbidden_undefined_symbols); - return UNITY_END(); } diff --git a/src/scheduler/testsuite/test_host_admin_close.c b/src/scheduler/testsuite/test_host_admin_close.c index 469b8318..568a010b 100644 --- a/src/scheduler/testsuite/test_host_admin_close.c +++ b/src/scheduler/testsuite/test_host_admin_close.c @@ -45,9 +45,6 @@ extern void sim_bootstrap_parjob_allocator(xce_sched_sim_driver_t* sim); #define JOBB_ID ((uint64_t)193902ULL) #define JOBP_ID ((uint64_t)193903ULL) -void setUp(void) { return; } -void tearDown(void) { return; } - static void register_slots_resource(var resmgr) { xce_resource_t res; @@ -272,9 +269,9 @@ static void test_admin_closed_host_gets_no_new_jobs(void) assert_outcome(&(g_sim.core), closed_sim, "sim mode"); } -int main(void) +/* ---- suite entry for the sched_unit_test aggregate ---------------------- */ +void test_sched_host_admin_close(void) { - UNITY_BEGIN(); + UnitySetTestFile(__FILE__); RUN_TEST(test_admin_closed_host_gets_no_new_jobs); - return UNITY_END(); } diff --git a/src/scheduler/testsuite/test_host_unavail_reconciling.c b/src/scheduler/testsuite/test_host_unavail_reconciling.c index c26cf068..d5dc4b1c 100644 --- a/src/scheduler/testsuite/test_host_unavail_reconciling.c +++ b/src/scheduler/testsuite/test_host_unavail_reconciling.c @@ -56,9 +56,6 @@ static const int g_bad_status[NSCENARIOS] = { XCE_WORKER_UNAVAIL, XCE_WORKER_RECONCILING }; static const char* g_bad_label[NSCENARIOS] = { "unavailable", "reconciling" }; -void setUp(void) { return; } -void tearDown(void) { return; } - static void register_slots_resource(var resmgr) { xce_resource_t res; @@ -278,9 +275,9 @@ static void test_unavail_and_reconciling_hosts_get_no_new_jobs(void) } } -int main(void) +/* ---- suite entry for the sched_unit_test aggregate ---------------------- */ +void test_sched_host_unavail_reconciling(void) { - UNITY_BEGIN(); + UnitySetTestFile(__FILE__); RUN_TEST(test_unavail_and_reconciling_hosts_get_no_new_jobs); - return UNITY_END(); } diff --git a/src/scheduler/testsuite/test_job_move_priority.c b/src/scheduler/testsuite/test_job_move_priority.c index 8a891d9b..93b03a2c 100644 --- a/src/scheduler/testsuite/test_job_move_priority.c +++ b/src/scheduler/testsuite/test_job_move_priority.c @@ -39,9 +39,6 @@ #define JOB_B2_ID ((uint64_t)194402ULL) #define JOB_M_ID ((uint64_t)194403ULL) -void setUp(void) { return; } -void tearDown(void) { return; } - static void register_slots_resource(var resmgr) { xce_resource_t res; @@ -219,9 +216,9 @@ static void test_moved_job_keeps_its_priority_and_place(void) "the moved job must not overtake jobs already pending in qb"); } -int main(void) +/* ---- suite entry for the sched_unit_test aggregate ---------------------- */ +void test_sched_job_move_priority(void) { - UNITY_BEGIN(); + UnitySetTestFile(__FILE__); RUN_TEST(test_moved_job_keeps_its_priority_and_place); - return UNITY_END(); } diff --git a/src/scheduler/testsuite/test_limit_host_dedup.c b/src/scheduler/testsuite/test_limit_host_dedup.c index fa44c951..54763860 100644 --- a/src/scheduler/testsuite/test_limit_host_dedup.c +++ b/src/scheduler/testsuite/test_limit_host_dedup.c @@ -45,9 +45,6 @@ #define JOB_ID ((uint64_t)518461ULL) #define NATTEMPTS (5) -void setUp(void) { return; } -void tearDown(void) { return; } - static void register_slots_resource(var resmgr) { xce_resource_t res; @@ -280,10 +277,10 @@ static void test_hlimits_zarray_releases_its_lists(void) printf("test_hlimits_zarray_releases_its_lists: PASS\n"); } -int main(void) +/* ---- suite entry for the sched_unit_test aggregate ---------------------- */ +void test_sched_limit_host_dedup(void) { - UNITY_BEGIN(); + UnitySetTestFile(__FILE__); RUN_TEST(test_repeated_host_attempts_stage_host_limit_once); RUN_TEST(test_hlimits_zarray_releases_its_lists); - return UNITY_END(); } diff --git a/src/scheduler/testsuite/test_no_bare_printf.c b/src/scheduler/testsuite/test_no_bare_printf.c index 312e07e0..9a74637c 100644 --- a/src/scheduler/testsuite/test_no_bare_printf.c +++ b/src/scheduler/testsuite/test_no_bare_printf.c @@ -44,9 +44,6 @@ "XCE_SCHEDULER_PLUGINS_DIR must be defined by meson.build to src/scheduler/src/plugins's absolute path" #endif -void setUp(void) { return; } -void tearDown(void) { return; } - static char* read_whole_file(const char* path) { FILE* f = fopen(path, "rb"); @@ -175,10 +172,10 @@ static void test_scheduler_plugins_has_no_bare_printf_calls(void) scan_dir_for_bare_printf(XCE_SCHEDULER_PLUGINS_DIR); } -int main(void) +/* ---- suite entry for the sched_unit_test aggregate ---------------------- */ +void test_sched_no_bare_printf(void) { - UNITY_BEGIN(); + UnitySetTestFile(__FILE__); RUN_TEST(test_scheduler_src_has_no_bare_printf_calls); RUN_TEST(test_scheduler_plugins_has_no_bare_printf_calls); - return UNITY_END(); } diff --git a/src/scheduler/testsuite/test_picker_core_loop_boundary.c b/src/scheduler/testsuite/test_picker_core_loop_boundary.c index e90d6992..55309d89 100644 --- a/src/scheduler/testsuite/test_picker_core_loop_boundary.c +++ b/src/scheduler/testsuite/test_picker_core_loop_boundary.c @@ -243,13 +243,10 @@ static void test_core_loop_calls_only_through_picker_interface(void) free(body); } -void setUp(void) { return; } -void tearDown(void) { return; } - -int main(void) +/* ---- suite entry for the sched_unit_test aggregate ---------------------- */ +void test_sched_picker_core_loop_boundary(void) { - UNITY_BEGIN(); + UnitySetTestFile(__FILE__); RUN_TEST(test_core_loop_has_no_forbidden_traversal_symbols); RUN_TEST(test_core_loop_calls_only_through_picker_interface); - return UNITY_END(); } diff --git a/src/scheduler/testsuite/test_picker_iface.c b/src/scheduler/testsuite/test_picker_iface.c index a1cf6861..271b885a 100644 --- a/src/scheduler/testsuite/test_picker_iface.c +++ b/src/scheduler/testsuite/test_picker_iface.c @@ -124,8 +124,8 @@ static int stub_on_job_rusage(void* picker, xce_sched_job_t* job, return 0; } -void setUp(void) { return; } -void tearDown(void) { return; } +/* ---- suite entry for the sched_unit_test aggregate ---------------------- */ +void test_sched_picker_iface(void); /* Assigns every hook through an explicitly-typed intermediate function * pointer -- see file header comment. If any field's declared signature in @@ -218,10 +218,9 @@ static void test_picker_iface_optional_hooks_may_be_null(void) TEST_ASSERT_NOT_NULL(iface.next_job); } -int main(void) +void test_sched_picker_iface(void) { - UNITY_BEGIN(); + UnitySetTestFile(__FILE__); RUN_TEST(test_picker_iface_has_every_hook_with_correct_signature); RUN_TEST(test_picker_iface_optional_hooks_may_be_null); - return UNITY_END(); } diff --git a/src/scheduler/testsuite/test_picker_pendreason_factory_audit.c b/src/scheduler/testsuite/test_picker_pendreason_factory_audit.c index 7bb0cb06..2266373a 100644 --- a/src/scheduler/testsuite/test_picker_pendreason_factory_audit.c +++ b/src/scheduler/testsuite/test_picker_pendreason_factory_audit.c @@ -156,8 +156,8 @@ static int scan_file_for_violation(const char* path, char* violating_line_out, return found; } -void setUp(void) { return; } -void tearDown(void) { return; } +/* ---- suite entry for the sched_unit_test aggregate ---------------------- */ +void test_sched_picker_pendreason_factory_audit(void); /* Sanity check for the audit itself: every baked-in path must actually * open. Without this, a stale/typo'd relative path would make @@ -233,11 +233,10 @@ static void test_no_direct_pendreason_calloc_in_scheduler_tree(void) } } -int main(void) +void test_sched_picker_pendreason_factory_audit(void) { - UNITY_BEGIN(); + UnitySetTestFile(__FILE__); RUN_TEST(test_all_scanned_paths_are_readable); RUN_TEST(test_detector_fires_on_same_line_and_not_on_split_lines); RUN_TEST(test_no_direct_pendreason_calloc_in_scheduler_tree); - return UNITY_END(); } diff --git a/src/scheduler/testsuite/test_queue_admin_control.c b/src/scheduler/testsuite/test_queue_admin_control.c index 582efd06..f20d5fbc 100644 --- a/src/scheduler/testsuite/test_queue_admin_control.c +++ b/src/scheduler/testsuite/test_queue_admin_control.c @@ -49,9 +49,6 @@ extern void sim_bootstrap_parjob_allocator(xce_sched_sim_driver_t* sim); #define JOB_CLOSED_ID ((uint64_t)193802ULL) #define JOB_INACT_ID ((uint64_t)193803ULL) -void setUp(void) { return; } -void tearDown(void) { return; } - static void register_slots_resource(var resmgr) { xce_resource_t res; @@ -282,9 +279,9 @@ static void test_inactive_queue_holds_jobs_closed_queue_dispatches(void) assert_outcome(&(g_sim.core), n_sim, "sim mode"); } -int main(void) +/* ---- suite entry for the sched_unit_test aggregate ---------------------- */ +void test_sched_queue_admin_control(void) { - UNITY_BEGIN(); + UnitySetTestFile(__FILE__); RUN_TEST(test_inactive_queue_holds_jobs_closed_queue_dispatches); - return UNITY_END(); } diff --git a/src/scheduler/testsuite/test_repl_output_compression.c b/src/scheduler/testsuite/test_repl_output_compression.c index f6ea5ff3..e0bfb8e9 100644 --- a/src/scheduler/testsuite/test_repl_output_compression.c +++ b/src/scheduler/testsuite/test_repl_output_compression.c @@ -86,9 +86,6 @@ extern int repl_fmt_jobid_range(char* buf, size_t bufsz, const uint64_t* jobids, int njobids); -void setUp(void) { return; } -void tearDown(void) { return; } - /* ---------------------------------------------------------------------- */ /* Fixture helpers -- real, correctly bit-packed jobids (see header */ /* comment above for the exact encoding each mirrors). */ @@ -303,15 +300,13 @@ static void test_buffer_too_small_fails_safely_without_truncating(void) "test_buffer_too_small_fails_safely_without_truncating: PASS\n"); } -int main(void) +/* ---- suite entry for the sched_unit_test aggregate ---------------------- */ +void test_sched_repl_output_compression(void) { - UNITY_BEGIN(); - + UnitySetTestFile(__FILE__); RUN_TEST(test_contiguous_array_range_compresses_to_single_range); RUN_TEST(test_noncontiguous_indices_compress_to_commajoined_subranges); RUN_TEST(test_multiple_array_submissions_compress_independently); RUN_TEST(test_mixed_array_and_nonarray_ids_shows_nonarray_individually); RUN_TEST(test_buffer_too_small_fails_safely_without_truncating); - - return UNITY_END(); } diff --git a/src/scheduler/testsuite/test_repl_resource_formatting.c b/src/scheduler/testsuite/test_repl_resource_formatting.c index ff3cf602..a0466f15 100644 --- a/src/scheduler/testsuite/test_repl_resource_formatting.c +++ b/src/scheduler/testsuite/test_repl_resource_formatting.c @@ -109,9 +109,6 @@ extern bool repl_is_bytes_valued_resource(const char* name); extern void repl_format_bytes_human(double bytes, char* buf, size_t bufsz); -void setUp(void) { return; } -void tearDown(void) { return; } - /* ---------------------------------------------------------------------- */ /* Test 1 (AC 6.1): the classifier returns true for EXACTLY the five */ /* confirmed canonical-bytes resource names. */ @@ -406,10 +403,10 @@ static void test_shared_current_units_mode_reads_state_or_defaults(void) TEST_ASSERT_EQUAL_INT(XCE_REPL_UNITS_RAW, repl_current_units_mode(&sim)); } -int main(void) +/* ---- suite entry for the sched_unit_test aggregate ---------------------- */ +void test_sched_repl_resource_formatting(void) { - UNITY_BEGIN(); - + UnitySetTestFile(__FILE__); RUN_TEST(test_bytes_valued_classifier_true_for_canonical_five); RUN_TEST(test_bytes_valued_classifier_false_for_swp_unitless_and_unknown); RUN_TEST( @@ -421,6 +418,4 @@ int main(void) RUN_TEST(test_shared_numeric_resource_value_formats_per_units_mode); RUN_TEST(test_shared_consumable_value_and_used_formats); RUN_TEST(test_shared_current_units_mode_reads_state_or_defaults); - - return UNITY_END(); } diff --git a/src/scheduler/testsuite/test_repl_trace_emit.c b/src/scheduler/testsuite/test_repl_trace_emit.c index cf3daf30..9dc1c478 100644 --- a/src/scheduler/testsuite/test_repl_trace_emit.c +++ b/src/scheduler/testsuite/test_repl_trace_emit.c @@ -58,7 +58,8 @@ static int g_cap_fd = -1; static int g_cap_saved = -1; static char g_cap_path[64]; -void setUp(void) +/* Per-suite hooks for the sched_unit_test aggregate (were setUp/tearDown). */ +void trace_emit_setup(void) { memset(&g_sim, 0, sizeof(g_sim)); memset(&g_rs, 0, sizeof(g_rs)); @@ -73,7 +74,7 @@ void setUp(void) TEST_ASSERT_EQUAL_INT(0, chdir(g_dir)); } -void tearDown(void) +void trace_emit_teardown(void) { repl_trace_shutdown(&g_sim); free(g_rs.collapse_pend_jobids); @@ -692,9 +693,10 @@ static void test_file_write_error_inside_render_reports_cause(void) repl_trace_session_end(&g_sim); } -int main(void) +/* ---- suite entry for the sched_unit_test aggregate ---------------------- */ +void test_sched_repl_trace_emit(void) { - UNITY_BEGIN(); + UnitySetTestFile(__FILE__); RUN_TEST(test_session_begin_publishes_next_with_stamp); RUN_TEST(test_session_begin_with_tracing_off_publishes_nothing); RUN_TEST(test_command_during_session_applies_next_session); @@ -707,5 +709,4 @@ int main(void) RUN_TEST(test_file_copy_byte_equal_to_console); RUN_TEST(test_file_write_error_inside_render_reports_cause); RUN_TEST(test_file_write_error_reported_once_per_session); - return UNITY_END(); } diff --git a/src/scheduler/testsuite/test_sched_election_null_schedobj.c b/src/scheduler/testsuite/test_sched_election_null_schedobj.c index a77181c1..7b73006f 100644 --- a/src/scheduler/testsuite/test_sched_election_null_schedobj.c +++ b/src/scheduler/testsuite/test_sched_election_null_schedobj.c @@ -34,8 +34,8 @@ #define TEST_JOBID ((uint64_t)189701ULL) #define QUEUE_NAME "normal" -void setUp(void) { return; } -void tearDown(void) { return; } +/* ---- suite entry for the sched_unit_test aggregate ---------------------- */ +void test_sched_election_null_schedobj(void); static void test_sched_allocator_skips_job_without_schedobj(void) { @@ -107,9 +107,8 @@ static void test_sched_allocator_skips_job_without_schedobj(void) TEST_ASSERT_NULL(job->allocs); } -int main(void) +void test_sched_election_null_schedobj(void) { - UNITY_BEGIN(); + UnitySetTestFile(__FILE__); RUN_TEST(test_sched_allocator_skips_job_without_schedobj); - return UNITY_END(); } diff --git a/src/scheduler/testsuite/test_sched_election_sim_fixture.c b/src/scheduler/testsuite/test_sched_election_sim_fixture.c index 7e0fa41d..0a7badd5 100644 --- a/src/scheduler/testsuite/test_sched_election_sim_fixture.c +++ b/src/scheduler/testsuite/test_sched_election_sim_fixture.c @@ -100,9 +100,6 @@ #define QUEUE_NAME "normal" #define TEST_RESREQ ((char*)"select[type==any] rusage[mem=1]") -void setUp(void) { return; } -void tearDown(void) { return; } - /* * Req 1.1/1.2/5.1: sched_job_picker()/sched_allocator() (sched_election.c), * spawned via pthread_create() against nothing but a bare @@ -288,9 +285,9 @@ test_sched_election_thread_pair_runs_against_bare_core_fixture(void) TEST_ASSERT_NULL(job->accounts); } -int main(void) +/* ---- suite entry for the sched_unit_test aggregate ---------------------- */ +void test_sched_election_sim_fixture(void) { - UNITY_BEGIN(); + UnitySetTestFile(__FILE__); RUN_TEST(test_sched_election_thread_pair_runs_against_bare_core_fixture); - return UNITY_END(); } diff --git a/src/scheduler/testsuite/test_scheduler_connect.c b/src/scheduler/testsuite/test_scheduler_connect.c index dd1dcf54..b0b99ec6 100644 --- a/src/scheduler/testsuite/test_scheduler_connect.c +++ b/src/scheduler/testsuite/test_scheduler_connect.c @@ -79,9 +79,6 @@ extern int scheduler_req_handler(xce_request_t*, void*); -void setUp(void) { return; } -void tearDown(void) { return; } - /* ════════════════════════════════════════════════════════════════════════ * Helpers * ════════════════════════════════════════════════════════════════════════ */ @@ -570,9 +567,10 @@ static void test_no_periodic_heartbeat_call_in_source(void) printf("test_no_periodic_heartbeat_call_in_source: PASS\n"); } -int main(void) +/* ---- suite entry for the sched_unit_test aggregate ---------------------- */ +void test_sched_scheduler_connect(void) { - UNITY_BEGIN(); + UnitySetTestFile(__FILE__); RUN_TEST(test_no_peers_and_single_entry_peers_produce_identical_cluster_cfg_shape); RUN_TEST(test_multi_candidate_cluster_cfg_passthrough); RUN_TEST(test_sched_init_all_candidates_unreachable_fails_fast); @@ -582,5 +580,4 @@ int main(void) RUN_TEST(test_no_periodic_heartbeat_call_in_source); RUN_TEST(test_rejoin_callback_body_has_no_io_or_xcecli_calls); RUN_TEST(test_sched_init_has_single_connect_sequence_not_a_loop); - return UNITY_END(); } diff --git a/src/scheduler/testsuite/test_scheduler_dispatch_commit.c b/src/scheduler/testsuite/test_scheduler_dispatch_commit.c index fdafadc2..8f51783b 100644 --- a/src/scheduler/testsuite/test_scheduler_dispatch_commit.c +++ b/src/scheduler/testsuite/test_scheduler_dispatch_commit.c @@ -133,9 +133,6 @@ static xce_job_alloc_t* make_dispatch_alloc(uint64_t jobid, char* host, return j; } -void setUp(void) { return; } -void tearDown(void) { return; } - /* * Requirement 1.1: committing a DISPATCH decision transitions the job to * JOB_STAT_RUN in the SAME operation that commits job->allocs/job->accounts @@ -436,13 +433,13 @@ static void test_dispatch_commit_multi_round_gap_matches_same_round_confirmation TEST_ASSERT_EQUAL_FLOAT(same_round_val, multi_round_gap_val); } -int main(void) +/* ---- suite entry for the sched_unit_test aggregate ---------------------- */ +void test_sched_scheduler_dispatch_commit(void) { - UNITY_BEGIN(); + UnitySetTestFile(__FILE__); RUN_TEST(test_dispatch_commit_transitions_job_to_run); RUN_TEST(test_dispatch_commit_survives_round_boundary_before_confirmation); RUN_TEST(test_dispatch_commit_survives_several_rounds_before_confirmation); RUN_TEST(test_dispatch_commit_multi_round_gap_matches_same_round_confirmation); RUN_TEST(test_pend_decision_does_not_touch_job_state); - return UNITY_END(); } diff --git a/src/scheduler/testsuite/test_sim_alloc_limit_fanout.c b/src/scheduler/testsuite/test_sim_alloc_limit_fanout.c index 46554ba7..31cb7134 100644 --- a/src/scheduler/testsuite/test_sim_alloc_limit_fanout.c +++ b/src/scheduler/testsuite/test_sim_alloc_limit_fanout.c @@ -110,9 +110,6 @@ extern void sim_bootstrap_parjob_allocator(xce_sched_sim_driver_t* sim); #define LIMIT_RESNAME "sim_alloc_host_res" #define LIMIT_NAME "sim_alloc_host_limit" -void setUp(void) { return; } -void tearDown(void) { return; } - /* ---------------------------------------------------------------------- */ /* Fixture helpers */ /* ---------------------------------------------------------------------- */ @@ -380,10 +377,10 @@ test_host_scoped_limit_usage_instance_created_via_live_sim_dispatch(void) "dispatch: PASS\n"); } -int main(void) +/* ---- suite entry for the sched_unit_test aggregate ---------------------- */ +void test_sched_sim_alloc_limit_fanout(void) { - UNITY_BEGIN(); + UnitySetTestFile(__FILE__); RUN_TEST( test_host_scoped_limit_usage_instance_created_via_live_sim_dispatch); - return UNITY_END(); } diff --git a/src/scheduler/testsuite/test_sim_cache_clear_isolation.c b/src/scheduler/testsuite/test_sim_cache_clear_isolation.c index 407ac83b..2b6a7b97 100644 --- a/src/scheduler/testsuite/test_sim_cache_clear_isolation.c +++ b/src/scheduler/testsuite/test_sim_cache_clear_isolation.c @@ -71,22 +71,8 @@ #include "sched/alloc_cache.h" #include "sim.h" -void kill_sched_job(void* arg) { (void)arg; } -void kill_sched_queue(void* arg) { (void)arg; } -void kill_sched_worker(void* arg) { (void)arg; } -void kill_sched_user(void* arg) { (void)arg; } -void kill_sched_project(void* arg) { (void)arg; } -void kill_sched_resval(xce_val_t* val) { (void)val; } -void plugin_unregister(void* arg) { (void)arg; } - -/* sched_worker_release_host_ctx (resource.c) is outside this test's linked - * source set (only core.c/core_clock.c/core_session.c/decision.c/ - * alloc_cache.c, meson.build) -- this fixture never adds a worker, so it - * is never actually invoked at runtime either. */ -void sched_worker_release_host_ctx(xce_sched_worker_t* w) { (void)w; } - -void setUp(void) { return; } -void tearDown(void) { return; } +/* kill_sched_* / plugin_unregister / sched_worker_release_host_ctx come + * from the aggregate's shared fixture (sched_unit_fixture.c). */ /* * THE Observable this regression guards (Req 7.2, round-2 review @@ -181,10 +167,10 @@ static void test_sim_registered_cache_clear_uses_the_core_table(void) destroy(sim.core.unsatisfiable_cache); } -int main(void) +/* ---- suite entry for the sched_unit_test aggregate ---------------------- */ +void test_sched_sim_cache_clear_isolation(void) { - UNITY_BEGIN(); + UnitySetTestFile(__FILE__); RUN_TEST(test_sim_begin_session_never_corrupts_alt_events_file); RUN_TEST(test_sim_registered_cache_clear_uses_the_core_table); - return UNITY_END(); } diff --git a/src/scheduler/testsuite/test_sim_contention_limit_driver_parity.c b/src/scheduler/testsuite/test_sim_contention_limit_driver_parity.c index e19785f5..52527816 100644 --- a/src/scheduler/testsuite/test_sim_contention_limit_driver_parity.c +++ b/src/scheduler/testsuite/test_sim_contention_limit_driver_parity.c @@ -103,9 +103,6 @@ extern void sim_bootstrap_parjob_allocator(xce_sched_sim_driver_t* sim); #define JOBB_ID ((uint64_t)510202ULL) #define JOBC_ID ((uint64_t)510203ULL) -void setUp(void) { return; } -void tearDown(void) { return; } - /* ---------------------------------------------------------------------- */ /* Fixture helpers -- identical techniques to this file's sibling */ /* (test_sim_contention_resource_driver_parity.c) plus test_sim_alloc_ */ @@ -577,10 +574,10 @@ test_limit_constrained_contention_matches_between_normal_and_sim_drivers( "sim_drivers: PASS\n"); } -int main(void) +/* ---- suite entry for the sched_unit_test aggregate ---------------------- */ +void test_sched_sim_contention_limit_driver_parity(void) { - UNITY_BEGIN(); + UnitySetTestFile(__FILE__); RUN_TEST( test_limit_constrained_contention_matches_between_normal_and_sim_drivers); - return UNITY_END(); } diff --git a/src/scheduler/testsuite/test_sim_contention_resource_driver_parity.c b/src/scheduler/testsuite/test_sim_contention_resource_driver_parity.c index b937ffbf..ab544b1a 100644 --- a/src/scheduler/testsuite/test_sim_contention_resource_driver_parity.c +++ b/src/scheduler/testsuite/test_sim_contention_resource_driver_parity.c @@ -145,9 +145,6 @@ extern void sim_bootstrap_parjob_allocator(xce_sched_sim_driver_t* sim); #define JOBB_ID ((uint64_t)510102ULL) #define JOBC_ID ((uint64_t)510103ULL) -void setUp(void) { return; } -void tearDown(void) { return; } - /* ---------------------------------------------------------------------- */ /* Fixture helpers -- same techniques test_sched_election_sim_fixture.c/ */ /* test_sim_alloc_limit_fanout.c/test_sim_contention_parity.c each already */ @@ -578,9 +575,9 @@ test_resource_contention_matches_between_normal_and_sim_drivers(void) "drivers: PASS\n"); } -int main(void) +/* ---- suite entry for the sched_unit_test aggregate ---------------------- */ +void test_sched_sim_contention_resource_driver_parity(void) { - UNITY_BEGIN(); + UnitySetTestFile(__FILE__); RUN_TEST(test_resource_contention_matches_between_normal_and_sim_drivers); - return UNITY_END(); } diff --git a/src/scheduler/testsuite/test_sim_e2e_limit_visibility.c b/src/scheduler/testsuite/test_sim_e2e_limit_visibility.c index c75c8839..5fc8a3b7 100644 --- a/src/scheduler/testsuite/test_sim_e2e_limit_visibility.c +++ b/src/scheduler/testsuite/test_sim_e2e_limit_visibility.c @@ -149,9 +149,6 @@ extern int write_capnp_message(FILE* f, struct capn* c); #define HOST_LIMIT_PERCENT_VAL 50.0f #define HOST_RES_CAPACITY 1000.0f -void setUp(void) { return; } -void tearDown(void) { return; } - /* ---------------------------------------------------------------------- */ /* Fixture helpers -- capnp event writers duplicated from test_sim_live_ */ /* allocation.c's own proven shape (this directory's established */ @@ -717,9 +714,9 @@ test_sim_replay_shows_real_global_and_host_scoped_limit_usage(void) "PASS\n"); } -int main(void) +/* ---- suite entry for the sched_unit_test aggregate ---------------------- */ +void test_sched_sim_e2e_limit_visibility(void) { - UNITY_BEGIN(); + UnitySetTestFile(__FILE__); RUN_TEST(test_sim_replay_shows_real_global_and_host_scoped_limit_usage); - return UNITY_END(); } diff --git a/src/scheduler/testsuite/test_sim_group_limit_parity.c b/src/scheduler/testsuite/test_sim_group_limit_parity.c index a3a8721e..08278e2d 100644 --- a/src/scheduler/testsuite/test_sim_group_limit_parity.c +++ b/src/scheduler/testsuite/test_sim_group_limit_parity.c @@ -54,9 +54,6 @@ extern void sim_bootstrap_parjob_allocator(xce_sched_sim_driver_t* sim); #define JOB_USER "user1" #define JOB_ID ((uint64_t)194301ULL) -void setUp(void) { return; } -void tearDown(void) { return; } - static void register_resources(var resmgr) { xce_resource_t res; @@ -340,9 +337,9 @@ static void test_user_group_limit_matches_in_sim_as_in_live(void) TEST_ASSERT_TRUE(is_in_group(g, (char*)WORKER_NAME) > 0); } -int main(void) +/* ---- suite entry for the sched_unit_test aggregate ---------------------- */ +void test_sched_sim_group_limit_parity(void) { - UNITY_BEGIN(); + UnitySetTestFile(__FILE__); RUN_TEST(test_user_group_limit_matches_in_sim_as_in_live); - return UNITY_END(); } diff --git a/src/scheduler/testsuite/test_sim_isolation.c b/src/scheduler/testsuite/test_sim_isolation.c index ae0db4d9..0991da44 100644 --- a/src/scheduler/testsuite/test_sim_isolation.c +++ b/src/scheduler/testsuite/test_sim_isolation.c @@ -603,9 +603,6 @@ static int dirname_of(const char* path, char* out, size_t out_sz) return 1; } -void setUp(void) { return; } -void tearDown(void) { return; } - /* Sanity check: all three source paths baked in by meson.build must * actually be readable -- without this, a stale path would make every scan * below silently pass on zero bytes of text (the exact false-confidence @@ -1156,9 +1153,10 @@ static void test_sim_object_has_no_forbidden_undefined_symbols(void) "vacuously)"); } -int main(void) +/* ---- suite entry for the sched_unit_test aggregate ---------------------- */ +void test_sched_sim_isolation(void) { - UNITY_BEGIN(); + UnitySetTestFile(__FILE__); RUN_TEST(test_sim_source_paths_are_readable); RUN_TEST(test_sim_never_includes_forbidden_headers); RUN_TEST(test_sim_never_calls_forbidden_symbols); @@ -1167,5 +1165,4 @@ int main(void) RUN_TEST(test_trace_enable_is_repl_only); RUN_TEST(test_sim_driver_struct_has_no_forbidden_fields); RUN_TEST(test_sim_object_has_no_forbidden_undefined_symbols); - return UNITY_END(); } diff --git a/src/scheduler/testsuite/test_sim_limit_config_push_parity.c b/src/scheduler/testsuite/test_sim_limit_config_push_parity.c index c2e9da65..6a4d5757 100644 --- a/src/scheduler/testsuite/test_sim_limit_config_push_parity.c +++ b/src/scheduler/testsuite/test_sim_limit_config_push_parity.c @@ -56,9 +56,6 @@ extern void sim_bootstrap_parjob_allocator(xce_sched_sim_driver_t* sim); #define JOB_USER "user1" #define JOB_ID ((uint64_t)196401ULL) -void setUp(void) { return; } -void tearDown(void) { return; } - static void register_resources(var resmgr) { xce_resource_t res; @@ -317,9 +314,9 @@ static void test_config_push_reaches_limit_plugin_in_sim_as_in_live(void) "sim: the pushed limit must match the job as it does live"); } -int main(void) +/* ---- suite entry for the sched_unit_test aggregate ---------------------- */ +void test_sched_sim_limit_config_push_parity(void) { - UNITY_BEGIN(); + UnitySetTestFile(__FILE__); RUN_TEST(test_config_push_reaches_limit_plugin_in_sim_as_in_live); - return UNITY_END(); } diff --git a/src/scheduler/testsuite/test_sim_live_allocation.c b/src/scheduler/testsuite/test_sim_live_allocation.c index 44e4761f..77eba608 100644 --- a/src/scheduler/testsuite/test_sim_live_allocation.c +++ b/src/scheduler/testsuite/test_sim_live_allocation.c @@ -132,9 +132,6 @@ extern int write_capnp_message(FILE* f, struct capn* c); #define TEST_JOBID ((uint64_t)940101ULL) #define WORKER_SLOTS 4.0f -void setUp(void) { return; } -void tearDown(void) { return; } - /* ---------------------------------------------------------------------- */ /* Fixture helpers */ /* ---------------------------------------------------------------------- */ @@ -842,12 +839,12 @@ static void test_sim_replay_reproduces_recorded_alloc_from(void) free(captured); } -int main(void) +/* ---- suite entry for the sched_unit_test aggregate ---------------------- */ +void test_sched_sim_live_allocation(void) { - UNITY_BEGIN(); + UnitySetTestFile(__FILE__); RUN_TEST(test_sim_driver_run_dispatches_a_job_with_available_resources); RUN_TEST( test_sim_verify_no_false_mismatch_after_live_dispatch_and_later_confirmation); RUN_TEST(test_sim_replay_reproduces_recorded_alloc_from); - return UNITY_END(); } diff --git a/src/scheduler/testsuite/test_snapshot_sparse_resvals.c b/src/scheduler/testsuite/test_snapshot_sparse_resvals.c index 76fdf701..ea0d8069 100644 --- a/src/scheduler/testsuite/test_snapshot_sparse_resvals.c +++ b/src/scheduler/testsuite/test_snapshot_sparse_resvals.c @@ -47,9 +47,6 @@ #define LICENSE_TOTAL 2.0f #define GPU_TOTAL 8.0f -void setUp(void) { return; } -void tearDown(void) { return; } - /* ---------------------------------------------------------------------- */ /* Fixture helpers */ /* ---------------------------------------------------------------------- */ @@ -388,14 +385,14 @@ static void test_replay_round_trip_keeps_sparse_resvals(void) rmdir(tmpl); } -int main(void) +/* ---- suite entry for the sched_unit_test aggregate ---------------------- */ +void test_sched_snapshot_sparse_resvals(void) { - UNITY_BEGIN(); + UnitySetTestFile(__FILE__); RUN_TEST(test_save_keeps_sparse_shared_resval); RUN_TEST(test_save_keeps_sparse_worker_resval); RUN_TEST(test_save_load_round_trip_keeps_sparse_resvals); RUN_TEST(test_load_takes_shared_resval_with_empty_host); RUN_TEST(test_load_skips_resval_with_named_host); RUN_TEST(test_replay_round_trip_keeps_sparse_resvals); - return UNITY_END(); }