New alloc_runner.c: sched_allocator_run() validates its inputs (-EINVAL without touching the pend reason), applies the plugin's optional accepts guard, creates the pend-reason record, then checks shared resources: one host-less NO_RESOURCE reason per unmet entry (skip only on vget < 0, fixing bug-1893) and the met amounts counted once as uncommitted. Plan search follows in task 3.2. Runner tests use a fake allocator contract; the pend-reason factory audit now scans the runner. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2408 lines
125 KiB
Meson
2408 lines
125 KiB
Meson
scheduler_test_src = [
|
|
'test.c',
|
|
]
|
|
|
|
# libedit_dep (defined in the parent meson.build, task 12.1, Req 5 AC 22):
|
|
# every white-box test TU that #includes ../src/sim_loop.c now transitively
|
|
# pulls in repl.h's inline wrappers, which reference repl.c's real
|
|
# readline()/add_history() calls the moment ANY such TU also #includes
|
|
# ../src/repl.c (already required at link time regardless -- sim_loop.c's
|
|
# own repl.h wrappers reference xce_repl_start()/xce_repl_post_session_check()
|
|
# unconditionally). Added to the shared deps list rather than per-test so
|
|
# every current and future sim-family white-box test picks it up
|
|
# automatically.
|
|
scheduler_test_deps = [libxce_deps, librtti_dep, unity_dep, libxce_dep,
|
|
libedit_dep]
|
|
|
|
incdir = include_directories('../include', '../../include', '.', '../src', '../../lib')
|
|
|
|
scheduler_test = executable('sched_test',
|
|
scheduler_test_src,
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps],
|
|
install: false)
|
|
|
|
# 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.
|
|
sched_job_update_test = executable('sched_job_update_test',
|
|
['test_job_update.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps],
|
|
install: false)
|
|
|
|
# White-box test for the notify/dataset enqueue handlers. It #includes
|
|
# ../src/handler.c directly (enq_pend_update + the static handlers), so it is a
|
|
# standalone TU with its own main() — built as a separate executable.
|
|
sched_handlers_test = executable('sched_handlers_test',
|
|
['test_handlers.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps],
|
|
install: false)
|
|
|
|
# White-box test for the compact job-array push receive/expand path
|
|
# (job-array-single-wal-record task 5.3). It also #includes ../src/handler.c
|
|
# directly, but additionally needs a REAL sched->jobs kvmgr (sched_get_job/
|
|
# sched_add_job) to exercise the per-element dedup check for real — kept as
|
|
# its own binary rather than folded into sched_handlers_test so that file's
|
|
# "self-contained, only sched_init_config stubbed" story stays accurate.
|
|
sched_job_array_test = executable('sched_job_array_test',
|
|
['test_job_array_expand.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps],
|
|
install: false)
|
|
|
|
# Cross-daemon integration test (job-array-single-wal-record task 5.5): the
|
|
# REAL xce_encode()/xce_decode()/extract_data() -> scheduler_req_handler()
|
|
# chain (the top-level function vtask_entry() registers as its handler),
|
|
# proving one-push/N-tasks/log-once and redelivery-safety under genuinely
|
|
# re-decoded wire bytes -- one layer more real than sched_job_array_test's
|
|
# own wire-dispatch case, which stops at sched_handle_dataset(). Kept as its
|
|
# own binary for the same reason sched_job_array_test is separate from
|
|
# sched_handlers_test: it needs a REAL sched->jobs kvmgr for the dedup check.
|
|
sched_job_array_wire_e2e_test = executable('sched_job_array_wire_e2e_test',
|
|
['test_job_array_wire_e2e.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps],
|
|
install: false)
|
|
|
|
# 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)
|
|
|
|
# White-box test for the picker plugin registration category and the
|
|
# job_elect_fn compatibility wrapper (scheduler-core spec, task 1.2). It
|
|
# #includes ../src/plugin.c directly (same white-box pattern as
|
|
# sched_handlers_test/sched_job_array_test) so it exercises the real
|
|
# plugin_register() and the real legacy_picker_wrapper_iface, and needs a
|
|
# REAL sched->plugins kvmgr (same setup scheduler.c's sched_plugin_init()
|
|
# uses) to register plugins through it for real.
|
|
sched_picker_registration_test = executable('sched_picker_registration_test',
|
|
['test_plugin_picker_registration.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps],
|
|
install: false)
|
|
|
|
# White-box test for the driver-agnostic plugin-hook dispatch functions
|
|
# (plugin_job_election/plugin_prepare_allocation/plugin_commit_decision) and
|
|
# the new xce_sched_plugin_t.core field (scheduler-sim-live-allocation spec,
|
|
# task 1.2, "Plugin Hook Dispatchers"). It #includes ../src/plugin.c
|
|
# directly (same white-box pattern as sched_picker_registration_test) so it
|
|
# exercises the real dispatch loops and the real plugin_register()/
|
|
# plugin_register_core() entry points, not a re-implementation of either.
|
|
sched_plugin_hook_dispatch_test = executable('sched_plugin_hook_dispatch_test',
|
|
['test_plugin_hook_dispatch.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps],
|
|
install: false)
|
|
|
|
# White-box test for the picker configuration fields added to
|
|
# xce_scheduler_t/xce_sched_queue_t/xce_sched_project_t (scheduler-core
|
|
# spec, task 1.3). It #includes ../src/schedobj.c directly (same white-box
|
|
# pattern as sched_job_update_test) so it exercises the real
|
|
# make_sched_queue/make_sched_project/sched_set_default_job_pick_plugin,
|
|
# not a re-implementation of any of them.
|
|
sched_picker_config_fields_test = executable('sched_picker_config_fields_test',
|
|
['test_picker_config_fields.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps],
|
|
install: false)
|
|
|
|
# White-box test for builtin_fcfs's xce_job_picker_iface_t lifecycle hooks
|
|
# (scheduler-core spec, task 2.1). It #includes ../src/plugins/builtin_fcfs.c
|
|
# directly (same white-box pattern as sched_picker_registration_test) so it
|
|
# exercises the real builtin_fcfs_init()/builtin_fcfs_fini() and the real
|
|
# private fcfs_plugin_data_t layout, not a re-implementation of either.
|
|
sched_picker_fcfs_test = executable('sched_picker_fcfs_test',
|
|
['test_picker_fcfs.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps],
|
|
install: false)
|
|
|
|
# White-box test for builtin_fcfs's session hooks (begin_session/next_job/
|
|
# end_session) and post-allocation hooks (on_dispatch/on_pend) (scheduler-core
|
|
# spec, task 2.3). Split out of test_picker_fcfs.c rather than appended to it
|
|
# -- that file was already ~765 lines after tasks 2.1/2.2, against this
|
|
# project's 800-line ceiling. Also #includes ../src/plugins/builtin_fcfs.c
|
|
# directly (same white-box pattern as sched_picker_fcfs_test), and supplies
|
|
# its own sched_queue_is_ready()/sched_job_is_ready() test doubles since this
|
|
# translation unit does not link scheduler.c (see the file header comment).
|
|
sched_picker_fcfs_session_test = executable('sched_picker_fcfs_session_test',
|
|
['test_picker_fcfs_session.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps],
|
|
install: false)
|
|
|
|
# White-box test for wiring builtin_fcfs in as the registered default picker
|
|
# and removing the hardcoded "xce_sched_fcfs" picker string (scheduler-core
|
|
# spec, task 2.4). It #includes ../src/plugin.c, ../src/schedobj.c, and
|
|
# ../src/plugins/builtin_fcfs.c directly (same white-box pattern as the
|
|
# other picker tests) so it exercises the real plugin_register(),
|
|
# register_builtin_fcfs(), sched_set_default_job_pick_plugin(), and
|
|
# sched_resolve_job_picker() together -- not a re-implementation of any of
|
|
# them. See the file's own header comment for why sched_job_picker() itself
|
|
# (scheduler.c) is covered at the resolved-plugin level rather than by
|
|
# whole-file-including scheduler.c.
|
|
sched_picker_wiring_test = executable('sched_picker_wiring_test',
|
|
['test_picker_wiring.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps],
|
|
install: false)
|
|
|
|
# Regression guard for the core scheduling loop boundary (scheduler-core
|
|
# spec, task 2.5, Req 1 AC 1 / AC 7): "the core loop calls only
|
|
# picker->next_job() ... no project/queue/job iteration or ordering logic
|
|
# remains in the loop itself." Does NOT #include sched_election.c (that
|
|
# file's external dependency surface is why test_picker_wiring.c's own
|
|
# header comment already ruled out driving sched_job_picker() directly) --
|
|
# instead it reads sched_election.c's real on-disk text at test run time and
|
|
# mechanically checks sched_job_picker()'s body for required picker-
|
|
# interface call sites and absent direct-traversal symbols.
|
|
# XCE_SCHED_ELECTION_C_PATH bakes in the absolute path via
|
|
# 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)
|
|
|
|
# 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).
|
|
# Callers never calloc(sizeof(xce_pendreason_t)) directly." Same genre as
|
|
# sched_picker_core_loop_boundary_test above (reads real on-disk source at
|
|
# test run time rather than linking the huge dependency surface a live
|
|
# scheduler pulls in), but scans every non-testsuite .c/.h file under
|
|
# 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)
|
|
|
|
# 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
|
|
# the networking/API libraries ... a build-time or link-time check
|
|
# confirms this." Same source-text-scan genre as
|
|
# sched_picker_core_loop_boundary_test / sched_pendreason_factory_audit_test
|
|
# above, PLUS a genuine link-time proof: it inspects the undefined-symbol
|
|
# table (via nm(1)) of sched_core_isolation_lib (defined in the parent
|
|
# 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_CORE_LIB_PATH="'
|
|
+ sched_core_isolation_lib.full_path()
|
|
+ '"'],
|
|
install: false)
|
|
|
|
# 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)
|
|
|
|
# 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
|
|
# determinism invariant, not a tuning knob." Same white-box #include
|
|
# pattern as test_picker_config_fields.c (pulls the real
|
|
# xce_sched_core_init()/xce_sched_core_fini() from ../src/core.c into this
|
|
# TU) PLUS the source-text-scan genre used by test_picker_core_loop_boundary_test/
|
|
# test_core_isolation_test above -- a real runtime call proving
|
|
# core.jbuf.ncap == 1, and a scan of core.c's actual on-disk text proving
|
|
# the cbuf_init() capacity argument is the literal 1 (never a variable),
|
|
# that the former `njobs` local is gone, and that the separate/unrelated
|
|
# `ndecisions` FIXME was left untouched. XCE_CORE_C_PATH reuses the same
|
|
# absolute-path constant as sched_core_isolation_test above.
|
|
sched_core_jbuf_capacity_pin_test = executable(
|
|
'sched_core_jbuf_capacity_pin_test',
|
|
['test_core_jbuf_capacity_pin.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps],
|
|
c_args: ['-DXCE_CORE_C_PATH="'
|
|
+ (meson.current_source_dir() / '..' / 'src' / 'core.c')
|
|
+ '"'],
|
|
install: false)
|
|
|
|
# Contract test for the core event interface and batch event push
|
|
# (scheduler-core spec, task 4.3, Req 5 AC 4 / AC 8): xce_core_push_events()
|
|
# fires the resolved picker's corresponding state-change hook exactly once
|
|
# per event, synchronously, before it returns, and rejects with -EBUSY (no
|
|
# event applied) when a session is active. Same white-box #include pattern
|
|
# as test_core_jbuf_capacity_pin.c/test_core_isolation.c (pulls the real
|
|
# ../src/core.c into this TU) -- see the test's own header comment for why
|
|
# it provides its own real sched_resolve_job_picker() rather than
|
|
# #include-ing schedobj.c.
|
|
sched_core_events_test = executable(
|
|
'sched_core_events_test',
|
|
['test_core_events.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps],
|
|
install: false)
|
|
|
|
# Contract test for the session-start signal and decision callback protocol
|
|
# (scheduler-core spec, task 4.4, Req 5 AC 5 / AC 6): xce_core_go() signals
|
|
# the picker thread non-blockingly and rejects reentrant calls with
|
|
# -EINVAL; decisions placed on core->decisions reach the driver-registered
|
|
# on_decision callback once each, in order, followed by the end-of-session
|
|
# NULL marker terminating the drain loop; xce_core_end_session() clears
|
|
# session_active. Same white-box #include pattern as test_core_events.c
|
|
# (pulls ../src/core.c, ../src/core_session.c, and ../src/decision.c into
|
|
# this TU) -- see the test's own header comment for why this file needs no
|
|
# picker-plugin fixture (xce_core_go()/xce_core_end_session() never call
|
|
# sched_resolve_job_picker()).
|
|
sched_core_session_test = executable(
|
|
'sched_core_session_test',
|
|
['test_core_session.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps],
|
|
install: false)
|
|
|
|
# Contract test for clock virtualization and session timing (scheduler-core
|
|
# spec, task 4.5, Req 5 AC 3 / AC 12): xce_core_now()'s two-anchor + speed
|
|
# formula (normal 1/1, simulation frozen 0/1, plus formula tests with other
|
|
# ratios), xce_core_tlog_format()'s tlog
|
|
# integration (frozen virtual time shown instead of info->time's real
|
|
# wall-clock read), and session_start/session_duration_ns tracking across a
|
|
# real xce_core_go()/xce_core_end_session() cycle. Same white-box #include
|
|
# pattern as test_core_session.c (pulls ../src/core.c, ../src/core_session.c,
|
|
# and ../src/decision.c into this TU) PLUS ../src/core_clock.c (this task's
|
|
# new file -- see that file's own header comment for why xce_core_now()/
|
|
# the tlog format function live there, not in core.c).
|
|
sched_core_clock_test = executable(
|
|
'sched_core_clock_test',
|
|
['test_clock.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps],
|
|
install: false)
|
|
|
|
# Core contract test for the full push-events -> start-session ->
|
|
# drain-decisions -> end-session cycle (scheduler-core spec, task 4.6, Req 5
|
|
# AC 1 / AC 2), against a real picker thread + a stand-in allocator (this
|
|
# test's own driver thread) driving a minimal stub picker plugin through
|
|
# xce_core_push_events()/xce_core_go()/xce_core_end_session() end to end --
|
|
# also proving, mid-cycle against a GENUINELY active session, both the
|
|
# reentrant xce_core_go() rejection (Req 5 AC 5) and the xce_core_push_events()
|
|
# -EBUSY rejection (Req 5 AC 8) compose correctly with the rest of the
|
|
# cycle. Same white-box #include pattern as test_core_events.c/
|
|
# test_core_session.c (pulls ../src/core.c, ../src/core_events.c,
|
|
# ../src/core_session.c, ../src/core_clock.c, and ../src/decision.c into
|
|
# this TU) -- see the test's own header comment for the allocator-thread-
|
|
# vs-direct-jbuf-drain design call.
|
|
sched_core_full_cycle_test = executable(
|
|
'sched_core_full_cycle_test',
|
|
['test_core_full_cycle.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps],
|
|
install: false)
|
|
|
|
# Contract test for the normal-mode driver's controller event translation
|
|
# path (scheduler-core spec, task 5.1, Req 5 AC 8 / AC 9's translation
|
|
# half): xce_sched_driver_translate_pending_events() drains core->pend_updates
|
|
# (the same dataq-swap mechanism handler.c already populates and
|
|
# scheduler.c's sched_update() already drains), translates each dequeued
|
|
# xce_sched_update_request_t into the matching xce_core_event_t for all 10
|
|
# op types, and pushes the batch through a genuine xce_core_push_events()
|
|
# call. Same white-box #include pattern as test_core_events.c (pulls the
|
|
# real ../src/core.c and ../src/core_events.c into this TU) PLUS the new
|
|
# ../src/driver.c under test -- see that test's own header comment for why
|
|
# it provides its own real sched_resolve_job_picker() rather than
|
|
# #include-ing schedobj.c.
|
|
sched_driver_translate_test = executable(
|
|
'sched_driver_translate_test',
|
|
['test_driver_translate.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps],
|
|
install: false)
|
|
|
|
# Regression test for bug-1585's true root cause: a live heap-use-after-free
|
|
# in the RESVALS_FULL/RESVALS_DELTA event-application path (core_events.c),
|
|
# triggered by every second periodic resval report for the same
|
|
# worker+resource on ANY real deployment. Same white-box #include set as
|
|
# sched_driver_translate_test (its sibling), but with a REAL (non-stubbed)
|
|
# kill_sched_resval -- see test_resval_ownership.c's own header comment for
|
|
# why that distinction is exactly what makes this test able to catch the bug
|
|
# sched_driver_translate_test's own no-op stub cannot.
|
|
sched_resval_ownership_test = executable(
|
|
'sched_resval_ownership_test',
|
|
['test_resval_ownership.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps],
|
|
install: false)
|
|
|
|
# Contract test for the normal-mode driver's decision-publish callback
|
|
# (scheduler-core spec, task 5.2, Req 5 AC 6 / AC 9's publishing half):
|
|
# xce_sched_driver_on_decision() forwards DISPATCH/PEND decisions to
|
|
# sched_publish_dispatch()/sched_publish_pend_reason() exactly once each,
|
|
# with the same single-item njobs=1/nreasons=1 wrapping; PREEMPT fails
|
|
# loudly (-ENOSYS, no publish) rather than fabricating a nonexistent
|
|
# xcecli_preempt() call; NULL driver_ctx/decision each return -EINVAL, no
|
|
# publish. Same white-box #include pattern as test_driver_translate.c
|
|
# (pulls ../src/core.c, ../src/core_clock.c, ../src/core_events.c, and the
|
|
# new ../src/driver.c into this TU) PLUS ../src/decision.c for the real
|
|
# make_dispatch_decision()/make_pend_decision()/make_preempt_decision()
|
|
# constructors this file's fixtures use. sched_publish_dispatch()/
|
|
# sched_publish_pend_reason() are SPY test doubles (this file never links
|
|
# scheduler.c), same rationale as test_driver_translate.c's own stubs.
|
|
sched_driver_decision_cb_test = executable(
|
|
'sched_driver_decision_cb_test',
|
|
['test_driver_decision_cb.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps],
|
|
install: false)
|
|
|
|
# Safety-property proof for the begin/end-session ordering seam task 5.2
|
|
# introduced (Req 1 AC 7 / Req 5 AC 9): xce_sched_driver_run_normal_mode_round()
|
|
# (driver.c) must call plugin_begin_session()/sched_account_jobs() strictly
|
|
# AFTER xce_core_begin_session()'s resval reset and strictly BEFORE
|
|
# xce_core_signal_go() wakes the picker thread -- otherwise the picker could
|
|
# observe a session whose resource-in-use accounting was reset to zero but
|
|
# not yet re-summed from running jobs. Drives the REAL
|
|
# xce_sched_driver_run_normal_mode_round() (white-box #include of
|
|
# ../src/driver.c, same TU as test_driver_translate.c/
|
|
# test_driver_decision_cb.c, PLUS ../src/core_session.c for the real
|
|
# xce_core_begin_session()/xce_core_signal_go()/xce_core_end_session()
|
|
# under test) against a real picker pthread (same design as
|
|
# test_core_full_cycle.c's test_picker_thread_fn -- see that file's own
|
|
# header comment for the full "why a real thread, not a sequential drain"
|
|
# rationale: jbuf's hardcoded capacity-1 rendezvous requires one). Uses the
|
|
# REAL plugin_begin_session()/plugin_end_session() (../src/plugin.c) driven
|
|
# through a genuinely test-registered xce_sched_plugin_t whose
|
|
# begin_session_fn/end_session_fn set/check an ordering flag -- per this
|
|
# task's own suggested technique, this is a stronger proof than spying on
|
|
# plugin_begin_session() itself. sched_account_jobs() (scheduler.c, defined
|
|
# on xce_sched_core_t* as of scheduler-sim-decision-parity task 1.1, pulls
|
|
# in resource.c's sched_charge_account()) is instead a SPY test double
|
|
# recording an order index -- this test's target is the DRIVER's ordering
|
|
# discipline, not sched_account_jobs()'s own resource-accounting
|
|
# correctness (out of this task's scope, same "spy the collaborator"
|
|
# rationale test_driver_decision_cb.c/test_driver_translate.c already
|
|
# established for the xce_scheduler_t*-coupled
|
|
# sched_publish_dispatch()/sched_publish_pend_reason()).
|
|
sched_driver_session_ordering_test = executable(
|
|
'sched_driver_session_ordering_test',
|
|
['test_driver_session_ordering.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps],
|
|
install: false)
|
|
|
|
# Requirement 1.4 proof for the Core-Level Resource Accounting component
|
|
# (scheduler-sim-decision-parity spec, task 1.1): sched_charge_account()/
|
|
# sched_uncharge_account()/sched_commit_job_alloc() (resource.c, relocated
|
|
# from xce_scheduler_t* to xce_sched_core_t* by this task) produce
|
|
# byte-identical resInUse/sharedInUse output whether `core` came from an
|
|
# xce_scheduler_t (normal-mode driver) or an xce_sched_sim_driver_t
|
|
# (simulation driver, sim.h) -- see test_resource_accounting.c's own file
|
|
# header comment for why sched_account_jobs() itself (scheduler.c) is not
|
|
# also white-box #included here (no existing test in this directory
|
|
# white-box #includes scheduler.c, for the same reason documented there).
|
|
sched_resource_accounting_test = executable(
|
|
'sched_resource_accounting_test',
|
|
['test_resource_accounting.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps],
|
|
install: false)
|
|
|
|
# Cross-core behavioral-equivalence proof for
|
|
# xce_sched_core_save_snapshot()/xce_sched_core_load_snapshot()
|
|
# (scheduler-core spec, task 8.1, Req 5 AC 21 / Req 6 AC 5): save immediately
|
|
# followed by load into a freshly-initialized, completely separate core
|
|
# produces a core whose observable scheduling behavior (next session's
|
|
# decisions, given the same events) is identical to the pre-save core, plus
|
|
# direct unit-level proof of both functions' -EBUSY (mid-session)/-EINVAL
|
|
# (NULL args) guards. Same white-box #include pattern as
|
|
# test_core_full_cycle.c (../src/core.c, ../src/core_clock.c,
|
|
# ../src/core_events.c, ../src/core_session.c, ../src/decision.c) PLUS the
|
|
# three files task 8.1's own 800-line-cap split produced:
|
|
# ../src/snapshot.c, ../src/snapshot_wire.c, ../src/snapshot_load.c. See
|
|
# that test's own header comment for the two-independent-picker-instance
|
|
# design (xce_sched_plugin_t->data-scoped state) that lets this test drive
|
|
# two fully independent xce_sched_core_t instances through the identical
|
|
# session protocol without cross-contaminating a shared global.
|
|
sched_snapshot_save_load_test = executable(
|
|
'sched_snapshot_save_load_test',
|
|
['test_snapshot_save_load.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps],
|
|
install: false)
|
|
|
|
# White-box test for the recording-directory path-validation function
|
|
# (scheduler-core spec, task 9.1, Req 5 AC 10 "Record file path
|
|
# validation"): rejects a recordFile containing a path separator or a ".."
|
|
# segment BEFORE any filesystem access, and confirms containment beneath
|
|
# record_dir via a genuine canonical-path (realpath()) comparison rather
|
|
# than a textual prefix match -- including a symlink-escape case and the
|
|
# "record_dir vs record_dir-evil sibling" prefix-match trap named in this
|
|
# task's own security brief. Same white-box #include pattern as
|
|
# test_job_update.c/test_handlers.c (pulls the real
|
|
# ../src/recording.c into this TU) -- the function under test has no
|
|
# scheduler-struct fixture dependency at all, so this is the simplest
|
|
# white-box test in this directory.
|
|
sched_recording_path_validation_test = executable(
|
|
'sched_recording_path_validation_test',
|
|
['test_recording_path_validation.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps],
|
|
install: false)
|
|
|
|
# Contract test for the record start/stop lifecycle and the driver-loop
|
|
# recording-write hooks (scheduler-core spec, task 9.2, Req 5 AC 10): start
|
|
# writes a decodable ReplayHeader then SnapshotEntry; a full start -> submit
|
|
# event batch -> complete one real session (real picker + stand-in
|
|
# allocator threads, same rendezvous design as
|
|
# sched_driver_session_ordering_test) -> stop cycle produces exactly the
|
|
# expected message stream ending in ReplayEvent{endSession}; recording
|
|
# inactive costs zero file I/O; double-start/stop-when-not-recording fail
|
|
# cleanly; a TOCTOU-style symlink/hard-link swap between path validation
|
|
# and the eventual open() is rejected. Same white-box #include pattern as
|
|
# sched_driver_session_ordering_test (core.c/core_clock.c/core_events.c/
|
|
# core_session.c/driver.c/plugin.c) PLUS ../src/recording.c/
|
|
# recording_events.c/recording_session.c (the code under test) PLUS
|
|
# ../src/snapshot.c/snapshot_wire.c (task 8.1's real
|
|
# xce_sched_core_save_snapshot(), needed by sched_record_start()).
|
|
sched_record_lifecycle_test = executable(
|
|
'sched_record_lifecycle_test',
|
|
['test_record_lifecycle.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps],
|
|
# bug-1843 regression: `-Wl,--wrap=realloc` linker symbol interposition
|
|
# (same technique/idiom as scheduler_decision_publish_retry_test's own
|
|
# xcecli_* wraps above), so
|
|
# test_decision_batch_growth_failure_drops_incomplete_session() can force
|
|
# a REAL, deterministic realloc() failure inside
|
|
# sched_record_session_add_decision()'s own decisions-array growth --
|
|
# this codebase has no other malloc/realloc fault-injection harness, and
|
|
# bug-1843's root cause was exactly this growth-failure path silently
|
|
# dropping decisions instead of aborting the recording. __wrap_realloc()
|
|
# passes through to __real_realloc() for every call except the one this
|
|
# test arms, so the other 12 tests in this same binary are unaffected.
|
|
link_args: ['-Wl,--wrap=realloc'],
|
|
install: false)
|
|
|
|
# Contract test for the scheduler-side OPCode_schedAdmin request handler
|
|
# (scheduler-core spec, task 9.4, Req 5 AC 10): decodes a forwarded
|
|
# SchedAdminRequest, dispatches by action to sched_record_start()/
|
|
# sched_record_stop()/sched_record_status(), and sends back a
|
|
# SchedAdminReply matching requirements.md's field-semantics table.
|
|
# recordStatus is proven synchronous (answered directly on the handler
|
|
# thread, both idle and while genuinely recording); recordStart/recordStop
|
|
# are proven deferred (enqueued, not executed, until a subsequent
|
|
# xce_sched_driver_translate_pending_events() drain actually performs the
|
|
# real sched_record_start()/sched_record_stop() call and sends the reply).
|
|
# Same white-box #include pattern as sched_driver_translate_test
|
|
# (core.c/core_clock.c/core_events.c/driver.c) PLUS ../src/recording.c/
|
|
# recording_events.c/snapshot.c/snapshot_wire.c (real record start/stop/
|
|
# status/write, task 9.1/9.2/9.3) PLUS ../src/handler.c (the code under
|
|
# test). xcecli_reply_schedadmin() is a SPY test double, same pattern
|
|
# sched_driver_decision_cb_test already establishes for
|
|
# sched_publish_dispatch()/sched_publish_pend_reason().
|
|
sched_admin_request_test = executable(
|
|
'sched_admin_request_test',
|
|
['test_admin_request.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps],
|
|
install: false)
|
|
|
|
# Contract test for simulation-mode startup (scheduler-core spec, task 11.1,
|
|
# Req 5 AC 13): opening and validating the replay file (first message must
|
|
# be ReplayHeader, first data message must be SnapshotEntry), locating the
|
|
# most recent SnapshotEntry at or before --sim-start-ts, loading it via the
|
|
# real xce_sched_core_load_snapshot(), and setting the virtual clock's
|
|
# anchors from the loaded snapshot's timestamp, frozen (speed 0/1). Same
|
|
# white-box #include pattern as sched_snapshot_save_load_test (../src/core.c,
|
|
# ../src/core_clock.c, ../src/snapshot.c, ../src/snapshot_wire.c,
|
|
# ../src/snapshot_load.c) PLUS ../src/recording.c (used only to build real
|
|
# `.replay` fixtures via sched_record_start()/sched_record_stop(), not under
|
|
# test here) PLUS the new ../src/sim.c under test. No driver.c/plugin.c/
|
|
# core_events.c/core_session.c/decision.c: this task stops at "ready-to-run"
|
|
# (task 11.2 owns the event loop), so no real scheduling session is ever
|
|
# driven.
|
|
sched_sim_startup_test = executable(
|
|
'sched_sim_startup_test',
|
|
['test_sim_startup.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps],
|
|
install: false)
|
|
|
|
# Contract test for the simulation-mode event loop and virtual clock
|
|
# advancement (scheduler-core spec, task 11.2, Req 5 AC 14/18): the virtual
|
|
# clock jumps to each ReplayEvent's own timestamp, in exact file order
|
|
# (including a same-timestamp pair), at the moment it is queued; each
|
|
# ReplaySession boundary triggers one complete push-events ->
|
|
# start-session -> drain-decisions -> end-session round, in file order
|
|
# across multiple rounds. Same white-box #include pattern as
|
|
# sched_sim_startup_test (core.c, core_clock.c, recording.c, sim.c,
|
|
# snapshot.c/snapshot_wire.c/snapshot_load.c) PLUS core_events.c,
|
|
# core_session.c, decision.c (the real session/decision machinery this
|
|
# task's event loop drives) PLUS plugin.c, plugins/builtin_fcfs.c (task
|
|
# 11.2's own new core.h-scoped picker registration path,
|
|
# plugin_register_core()/builtin_fcfs_new_plugin() -- deliberately NOT
|
|
# schedobj.c, which needs a genuine xce_scheduler_t* this driver has none
|
|
# of, Req 5 AC 17) PLUS the new ../src/sim_loop.c under test.
|
|
sched_sim_event_loop_test = executable(
|
|
'sched_sim_event_loop_test',
|
|
['test_sim_event_loop.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps],
|
|
install: false)
|
|
|
|
# Regression guard for task 11.3's Observable (scheduler-core spec, Req 5 AC
|
|
# 17, "Simulation isolation"): "a build-time 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. Extended by task 11.5 to also cover the new
|
|
# sim_record.c (--sim-output writer) sibling file. Same source-text-scan +
|
|
# nm(1) link-time-proof genre as sched_core_isolation_test above, PLUS a
|
|
# third, narrower structural layer scanning ONLY xce_sched_sim_driver_t's own
|
|
# struct body text for forbidden field types -- see the test's own header
|
|
# comment for why a comment-stripping pass is required first (sim.h's own
|
|
# 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_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_LIB_PATH="'
|
|
+ sched_sim_isolation_lib.full_path()
|
|
+ '"'],
|
|
install: false)
|
|
|
|
# Contract test for decision verification (scheduler-core spec, task 11.4,
|
|
# Req 5 AC 15/18): each core-emitted decision is compared against the
|
|
# corresponding recorded decision at the same logical position when
|
|
# --sim-verify is set, and any mismatch is reported with the exact logical
|
|
# time and decision detail. Unit-level: sim_decision_eq()/sim_log_mismatch()
|
|
# (new ../src/sim_verify.c, task 11.4's sibling file to sim_loop.c) driven
|
|
# directly against hand-built DISPATCH/PEND/PREEMPT decision pairs --
|
|
# including DISPATCH, which sim_loop.c's own real picker thread can never
|
|
# produce live (Req 5 AC 17-adjacent scope boundary: real resource-matching
|
|
# allocation belongs to the not-yet-designed scheduler-allocation spec), so
|
|
# this is the only way to prove that comparator for real. Integration-level:
|
|
# a full sched_sim_driver_run() run against a real QUEUE_UPDATE+JOBS_PUSH
|
|
# fixture feeding the real builtin_fcfs picker to a genuine live PEND
|
|
# decision, --sim-verify both on (self-match reports zero mismatches,
|
|
# altered-copy reports the exact mismatch) and off (no mismatch reported
|
|
# even against an altered fixture) -- mismatch output observed via the same
|
|
# STDOUT_FILENO dup()/dup2() capture technique
|
|
# test_apply_correctness_verification.c's own
|
|
# test_apply_divergent_loud_fence_log_omits_false_peer_hwm_clause
|
|
# establishes for ERROR()'s tlog early-print path. Same white-box #include
|
|
# pattern as sched_sim_event_loop_test (core.c, core_clock.c, core_events.c,
|
|
# core_session.c, decision.c, plugin.c, plugins/builtin_fcfs.c, recording.c,
|
|
# sim.c, sim_loop.c, snapshot.c/snapshot_wire.c/snapshot_load.c) PLUS the
|
|
# new ../src/sim_verify.c under test.
|
|
sched_sim_verify_test = executable(
|
|
'sched_sim_verify_test',
|
|
['test_sim_verify.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps],
|
|
install: false)
|
|
|
|
# Contract test for what-if event-source branching (scheduler-core spec,
|
|
# task 11.5, Req 5 AC 16): running with --sim-alt-events produces decisions
|
|
# driven by the alternate events, not the base file's original events. A
|
|
# baseline run (no --sim-alt-events) proves the base file's own events drive
|
|
# scheduling by default; a --sim-alt-events run against the SAME base file's
|
|
# snapshot proves the alternate file's events drive it instead, and that the
|
|
# base file's own events are never read once --sim-alt-events is set. Same
|
|
# white-box #include pattern as sched_sim_verify_test (core.c, core_clock.c,
|
|
# core_events.c, core_session.c, decision.c, plugin.c, plugins/builtin_fcfs.c,
|
|
# recording.c, sim.c, sim_loop.c, sim_verify.c, snapshot.c/snapshot_wire.c/
|
|
# snapshot_load.c) -- sim_verify.c is required at link time even though this
|
|
# file never sets --sim-verify (sim_loop.c externs its two entry points
|
|
# unconditionally, same reason sched_sim_event_loop_test needs it).
|
|
sched_sim_alt_events_test = executable(
|
|
'sched_sim_alt_events_test',
|
|
['test_sim_alt_events.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps],
|
|
install: false)
|
|
|
|
# Contract test for the --sim-output `.replay` writer (scheduler-core spec,
|
|
# task 11.5, Req 5 AC 19): the output file, when requested, is decodable by
|
|
# the same reader used for normal-mode recordings (test_record_lifecycle.c's
|
|
# own capn_getp(capn_root(&c), 0, 1) + read_X()/decode_X() technique, reused
|
|
# verbatim here), with full ReplayHeader -> SnapshotEntry -> ReplayEvent* ->
|
|
# ReplaySession -> ReplayEvent{endSession} stream symmetry (Req 5 AC 19's own
|
|
# symmetry table). A second test proves --sim-output composes with
|
|
# --sim-alt-events: the output reflects the alternate run's own events and
|
|
# decision, not the base file's. Same white-box #include pattern as
|
|
# sched_sim_verify_test PLUS ../src/recording_session.c (the scheduler_t-free
|
|
# session-accumulator entry points sim_loop.c now calls) PLUS the new
|
|
# ../src/sim_record.c (the code under test).
|
|
sched_sim_record_output_test = executable(
|
|
'sched_sim_record_output_test',
|
|
['test_sim_record_output.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps],
|
|
install: false)
|
|
|
|
# Contract test for deterministic replay and normal-to-simulation
|
|
# equivalence (scheduler-core spec, task 11.6, Req 5 AC 7.1) -- the spec's
|
|
# own central regression test: a synthetic scheduling session recorded
|
|
# through the REAL normal-mode driver (real builtin_fcfs picker + a
|
|
# stand-in allocator producing real PEND decisions via the same
|
|
# make_pend_decision()/make_pendreason() production constructors) is
|
|
# replayed through the REAL, unmodified simulation driver, and the two
|
|
# resulting `.replay` files' ReplaySession.decisions lists are asserted to
|
|
# match identically (same jobid, same pend reason content, per decision),
|
|
# while never comparing ReplayHeader or SessionSummary fields (AC 7.1's own
|
|
# "only non-decision metadata may differ" carve-out). First test file in
|
|
# this directory to combine BOTH the normal-mode driver stack and the full
|
|
# simulation stack in one TU -- see the test's own header comment for the
|
|
# combined white-box #include set (test_record_lifecycle.c's own set union
|
|
# test_sim_record_output.c's own set), the full stub surface, and why every
|
|
# decision in this fixture is PEND rather than a DISPATCH/PEND mix
|
|
# (sim_loop.c's sim_picker_thread_fn() can never emit a live DISPATCH today
|
|
# -- a documented, out-of-this-task's-scope gap, not a weakening of this
|
|
# test).
|
|
sched_sim_equivalence_test = executable(
|
|
'sched_sim_equivalence_test',
|
|
['test_sim_equivalence.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps],
|
|
install: false)
|
|
|
|
# Round-boundary ordering contract for the simulation driver
|
|
# (scheduler-sim-decision-parity spec, task 2.1, Req 1.3/1.4, 5.1, 5.3): the
|
|
# sim-mode counterpart to sched_driver_session_ordering_test above -- proves
|
|
# sim_loop.c's sched_sim_driver_run() now calls the relocated
|
|
# sched_account_jobs() (core.h, task 1.1) once per replayed round, strictly
|
|
# inside that round's session-active window, mirroring driver.c's
|
|
# xce_sched_driver_run_normal_mode_round() exactly. Before this task,
|
|
# sim_loop.c called the older monolithic xce_core_go() with no interleaving
|
|
# slot and never called sched_account_jobs() at all (bug-1613) -- every
|
|
# worker's/shared resource's resInUse stayed permanently zero for the whole
|
|
# `--sim`/`--interactive` run. Same combined white-box #include set as
|
|
# sched_sim_equivalence_test (records two real normal-mode rounds via the
|
|
# REAL normal-mode driver, then replays the same file through the REAL,
|
|
# unmodified simulation driver) -- see the test's own header comment for why
|
|
# a spy sched_account_jobs() (not the real one) is the right-strength proof
|
|
# here, and why no cross-thread wbuf-rendezvous replica of
|
|
# test_driver_session_ordering.c's own design is attempted (sim_loop.c's
|
|
# picker thread is not independently substitutable from a test without
|
|
# touching sim_picker.c, outside this task's boundary).
|
|
sched_sim_session_ordering_test = executable(
|
|
'sched_sim_session_ordering_test',
|
|
['test_sim_session_ordering.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps],
|
|
install: false)
|
|
|
|
# Recorded-Decision Reconciliation trigger/lookup/not-found contract
|
|
# (scheduler-sim-decision-parity spec, task 2.2, Req 4.1/4.2, "Recorded-
|
|
# Decision Reconciliation" component). Calls the new sim_loop.c-local
|
|
# sim_reconcile_unaccounted_jobs() directly (it is `static` and not yet
|
|
# wired into any call site -- task 3's job) against hand-built
|
|
# xce_sched_core_t/replay_session_t fixtures (core_build_job()+
|
|
# sched_add_job(), no `.replay` file or capnp round-trip needed). Same
|
|
# white-box #include/stub set as sched_sim_event_loop_test -- sim_loop.c's
|
|
# compiled TU unconditionally references every one of those externs
|
|
# regardless of which functions this file's own tests call.
|
|
sched_sim_reconcile_unaccounted_test = executable(
|
|
'sched_sim_reconcile_unaccounted_test',
|
|
['test_sim_reconcile_unaccounted.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps],
|
|
install: false)
|
|
|
|
# Resource-contention replay fixture (scheduler-sim-decision-parity spec,
|
|
# task 1.2, Req 2.1/2.2): existing fixtures in this directory never have
|
|
# scarce capacity, so none can exercise or prove capacity-check correctness.
|
|
# This file records ONE real normal-mode session (real builtin_fcfs picker +
|
|
# a capacity-aware stand-in allocator that drives the REAL
|
|
# sched_check_host_satisfy()/sched_charge_account()/sched_commit_job_alloc()
|
|
# (resource.c) against a real, finite-capacity worker) where three jobs
|
|
# compete for 10.0 units of one resource -- two dispatch, one is genuinely
|
|
# denied capacity the other two, now running, are consuming. First file in
|
|
# this directory to combine resource.c with the full driver/sim/recording
|
|
# stack (test_resource_accounting.c, task 1.1, deliberately pairs resource.c
|
|
# with only core.c -- see that file's own header comment for why). The
|
|
# resulting `.replay` file is dual-use: it IS a genuine normal-mode
|
|
# recording, and this file's own second test proves it is also directly
|
|
# replayable via the real, unmodified simulation driver -- see this file's
|
|
# own header comment for the full rationale.
|
|
sched_sim_resource_contention_test = executable(
|
|
'sched_sim_resource_contention_test',
|
|
['test_sim_resource_contention.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps],
|
|
install: false)
|
|
|
|
# End-to-end integration proof for task 3 (Req 1.3/1.4, 2.1/2.2, 5.2): wires
|
|
# Recorded-Decision Reconciliation (tasks 2.2-2.4) into sim_loop.c's real
|
|
# round-boundary sequence, before sched_account_jobs()/xce_core_signal_go().
|
|
# Unlike every other sim_loop.c-including file in this directory, this one
|
|
# links a REAL (not no-op) sched_account_jobs() reimplementation (copied
|
|
# verbatim from scheduler.c) plus resource.c, so it can prove the actual
|
|
# resInUse/capacity-check outcome of the wired call site against the real,
|
|
# unmodified sched_sim_driver_run() -- not just that reconciliation runs in
|
|
# isolation (test_sim_reconcile_unaccounted.c) or that sched_account_jobs()
|
|
# is called at the right point (test_sim_session_ordering.c, via a spy).
|
|
# See this file's own header comment for the full scenario and rationale.
|
|
sched_sim_round_boundary_reconciliation_test = executable(
|
|
'sched_sim_round_boundary_reconciliation_test',
|
|
['test_sim_round_boundary_reconciliation.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps],
|
|
install: false)
|
|
|
|
# Regression coverage for task 4.2 (Req 4.1, 4.2): a replay starting from a
|
|
# SNAPSHOT that already has a job in RUN state, with no recorded decision
|
|
# for it anywhere in this replay's own window, must degrade gracefully --
|
|
# job->accounts/allocs stay NULL (unavailable, never fabricated), the run
|
|
# completes cleanly (rc == 0, no --sim-verify mismatch), and a second,
|
|
# ordinary job elsewhere in the same replay is still decided normally. A
|
|
# different trigger shape from sched_sim_verify_test's own already-resolved-
|
|
# job case (that job transitions RUN mid-replay via a JOB_STATE_CHANGE
|
|
# event WITH a matching recorded DISPATCH in the same round -- reconciled,
|
|
# not left unavailable): this file's job is already RUN in the INITIAL
|
|
# SNAPSHOT itself, with no recorded decision anywhere in-window to
|
|
# reconcile from at all, so sim_reconcile_unaccounted_jobs()'s "not found"
|
|
# branch (task 2.2) is the only path that can ever touch it -- see this
|
|
# file's own header comment for the full scenario and rationale.
|
|
sched_sim_snapshot_reconcile_gap_test = executable(
|
|
'sched_sim_snapshot_reconcile_gap_test',
|
|
['test_sim_snapshot_reconcile_gap.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps],
|
|
install: false)
|
|
|
|
# Record-then-replay-and-diff parity proof for task 4.1 (Req 1.4, 2.1, 2.2):
|
|
# extends task 1.2's resource-contention scenario (worker capacity 10.0,
|
|
# jobs wanting 8.0/5.0/2.0) to an actual round-by-round comparison between a
|
|
# REAL, driven normal-mode recording (this file's own Part A: real
|
|
# builtin_fcfs picker + a capacity-aware allocator, same technique as
|
|
# sched_sim_resource_contention_test, extended across TWO real rounds) and
|
|
# a hand-crafted simulation-mode `.replay` fixture (Part B: same
|
|
# JOB_STATE_CHANGE-precedes-matching-DISPATCH-decision reconciliation
|
|
# trigger sched_sim_round_boundary_reconciliation_test establishes,
|
|
# extended to BOTH jobs A and C together). Links a REAL (not no-op)
|
|
# sched_account_jobs() reimplementation, augmented with a round-boundary
|
|
# resInUse snapshot side effect, giving genuine per-round observability
|
|
# into simulation mode's own accounting -- not just the final state. See
|
|
# this file's own header comment for the full two-fixture design and why a
|
|
# straight replay of task 1.2's own recorded file (unmodified) cannot prove
|
|
# this by itself.
|
|
sched_sim_contention_parity_test = executable(
|
|
'sched_sim_contention_parity_test',
|
|
['test_sim_contention_parity.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps],
|
|
install: false)
|
|
|
|
# Live-verify for task 4.3 (Req 1.1-1.3, 3.1-3.3, FINAL task of this spec): a
|
|
# real, driven 24-round, 12-job, resource-constrained recording (real
|
|
# builtin_fcfs picker + a capacity-aware allocator, same technique as
|
|
# sched_sim_resource_contention_test/sched_sim_contention_parity_test, but
|
|
# extended far past a 1-2-round toy fixture) is replayed through the real,
|
|
# unmodified interactive REPL. Asserts "info worker" reports the
|
|
# arithmetically-correct, nonzero used= value at four checkpoints spanning
|
|
# the whole replay, and that the one job modeling "already resolved before
|
|
# this replay's own live decision-making reaches it" (Recorded-Decision
|
|
# Reconciliation's own designed trigger, unreachable from a purely organic
|
|
# session per this file's own header comment) has its DISPATCH decision
|
|
# visible in step/continue output -- bug-1611's own documented symptom,
|
|
# fixed. Substitutes for the original bug-1611/bug-1613 motivating
|
|
# recording (`scheduler-replay-20260820-070103.replay`), confirmed absent
|
|
# from this filesystem before this file was written -- see this file's own
|
|
# header comment for the full transparency note.
|
|
sched_sim_e2e_original_motivation_test = executable(
|
|
'sched_sim_e2e_original_motivation_test',
|
|
['test_sim_e2e_original_motivation.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps],
|
|
install: false)
|
|
|
|
# Contract test for the interactive simulation REPL's execution-control slice
|
|
# (scheduler-core spec, task 12.1, Req 5 AC 22): starting simulation with
|
|
# --interactive pauses before any event is processed, and a `step N` command
|
|
# advances exactly N sessions before returning control to the prompt. Same
|
|
# white-box #include pattern as sched_sim_alt_events_test/sched_sim_verify_test
|
|
# (core.c, core_clock.c, core_events.c, core_session.c, decision.c, plugin.c,
|
|
# plugins/builtin_fcfs.c, recording.c, recording_session.c, sim.c, sim_loop.c,
|
|
# sim_record.c, sim_verify.c, snapshot.c/snapshot_wire.c/snapshot_load.c) PLUS
|
|
# ../src/repl.c under test. Also pulls in ../src/repl_break.c/repl_info.c
|
|
# (task 12.2's 800-line-cap split of repl.c -- repl_internal.h's own "Why a
|
|
# split at all") -- required at link time since sim_loop.c's new breakpoint
|
|
# hooks (repl.h) reference symbols repl_break.c defines, even though this
|
|
# file's own tests exercise only the execution-control slice; task 12.2's
|
|
# own breakpoint/inspection tests live in the sibling
|
|
# test_repl_breakpoints_inspection.c. Needs libedit_dep (parent meson.build)
|
|
# at link time -- repl.c's real readline()/add_history() calls are pulled
|
|
# into this TU by the white-box #include.
|
|
sched_repl_execution_control_test = executable(
|
|
'sched_repl_execution_control_test',
|
|
['test_repl_execution_control.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps, libedit_dep],
|
|
install: false)
|
|
|
|
# Contract test for the interactive simulation REPL's Round Rollup
|
|
# component (scheduler-sim-repl-verbosity spec, task 2.1, Requirements 2
|
|
# and 3 "per-round decision summary"/"collapsing repetitive rounds"): a
|
|
# round with at least one decision produces a summary naming decision
|
|
# counts and affected jobids; idle or identical-outcome consecutive rounds
|
|
# collapse into a single range notification; and the shared
|
|
# repl_round_collapse_flush() entry point is exercised directly (a safe
|
|
# no-op when nothing is active) and indirectly (flushed before a structural
|
|
# event/replay-complete banner). Same white-box #include pattern as
|
|
# sched_repl_execution_control_test above (core.c, core_clock.c,
|
|
# core_events.c, core_session.c, decision.c, plugin.c,
|
|
# plugins/builtin_fcfs.c, recording.c, recording_session.c, sim.c,
|
|
# sim_loop.c, sim_record.c, sim_verify.c,
|
|
# snapshot.c/snapshot_wire.c/snapshot_load.c, repl.c, repl_break.c,
|
|
# repl_info.c, repl_params.c). Split into its own file rather than appended
|
|
# to test_repl_execution_control.c -- that file was already 936 lines
|
|
# (pre-existing, over this project's 800-line cap on its own), and this
|
|
# task's own tests (seven forked-child, real-stdout-capture fixtures plus
|
|
# their own fork/capture helper pair) would have pushed it to 1563 lines,
|
|
# past the ~1000-line threshold this exact spec family already treats as a
|
|
# split trigger (see sched_repl_snapshot_params_test's own comment below
|
|
# for the precedent). See design.md's "**Correction (post-review, task
|
|
# 2.1)**" note.
|
|
sched_repl_round_rollup_test = executable(
|
|
'sched_repl_round_rollup_test',
|
|
['test_repl_round_rollup.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps, libedit_dep],
|
|
install: false)
|
|
|
|
# Contract test for the interactive simulation REPL's Event Echo Gate
|
|
# component (scheduler-sim-repl-verbosity spec, task 3.1, Requirements 1 and
|
|
# 3.5/3.6 "mode-aware event echo"/"ending an active collapsed range"): a
|
|
# routine per-tick event (e.g. QUEUE_UPDATE) produces no line under
|
|
# continue-mode execution but still prints while single-stepping; a
|
|
# structural event (e.g. WORKERS_PUSH) still prints under continue and
|
|
# flushes any active Round Rollup collapsed range first; a breakpoint hit
|
|
# still interrupts continue-mode execution regardless of the matched
|
|
# event's classification, and likewise flushes any active collapsed range
|
|
# before the interruption is shown. Same white-box #include pattern as
|
|
# sched_repl_round_rollup_test above (core.c, core_clock.c, core_events.c,
|
|
# core_session.c, decision.c, plugin.c, plugins/builtin_fcfs.c, recording.c,
|
|
# recording_session.c, sim.c, sim_loop.c, sim_record.c, sim_verify.c,
|
|
# snapshot.c/snapshot_wire.c/snapshot_load.c, repl.c, repl_rollup.c,
|
|
# repl_break.c, repl_info.c, repl_params.c). Split into its own file rather
|
|
# than appended to test_repl_execution_control.c -- that file was already
|
|
# 937 lines (pre-existing, over this project's 800-line cap) before this
|
|
# feature began, and this task's own four behavioral cases would have
|
|
# pushed it well past 1300 lines, the same reasoning that already split
|
|
# test_repl_round_rollup.c out (task 2.1) -- see design.md's own
|
|
# "**Correction (post-review, task 3.1)**" note.
|
|
sched_repl_event_echo_test = executable(
|
|
'sched_repl_event_echo_test',
|
|
['test_repl_event_echo.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps, libedit_dep],
|
|
install: false)
|
|
|
|
# Contract test for the interactive simulation REPL's Event Echo Preamble
|
|
# Deduplicator component (scheduler-sim-step-verbosity spec, task 1.1,
|
|
# Requirements 1 and 2 "collapse the repeated timestamp/session preamble
|
|
# across consecutive same-context echoed events"): two consecutive echoed
|
|
# events sharing the same rendered (second-granularity) timestamp and
|
|
# displayed session omit the second's preamble line while still printing
|
|
# its own content line; events spanning a session boundary each print their
|
|
# own full preamble; two events whose raw high-resolution timestamps differ
|
|
# but whose rendered timestamp and session are identical still dedupe (the
|
|
# design's central "rendered value, not raw ns" nuance); the first echoed
|
|
# event of a fresh REPL session always prints its preamble; the same rule
|
|
# applies to a structural event echoed under `continue` mode after a
|
|
# stretch of suppressed routine events; and event content/ordering stay
|
|
# unaffected by the preamble decision at N=3 consecutive same-context
|
|
# events. THIS TASK (1.1) IS RED-PHASE ONLY -- see this file's own header
|
|
# comment. Same white-box #include pattern and forked-child/real-stdout-
|
|
# capture technique as sched_repl_event_echo_test above (core.c,
|
|
# core_clock.c, core_events.c, core_session.c, decision.c, plugin.c,
|
|
# plugins/builtin_fcfs.c, recording.c, recording_session.c, sim.c,
|
|
# sim_loop.c, sim_record.c, sim_verify.c,
|
|
# snapshot.c/snapshot_wire.c/snapshot_load.c, repl.c, repl_fmt.c,
|
|
# repl_rollup.c, repl_break.c, repl_info.c, repl_params.c). Split into its
|
|
# own file from the start rather than appended to test_repl_event_echo.c
|
|
# (705 lines before this feature) -- design.md's File Structure Plan flags
|
|
# this file's ~1000-line split trigger, and this task's six behavioral
|
|
# cases plus their own preamble-construction helper would have pushed it
|
|
# well past that threshold; the same reasoning that already split
|
|
# test_repl_round_rollup.c/test_repl_event_echo.c/test_repl_prompt_context.c/
|
|
# test_sim_print_decision_gate.c out of test_repl_execution_control.c.
|
|
sched_repl_step_verbosity_test = executable(
|
|
'sched_repl_step_verbosity_test',
|
|
['test_repl_step_verbosity.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps, libedit_dep],
|
|
install: false)
|
|
|
|
# Contract test for the interactive simulation REPL's Prompt Context
|
|
# component (scheduler-sim-repl-verbosity spec, task 6.1, Requirement 5.5
|
|
# "REPL prompt shows session/timestamp"): the readline() prompt is the
|
|
# plain "(sim) " before any session has completed, and becomes "(sim
|
|
# session=<N> t=<ISO8601-ts>) " (bare rs->session_count) once at least one
|
|
# session has run, in both `step` and `continue` modes, without altering
|
|
# any command's own printed output. Same white-box #include pattern as
|
|
# sched_repl_execution_control_test above (core.c, core_clock.c,
|
|
# core_events.c, core_session.c, decision.c, plugin.c,
|
|
# plugins/builtin_fcfs.c, recording.c, recording_session.c, sim.c,
|
|
# sim_loop.c, sim_record.c, sim_verify.c,
|
|
# snapshot.c/snapshot_wire.c/snapshot_load.c, repl.c, repl_rollup.c,
|
|
# repl_break.c, repl_info.c, repl_params.c). Split into its own file rather
|
|
# than appended to test_repl_execution_control.c (948 lines today, already
|
|
# over this project's 800-line cap and grown past the 937-line figure
|
|
# design.md's own File Structure Plan cited when it named that file as this
|
|
# task's home) -- same reasoning that already split test_repl_round_
|
|
# rollup.c/test_repl_event_echo.c out; see this file's own header comment
|
|
# for the full rationale, including why a pty (openpty(), <pty.h>) is
|
|
# required instead of this file family's usual freopen()-from-a-file
|
|
# capture technique to make readline()'s prompt text observable at all.
|
|
sched_repl_prompt_context_test = executable(
|
|
'sched_repl_prompt_context_test',
|
|
['test_repl_prompt_context.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps, libedit_dep],
|
|
install: false)
|
|
|
|
# Contract test for the interactive simulation REPL's `sim_print_decision`
|
|
# Gate component (scheduler-sim-repl-verbosity spec, task 4.1, Requirements
|
|
# 2.3, 5.1, 5.4 "retire the redundant per-decision echo during continuous
|
|
# execution"): under `continue` mode, sim_print_decision()'s (sim_loop.c)
|
|
# bare per-decision line must no longer appear outside the Round Rollup's
|
|
# own per-round summary; `step` mode and non-interactive (headless, no -i)
|
|
# batch runs are completely unaffected and keep printing that bare line
|
|
# exactly as today. Same white-box #include pattern as
|
|
# sched_repl_round_rollup_test/sched_repl_event_echo_test above (core.c,
|
|
# core_clock.c, core_events.c, core_session.c, decision.c, plugin.c,
|
|
# plugins/builtin_fcfs.c, recording.c, recording_session.c, sim.c,
|
|
# sim_loop.c, sim_record.c, sim_verify.c,
|
|
# snapshot.c/snapshot_wire.c/snapshot_load.c, repl.c, repl_rollup.c,
|
|
# repl_break.c, repl_info.c, repl_params.c). Split into its own file rather
|
|
# than extended onto either sibling: test_repl_round_rollup.c is already
|
|
# 1022 lines (222 over this project's 800-line cap) on its own, and
|
|
# test_repl_event_echo.c (704 lines) deliberately keeps every one of its
|
|
# own fixtures job-free (bug-1595 jobid-reuse safety discipline), which
|
|
# this task's decision-producing fixtures cannot follow -- see this file's
|
|
# own header comment for the full rationale.
|
|
sched_sim_print_decision_gate_test = executable(
|
|
'sched_sim_print_decision_gate_test',
|
|
['test_sim_print_decision_gate.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps, libedit_dep],
|
|
install: false)
|
|
|
|
# Contract test for the interactive simulation REPL's breakpoint and
|
|
# state-inspection slice (scheduler-core spec, task 12.2, Req 5 AC 22
|
|
# "Breakpoints"/"State inspection"): setting a breakpoint on a specific
|
|
# event type and field value pauses the REPL exactly when a matching event
|
|
# is about to be processed, and each `info` command reports state matching
|
|
# a snapshot dump of the same moment. Same white-box #include pattern as
|
|
# sched_repl_execution_control_test above (core.c, core_clock.c,
|
|
# core_events.c, core_session.c, decision.c, plugin.c,
|
|
# plugins/builtin_fcfs.c, recording.c, recording_session.c, sim.c,
|
|
# sim_loop.c, sim_record.c, sim_verify.c,
|
|
# snapshot.c/snapshot_wire.c/snapshot_load.c, repl.c, repl_break.c,
|
|
# repl_info.c). Split into its own file rather than appended to
|
|
# test_repl_execution_control.c -- that file was already 644 lines after
|
|
# task 12.1, and this task's own fixture/assertion surface (breakpoints on
|
|
# multiple event kinds plus five separate `info` dumps) does not fit
|
|
# alongside it under this project's 800-line cap.
|
|
sched_repl_breakpoints_inspection_test = executable(
|
|
'sched_repl_breakpoints_inspection_test',
|
|
['test_repl_breakpoints_inspection.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps, libedit_dep],
|
|
install: false)
|
|
|
|
# Contract test for the interactive simulation REPL's Resource Value
|
|
# Formatter table/grouping layout, units-mode rendering, and the Jobid
|
|
# Range Compressor's adoption in `info worker`'s assigned-job listing
|
|
# (scheduler-sim-repl-verbosity spec, task 8.1, Requirements 6.4, 6.5, 6.6,
|
|
# 4.5). Same white-box #include pattern as
|
|
# sched_repl_breakpoints_inspection_test above (core.c, core_clock.c,
|
|
# core_events.c, core_session.c, decision.c, plugin.c,
|
|
# plugins/builtin_fcfs.c, recording.c, recording_session.c, sim.c,
|
|
# sim_loop.c, sim_record.c, sim_verify.c,
|
|
# snapshot.c/snapshot_wire.c/snapshot_load.c, repl.c, repl_fmt.c,
|
|
# repl_rollup.c, repl_break.c, repl_info.c, repl_params.c). Split into its
|
|
# own file rather than appended to test_repl_breakpoints_inspection.c --
|
|
# landing these ten tests there per design.md's own File Structure Plan
|
|
# pushed that file from 2095 to 3215 lines, well past the ~1000-line split
|
|
# trigger this exact file family already established (the same reasoning
|
|
# that already split test_repl_round_rollup.c/test_repl_event_echo.c out;
|
|
# see this file's own header comment for the full rationale).
|
|
sched_repl_resource_table_test = executable(
|
|
'sched_repl_resource_table_test',
|
|
['test_repl_resource_table.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps, libedit_dep],
|
|
install: false)
|
|
|
|
# Contract test for the interactive simulation REPL's `info limit <name|all>`
|
|
# name/all resolution and absence messaging (scheduler-sim-diagnostics spec,
|
|
# Requirement Set 1, task 2.1, Requirements 1.3, 1.7, 4.1, 4.2). Split into
|
|
# its own file rather than added to test_repl_resource_table.c, per
|
|
# design.md's own explicit build-wiring risk note: that file's white-box
|
|
# #include set deliberately does NOT link plugins/limit.c or resource.c
|
|
# ("resource.c, not linked here"), and this task needs the REAL
|
|
# plugins/limit.c (for the real limit_get_configured_limits()/limit_init()/
|
|
# limit_update_config() its own fixtures and repl_info_limit() call) --
|
|
# not stubbed, the same bug-1762 precedent design.md cites for a different
|
|
# scheduler-sim-repl-verbosity command that hit the identical undefined-
|
|
# reference link-failure class. Same white-box #include pattern as
|
|
# sched_repl_resource_table_test above (core.c, core_clock.c, core_events.c,
|
|
# core_session.c, decision.c, plugin.c, plugins/builtin_fcfs.c, recording.c,
|
|
# recording_session.c, sim.c, sim_loop.c, sim_picker.c, sim_record.c,
|
|
# sim_verify.c, snapshot.c/snapshot_wire.c/snapshot_load.c, repl.c,
|
|
# repl_fmt.c, repl_rollup.c, repl_break.c, repl_info.c, repl_params.c) PLUS
|
|
# the new ../src/plugins/limit.c under test. task 2.1's own scope never
|
|
# reads live usage/resource accounting (that's task 3), so resource.c is
|
|
# NOT linked here -- the same minimal link-satisfying stubs
|
|
# test_limit_plugin.c already establishes for limit.c's unused
|
|
# limit_job_election()/limit_prepare_allocation() hook bodies
|
|
# (reset_sched_obj()/get_resvals()/put_resvals()) are reused verbatim,
|
|
# confirmed sufficient by actually attempting the build and reading the
|
|
# resulting undefined-reference errors rather than guessing blindly.
|
|
# `repl_info_limit()` is not yet wired into repl_cmd_info() (task 4) -- every
|
|
# test in this file calls it directly, not through repl_dispatch().
|
|
sched_repl_limit_table_test = executable(
|
|
'sched_repl_limit_table_test',
|
|
['test_repl_limit_table.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps, libedit_dep],
|
|
install: false)
|
|
|
|
# Contract test for the interactive simulation REPL's Help & Breakpoint
|
|
# Discoverability component (scheduler-sim-repl-verbosity spec, task 9.1,
|
|
# Requirements 7.1-7.4): `help`'s listing groups commands into four labeled
|
|
# sections in a fixed order, aligns every command's description to one
|
|
# consistent column position throughout, lists `info config` together with
|
|
# its `info` siblings in the state-inspection section, lists `set units`
|
|
# alongside `set output`/`set verify` in the snapshot-and-parameters
|
|
# section (`set speed` was removed, scheduler-sim-discrete-clock), and
|
|
# enumerates the complete BP_KIND_TABLE event-type set on the `break` line. Same white-box #include pattern as
|
|
# sched_repl_resource_table_test above (core.c, core_clock.c, core_events.c,
|
|
# core_session.c, decision.c, plugin.c, plugins/builtin_fcfs.c, recording.c,
|
|
# recording_session.c, sim.c, sim_loop.c, sim_record.c, sim_verify.c,
|
|
# snapshot.c/snapshot_wire.c/snapshot_load.c, repl.c, repl_fmt.c,
|
|
# repl_rollup.c, repl_break.c, repl_info.c, repl_params.c) even though this
|
|
# file's own tests call only repl_print_help() directly -- no
|
|
# xce_sched_sim_driver_t/replay fixture needed. Split into its own file
|
|
# rather than appended to test_repl_execution_control.c -- that file was
|
|
# already 949 lines (pre-existing, over this project's 800-line cap) before
|
|
# this task began; landing this task's own section/column/discoverability
|
|
# tests there would have pushed it well past the ~1000-line split trigger
|
|
# this exact file family already established (the same reasoning that split
|
|
# test_repl_round_rollup.c/test_repl_event_echo.c/test_repl_resource_table.c
|
|
# out of their own siblings). `break`'s own unrecognized-event-type error
|
|
# message test (Requirement 7.5) lives in
|
|
# test_repl_breakpoints_inspection.c instead, per design.md's own file-
|
|
# placement guidance for this component.
|
|
sched_repl_help_test = executable(
|
|
'sched_repl_help_test',
|
|
['test_repl_help.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps, libedit_dep],
|
|
install: false)
|
|
|
|
# Contract test for the interactive simulation REPL's snapshot-capture and
|
|
# simulation-parameter command slice (scheduler-core spec, task 12.3, Req 5
|
|
# AC 22 "Snapshots"/"Simulation parameters"): `snapshot [FILE]` writes a
|
|
# standalone .replay file a FRESH sched_sim_driver_start() can load, landing
|
|
# on the exact position the snapshot was taken at (the task's own central
|
|
# Observable, proved end to end via a forked child + a second, real
|
|
# sched_sim_driver_start() call in the parent); `set output`/`set verify`
|
|
# mutate the parameters `info config` reports, and the removed `set speed`
|
|
# prints a removal message and changes nothing. Same white-box
|
|
# #include pattern as sched_repl_breakpoints_inspection_test above (core.c,
|
|
# core_clock.c, core_events.c, core_session.c, decision.c, plugin.c,
|
|
# plugins/builtin_fcfs.c, recording.c, recording_session.c, sim.c,
|
|
# sim_loop.c, sim_record.c, sim_verify.c,
|
|
# snapshot.c/snapshot_wire.c/snapshot_load.c, repl.c, repl_break.c,
|
|
# repl_info.c) PLUS the new ../src/repl_params.c under test. Split into its
|
|
# own file rather than appended to test_repl_breakpoints_inspection.c --
|
|
# that file was already over 1000 lines after task 12.2, and this task's
|
|
# own fixture/assertion surface (a fork+reload round-trip plus five
|
|
# further unit-level command tests) does not belong crammed into it.
|
|
sched_repl_snapshot_params_test = executable(
|
|
'sched_repl_snapshot_params_test',
|
|
['test_repl_snapshot_params.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps, libedit_dep],
|
|
install: false)
|
|
|
|
# Contract test for REPL step/continue-to-completion vs batch simulation
|
|
# equivalence (scheduler-core spec, task 12.4, Req 5 AC 22 "Deterministic
|
|
# replay is preserved"): running a fixture through the REPL via a scripted
|
|
# `step`/`continue` command sequence to completion must produce the SAME
|
|
# decision sequence as running the identical fixture through batch
|
|
# (non-interactive) simulation mode. Unlike task 11.6's
|
|
# test_sim_equivalence.c (which compares the NORMAL-mode driver against the
|
|
# SIMULATION driver), this compares the SAME sched_sim_driver_run() against
|
|
# itself, differing only in `sim->interactive` -- proving the REPL only
|
|
# controls WHEN events are processed, never WHAT. Same white-box #include
|
|
# pattern as sched_repl_execution_control_test (core.c, core_clock.c,
|
|
# core_events.c, core_session.c, decision.c, plugin.c,
|
|
# plugins/builtin_fcfs.c, recording.c, recording_session.c, sim.c,
|
|
# sim_loop.c, sim_record.c, sim_verify.c,
|
|
# snapshot.c/snapshot_wire.c/snapshot_load.c, repl.c, repl_break.c,
|
|
# repl_info.c, repl_params.c) -- no driver.c: both runs are pure
|
|
# simulation-driver replays of one hand-built fixture, never a real
|
|
# normal-mode recording session.
|
|
sched_repl_equivalence_test = executable(
|
|
'sched_repl_equivalence_test',
|
|
['test_repl_equivalence.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps, libedit_dep],
|
|
install: false)
|
|
|
|
# Contract test for the REPL's job-identifier range compressor
|
|
# (scheduler-sim-repl-verbosity spec, task 1.1/1.2, Requirement 4).
|
|
# repl_fmt_jobid_range() lives in ../src/repl.c (design.md's File Structure
|
|
# Plan: "implements the new shared jobid-range-compression helper ... in
|
|
# repl.c"), but repl.c's own dependency surface is too large for the lean
|
|
# "#include the one file under test" pattern the other lightweight REPL
|
|
# tests use (test_repl_output_compression.c declares repl_fmt_jobid_range()
|
|
# as a plain extern rather than #include-ing repl.c -- see that file's own
|
|
# header comment: repl.c's repl_dispatch() references repl_cmd_break/
|
|
# repl_cmd_info/repl_cmd_set/... from sibling files repl_break.c/
|
|
# repl_info.c/repl_params.c, and a directly-linked .o -- unlike an archive
|
|
# member -- requires ALL its undefined symbols resolved regardless of
|
|
# whether the calling code path is ever exercised). So instead this target
|
|
# links the real scheduler_srcs object list, the same technique
|
|
# sched_scheduler_connect_test below established for the identical "real
|
|
# production dependency surface, avoid textual inclusion" problem.
|
|
# scheduler_srcs (parent meson.build) minus src/main.c (this test file
|
|
# supplies its own main()) -- built via a loop, same as
|
|
# 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)
|
|
|
|
# Contract test for the REPL's resource-value byte/megabyte classification
|
|
# and adaptive human-scaling helpers (scheduler-sim-repl-verbosity spec, task
|
|
# 7.1, Requirement 6.1/6.2 "Human-Readable Resource Value Formatting").
|
|
# repl_is_bytes_valued_resource()/repl_format_bytes_human() are pure,
|
|
# self-contained formatters (design.md's "Resource Value Formatter"
|
|
# component) that -- like repl_fmt_jobid_range() above -- do not yet exist
|
|
# anywhere in this codebase (task 7.2, a separate later task, implements
|
|
# them); this test file declares them as plain externs rather than
|
|
# #include-ing repl.c, same rationale as
|
|
# 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)
|
|
|
|
# Tests for the scheduler's unified candidate-list connect/rejoin pipeline
|
|
# (component-failover-adoption, task 3.1, boundary: SchedulerControllerClient).
|
|
# Unlike the white-box #include-the-.c-file tests above, this target links
|
|
# the REAL scheduler_srcs (everything sched_init() needs -- core.c,
|
|
# schedobj.c, resource.c, plugin.c, the picker/allocator plugins, etc.) and
|
|
# calls the real, public sched_init()/sched_fini(): scheduler.c's own
|
|
# dependency surface is too large for whole-file inclusion (same "too many
|
|
# externals to stub" reasoning sched_picker_core_loop_boundary_test's own
|
|
# comment already gives for not #include-ing scheduler.c), so this avoids
|
|
# that by linking the real objects instead of textually including one.
|
|
# 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)
|
|
|
|
# Tests for the scheduler's decision-publish retry-until-success-or-shutdown
|
|
# wrapper, composed with rejoin retry-on-failure (component-failover-adoption,
|
|
# task 3.2, boundary: SchedulerControllerClient). scheduler.c IS the file
|
|
# under test here (sched_publish_dispatch()/sched_publish_pend_reason()), so
|
|
# unlike sched_driver_decision_cb_test this target cannot spy on those two
|
|
# functions directly. Same real-scheduler_srcs link technique as
|
|
# sched_scheduler_connect_test above (reused scheduler_connect_test_srcs
|
|
# list), PLUS `-Wl,--wrap=` linker symbol interposition on the three libxce
|
|
# client calls this task's retry/rejoin logic makes (xcecli_jobdispatch,
|
|
# xcecli_set_pend_reason, xcecli_join) and two more needed only to let this
|
|
# file's one real sched_init() setup call reach xcecli_set_reconnect_handler()
|
|
# without a live controller (xcecli_start, xcecli_set_reconnect_handler) --
|
|
# see the test file's own header comment for why `--wrap` (which redirects
|
|
# call sites, not archive members) was required instead of the "test double
|
|
# ahead of the archive" trick: all of these symbols share client.c's single
|
|
# translation unit inside libxce.a with several OTHER xcecli_* entry points
|
|
# this test's real scheduler_srcs dependency graph also needs, so simply
|
|
# excluding client.c from the link was not viable.
|
|
scheduler_decision_publish_retry_test_srcs = [
|
|
'test_scheduler_decision_publish_retry.c']
|
|
foreach f : scheduler_srcs
|
|
if f != 'src/main.c'
|
|
scheduler_decision_publish_retry_test_srcs += ['../' + f]
|
|
endif
|
|
endforeach
|
|
|
|
sched_scheduler_decision_publish_retry_test = executable(
|
|
'sched_scheduler_decision_publish_retry_test',
|
|
scheduler_decision_publish_retry_test_srcs,
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_deps, unity_dep],
|
|
c_args: ['-DXCE_MAIN_C_PATH="'
|
|
+ (meson.current_source_dir() / '..' / 'src' / 'main.c')
|
|
+ '"'],
|
|
link_args: ['-Wl,--wrap=xcecli_jobdispatch',
|
|
'-Wl,--wrap=xcecli_set_pend_reason',
|
|
'-Wl,--wrap=xcecli_join',
|
|
'-Wl,--wrap=xcecli_start',
|
|
'-Wl,--wrap=xcecli_set_reconnect_handler',
|
|
'-Wl,--wrap=xcecli_is_connection_broken'],
|
|
install: false)
|
|
|
|
# Worst-case decision/allocation backpressure test (component-failover-
|
|
# adoption, task 3.3, boundary: SchedulerControllerClient, Req 3 AC2 / Req
|
|
# 7). Same real-scheduler_srcs link technique as the two targets above, PLUS
|
|
# `-Wl,--wrap=` on xcecli_start/xcecli_join (forced to succeed with no I/O,
|
|
# so this file's one real sched_init() call actually starts the picker/
|
|
# allocator threads) and xcecli_set_pend_reason (blocks on a test-controlled
|
|
# condvar, standing in for a stuck outage retry) -- see the test file's own
|
|
# header comment for the full design and worst-case derivation.
|
|
scheduler_backpressure_test_srcs = ['test_scheduler_backpressure.c']
|
|
foreach f : scheduler_srcs
|
|
if f != 'src/main.c'
|
|
scheduler_backpressure_test_srcs += ['../' + f]
|
|
endif
|
|
endforeach
|
|
|
|
sched_scheduler_backpressure_test = executable(
|
|
'sched_scheduler_backpressure_test',
|
|
scheduler_backpressure_test_srcs,
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_deps, unity_dep],
|
|
link_args: ['-Wl,--wrap=xcecli_start',
|
|
'-Wl,--wrap=xcecli_join',
|
|
'-Wl,--wrap=xcecli_set_pend_reason'],
|
|
install: false)
|
|
|
|
# Queue-level decision-redelivery test coverage (component-failover-adoption,
|
|
# task 3.4, boundary: SchedulerControllerClient, Req 7). Proves task 3.2's
|
|
# retry-until-success-or-shutdown wrapper's guarantees hold across MULTIPLE
|
|
# queued decisions drained through the real xce_sched_driver_on_decision()
|
|
# (driver.c), not just a single isolated call (already covered by
|
|
# test_scheduler_decision_publish_retry.c). Same real-scheduler_srcs link
|
|
# technique as the targets above, but only xcecli_jobdispatch() needs
|
|
# wrapping here -- these fixtures use xce_sched_core_init() directly (not
|
|
# sched_init()), so sched_needs_rejoin is never set and
|
|
# sched_publish_check_rejoin() never reaches xcecli_join(). Also needs
|
|
# driver.c's absolute path (XCE_DRIVER_C_PATH) alongside scheduler.c's
|
|
# (XCE_SCHEDULER_C_PATH, same pattern as sched_scheduler_connect_test) for
|
|
# its Req 7 AC5 source-text scan.
|
|
scheduler_decision_redelivery_test_srcs = [
|
|
'test_scheduler_decision_redelivery.c']
|
|
foreach f : scheduler_srcs
|
|
if f != 'src/main.c'
|
|
scheduler_decision_redelivery_test_srcs += ['../' + f]
|
|
endif
|
|
endforeach
|
|
|
|
sched_scheduler_decision_redelivery_test = executable(
|
|
'sched_scheduler_decision_redelivery_test',
|
|
scheduler_decision_redelivery_test_srcs,
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_deps, unity_dep],
|
|
c_args: ['-DXCE_SCHEDULER_C_PATH="'
|
|
+ (meson.current_source_dir() / '..' / 'src' / 'scheduler.c')
|
|
+ '"',
|
|
'-DXCE_DRIVER_C_PATH="'
|
|
+ (meson.current_source_dir() / '..' / 'src' / 'driver.c')
|
|
+ '"'],
|
|
link_args: ['-Wl,--wrap=xcecli_jobdispatch'],
|
|
install: false)
|
|
|
|
# scheduler-dispatch-commit spec, task 2.1 (Req 1.1/1.2/1.3): proves
|
|
# sched_commit_decision()'s DISPATCH branch transitions job->state to
|
|
# JOB_STAT_RUN in the same operation that already commits job->allocs/
|
|
# 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)
|
|
|
|
# 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
|
|
# xce_sched_core_load_snapshot() (task 1.2's job->schedobj fix) reaches the
|
|
# scheduler's REAL allocator entry point (sched_make_allocation(),
|
|
# `static` to scheduler.c) without crashing -- the exact bug-1569-class
|
|
# failure shape this feature closes. Same real-scheduler_srcs link
|
|
# technique as sched_scheduler_connect_test/sched_scheduler_backpressure_test
|
|
# above (see this test file's own header comment for why extending
|
|
# test_snapshot_save_load.c's existing white-box #include of core.c/
|
|
# core_events.c/.../snapshot_load.c with ALSO #include-ing scheduler.c was
|
|
# ruled out: scheduler.c's dependency surface is exactly the "link-surface
|
|
# reason" test_scheduler_connect.c's own header comment already documents
|
|
# for not white-box #include-ing it anywhere in this directory). Only
|
|
# `-Wl,--wrap=` needed is xcecli_start/xcecli_join (trivial always-succeed
|
|
# doubles, identical to sched_scheduler_backpressure_test's own), so this
|
|
# file's one real sched_init() call succeeds with no live controller and
|
|
# starts the real picker/allocator threads.
|
|
scheduler_snapshot_load_allocator_regression_test_srcs = [
|
|
'test_snapshot_load_allocator_regression.c']
|
|
foreach f : scheduler_srcs
|
|
if f != 'src/main.c'
|
|
scheduler_snapshot_load_allocator_regression_test_srcs += ['../' + f]
|
|
endif
|
|
endforeach
|
|
|
|
sched_snapshot_load_allocator_regression_test = executable(
|
|
'sched_snapshot_load_allocator_regression_test',
|
|
scheduler_snapshot_load_allocator_regression_test_srcs,
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_deps, unity_dep],
|
|
link_args: ['-Wl,--wrap=xcecli_start',
|
|
'-Wl,--wrap=xcecli_join'],
|
|
install: false)
|
|
|
|
# scheduler-allocation spec, task 5.1 (Req 7.3, 7.4, 7.5): wiring the
|
|
# unsatisfiable-resreq cache around sched_make_primary_alloc_() (`static`
|
|
# to scheduler.c). Same real-scheduler_srcs link technique as
|
|
# sched_snapshot_load_allocator_regression_test above (see this test
|
|
# file's own header comment for the full rationale). In addition to the
|
|
# usual xcecli_start/xcecli_join doubles, this file also wraps
|
|
# sched_meet_host_selection (resource.c, exported) to count real calls --
|
|
# the decisive "did the real allocator run" signal a cache HIT and a
|
|
# genuine exhausted attempt cannot otherwise be told apart by (both pend,
|
|
# and Req 7.5 requires them to report the SAME reason category).
|
|
scheduler_cache_dispatch_test_srcs = ['test_scheduler_cache_dispatch.c']
|
|
foreach f : scheduler_srcs
|
|
if f != 'src/main.c'
|
|
scheduler_cache_dispatch_test_srcs += ['../' + f]
|
|
endif
|
|
endforeach
|
|
|
|
sched_cache_dispatch_test = executable(
|
|
'sched_cache_dispatch_test',
|
|
scheduler_cache_dispatch_test_srcs,
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_deps, unity_dep],
|
|
link_args: ['-Wl,--wrap=xcecli_start',
|
|
'-Wl,--wrap=xcecli_join',
|
|
'-Wl,--wrap=sched_meet_host_selection'],
|
|
install: false)
|
|
|
|
# Companion to sched_cache_dispatch_test above: the primary-nested-inside-
|
|
# a-COMPOUND half of the same task 5.1 proof, kept in its own binary/
|
|
# process -- calling sched_init() twice in one process is not safe here
|
|
# (plugins/fcfs.c's legacy job_elect_fn path carries process-global state;
|
|
# a real run with both tests in one binary crashed with a genuine SEGV in
|
|
# fcfs_del_job() the first time this was tried -- see this test file's own
|
|
# header comment).
|
|
scheduler_cache_dispatch_compound_test_srcs = [
|
|
'test_scheduler_cache_dispatch_compound.c']
|
|
foreach f : scheduler_srcs
|
|
if f != 'src/main.c'
|
|
scheduler_cache_dispatch_compound_test_srcs += ['../' + f]
|
|
endif
|
|
endforeach
|
|
|
|
sched_cache_dispatch_compound_test = executable(
|
|
'sched_cache_dispatch_compound_test',
|
|
scheduler_cache_dispatch_compound_test_srcs,
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_deps, unity_dep],
|
|
link_args: ['-Wl,--wrap=xcecli_start',
|
|
'-Wl,--wrap=xcecli_join',
|
|
'-Wl,--wrap=sched_meet_host_selection'],
|
|
install: false)
|
|
|
|
# White-box regression test for bug-1685 (double-free/heap-corruption
|
|
# SIGABRT in limit_update_config() on a duplicate limit-name config
|
|
# update). It #includes ../src/plugins/limit.c directly (same white-box
|
|
# pattern as sched_picker_registration_test) so it exercises the real
|
|
# limit_update_config()/limit_init()/limit_priv_data_init() -- all
|
|
# `static`, otherwise unreachable from a test binary -- not a
|
|
# re-implementation of any of them. Stubs reset_sched_obj()/get_resvals()/
|
|
# put_resvals() (scheduler/src, not part of this TU) purely to satisfy the
|
|
# linker for limit.c code paths this test never exercises -- see the
|
|
# file's own header comment.
|
|
sched_limit_plugin_test = executable('sched_limit_plugin_test',
|
|
['test_limit_plugin.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps],
|
|
install: false)
|
|
|
|
# White-box regression test for bug-1686 (live SIGSEGV in
|
|
# fcfs_cursor_enter_queue() <- builtin_fcfs_next_job(), a heap-use-after-free
|
|
# on priv->cursor/job_cursor -- raw ordq_item_t* values that persist across
|
|
# separate next_job() calls and can be freed in between by a properly-locked
|
|
# on_queue_update() re-sort of the same queue). It #includes
|
|
# ../src/plugins/builtin_fcfs.c directly (same white-box pattern as
|
|
# sched_picker_fcfs_session_test) so it exercises the real cursor logic and
|
|
# the real private fcfs_plugin_data_t layout -- including direct field
|
|
# access to priv->cursor/priv->job_cursor, which only a white-box #include
|
|
# gives a test -- not a re-implementation of any of it. Supplies its own
|
|
# always-ready sched_queue_is_ready()/sched_job_is_ready() test doubles and a
|
|
# plugin_register() stub, same convention as sched_picker_fcfs_session_test.
|
|
sched_builtin_fcfs_cursor_uaf_test = executable(
|
|
'sched_builtin_fcfs_cursor_uaf_test',
|
|
['test_builtin_fcfs_cursor_uaf.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps],
|
|
install: false)
|
|
|
|
# Contract test for the lazy allocation-plan and host-candidate iterator
|
|
# interfaces (scheduler-allocation spec, task 1.1, Req 2 AC 1-6 / Req 3 AC
|
|
# 1-6). Only #includes the new ../include/sched/alloc_iter.h -- no
|
|
# allocator is wired onto these interfaces yet (parjob_allocator/
|
|
# seqjob_allocator rewrap is later tasks' own work). Proves the contract
|
|
# shape compiles and is usable via a trivial, no-op reference
|
|
# implementation of each interface, stack-allocated and initialized in
|
|
# place per the documented convention, driven through a full
|
|
# init()/next()/fini() cycle -- including the exact plan -> per-bucket
|
|
# fresh-host_iter composition shape requirements.md's Composition
|
|
# Algorithm describes for allocate_primary() (Req 3 AC 4 / Req 4 AC 2).
|
|
sched_alloc_plan_iter_test = executable(
|
|
'sched_alloc_plan_iter_test',
|
|
['test_alloc_plan_iter.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps],
|
|
install: false)
|
|
|
|
# Contract + behavioral test for the one shared xce_host_iter_t
|
|
# implementation (scheduler-allocation spec, task 2.1, Req 3 AC 1-6). Unlike
|
|
# sched_alloc_plan_iter_test's own trivial no-op stubs, this drives the REAL
|
|
# ../src/host_iter.c against real fixture state -- select-expression
|
|
# filtering, availability filtering, exhaustion, the fresh-per-bucket
|
|
# adversarial case (a host too small for one search remains a valid
|
|
# candidate for a later, smaller search over a freshly-initialized
|
|
# instance), and a behavioral proof of the required pthread_testcancel()
|
|
# cancellation point. Same white-box #include pattern as
|
|
# test_resource_accounting.c (../src/core.c, ../src/resource.c,
|
|
# ../src/schedobj.c) PLUS the new ../src/host_iter.c under test.
|
|
sched_host_iter_test = executable(
|
|
'sched_host_iter_test',
|
|
['test_host_iter.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps],
|
|
install: false)
|
|
|
|
# Unit test for the session-level unsatisfiable-resreq cache
|
|
# (scheduler-allocation spec, task 2.2, Req 7.1, 7.3, 7.4, 7.5). White-box
|
|
# TU (#includes ../src/alloc_cache.c directly, same convention as
|
|
# sched_host_iter_test above) -- never touches xce_sched_core_init(), since
|
|
# alloc_cache.c only depends on kv.h + scheduler.h/sched/types.h struct
|
|
# definitions, not on core.c's collections. Covers: same-key-twice hit
|
|
# (the cache_key_cmp_() three-way-vs-boolean polarity regression guard),
|
|
# a miss on every individually-differing fingerprint/identity field,
|
|
# reason-category round-trip across two distinct categories, and
|
|
# clear-empties-all-entries.
|
|
sched_alloc_cache_test = executable(
|
|
'sched_alloc_cache_test',
|
|
['test_alloc_cache.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps],
|
|
install: false)
|
|
|
|
# Unit test for task 5.2 (scheduler-allocation spec, Req 7.2): clearing the
|
|
# unsatisfiable-resreq cache at the start of every scheduling session, from
|
|
# inside core_begin_session_internal() (core_session.c), via the
|
|
# driver-registered xce_core_cache_clear_cb_t hook (round 2 -- replaces
|
|
# round 1's unconditional weak-symbol cache_clear() call, found to be a
|
|
# CRITICAL type-confusion bug against simulation-mode sessions; see
|
|
# test_sim_cache_clear_isolation_test below). See this test file's own
|
|
# header comment for why it lists core.c/core_clock.c/core_session.c/
|
|
# decision.c/alloc_cache.c as genuinely SEPARATE compiled sources rather
|
|
# than white-box #include-ing them into one TU (the same "real,
|
|
# separately-linked scheduler internals" technique task 5.1's own
|
|
# sched_cache_dispatch_test above already established for this feature,
|
|
# scaled down to just the files this narrower test needs) -- this test's
|
|
# own registered cache_clear_cb calls the REAL, strong cache_clear()
|
|
# (alloc_cache.c), which is only meaningfully distinguishable from a stub
|
|
# across genuinely separate object files, never within one merged
|
|
# translation unit.
|
|
sched_core_session_cache_clear_test = executable(
|
|
'sched_core_session_cache_clear_test',
|
|
['test_core_session_cache_clear.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)
|
|
|
|
# Regression test for task 5.2 ROUND 2 (scheduler-allocation spec, Req 7.2):
|
|
# the CRITICAL defect that got round 1 REJECTED -- core_begin_session_
|
|
# internal() must NEVER touch xce_sched_sim_driver_t's alt_events_file (or
|
|
# any other sim-only field) even with alloc_cache.c's real, strong
|
|
# cache_clear(xce_scheduler_t*) linked into the same binary, because
|
|
# sim_loop.c never registers a cache_clear_cb (Req 5 AC 17 "Simulation
|
|
# isolation" -- a simulation-mode core has no cache to clear at all). Same
|
|
# 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)
|
|
|
|
# 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
|
|
# maxTasks==1 guard on seqjob_prepare_allocation() (Req 4.6). Same
|
|
# white-box #include pattern as sched_host_iter_test above (../src/core.c,
|
|
# ../src/resource.c, ../src/schedobj.c, ../src/host_iter.c) PLUS
|
|
# ../src/plugins/seqjob_allocator.c itself, the file under test. Smoke-
|
|
# level coverage only -- the exhaustive pre/post-rewrap equivalence proof
|
|
# is task 3.2's dedicated sched_seqjob_rewrap_equivalence_test.
|
|
sched_seqjob_allocator_test = executable(
|
|
'sched_seqjob_allocator_test',
|
|
['test_seqjob_allocator.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps],
|
|
install: false)
|
|
|
|
# scheduler-allocator-runner task 2.1 (Req 4.5, 5.4, 5.8, 7.2): seqjob
|
|
# characterization through the plugin's registered job_alloc_fn, against
|
|
# today's allocator and (from task 4.2) the framework runner. Same white-box
|
|
# stack as sched_seqjob_allocator_test. `--wrap` on libxce's
|
|
# make_host_alloc/make_job_alloc gives the test fail-on-call-N out-of-memory
|
|
# injection points that stay the same across the switch.
|
|
sched_alloc_equivalence_seqjob_test = executable(
|
|
'sched_alloc_equivalence_seqjob_test',
|
|
['test_alloc_equivalence_seqjob.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps],
|
|
link_args: ['-Wl,--wrap=make_host_alloc',
|
|
'-Wl,--wrap=make_job_alloc'],
|
|
install: false)
|
|
|
|
# scheduler-allocator-runner task 2.2 (Req 4.5, 5.1, 5.2, 5.4, 5.8, 7.2):
|
|
# parjob characterization through the plugin's registered job_alloc_fn,
|
|
# against today's allocator and (from task 4.1) the framework runner. Same
|
|
# white-box stack and make_host_alloc/make_job_alloc wraps as
|
|
# sched_alloc_equivalence_seqjob_test.
|
|
sched_alloc_equivalence_parjob_test = executable(
|
|
'sched_alloc_equivalence_parjob_test',
|
|
['test_alloc_equivalence_parjob.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps],
|
|
link_args: ['-Wl,--wrap=make_host_alloc',
|
|
'-Wl,--wrap=make_job_alloc'],
|
|
install: false)
|
|
|
|
# scheduler-allocator-runner task 3.1 (Req 1.3, 1.4, 2.1-2.4, 5.1): the
|
|
# framework allocation routine (alloc_runner.c) through sched_allocator_run()
|
|
# with an in-test fake allocator contract. Same white-box stack as the
|
|
# equivalence targets above; make_pendreason is wrapped for the reason-record
|
|
# out-of-memory test (the make_*_alloc wraps are not needed).
|
|
sched_alloc_runner_test = executable(
|
|
'sched_alloc_runner_test',
|
|
['test_alloc_runner.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps],
|
|
link_args: ['-Wl,--wrap=make_pendreason'],
|
|
install: false)
|
|
|
|
# Task 3.2 (scheduler-allocation spec, Req 9.1): the dedicated pre/post-
|
|
# rewrap host-selection EQUIVALENCE proof for seqjob_allocator.c's
|
|
# my_alloc() -- fixture states task 3.1's own smoke test does not cover
|
|
# (multiple candidate hosts with only one resource-satisfying, a host
|
|
# failing the select filter specifically despite abundant resources,
|
|
# iteration-order sensitivity across two equally-valid hosts, and a
|
|
# select-fail-then-resource-fail-then-success sequence). Same white-box
|
|
# #include pattern as sched_seqjob_allocator_test above, plus <rtti.h>
|
|
# directly for this file's own iter_make()/iter_next() grounding of
|
|
# "iteration order".
|
|
sched_seqjob_rewrap_equivalence_test = executable(
|
|
'sched_seqjob_rewrap_equivalence_test',
|
|
['test_seqjob_rewrap_equivalence.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps],
|
|
install: false)
|
|
|
|
# Task 4.1 (scheduler-allocation spec, Req 2 AC 1-6, Req 4 AC 1):
|
|
# parjob_allocator.c's REAL combinatorial xce_alloc_plan_iter_t
|
|
# implementation -- ascending host-count plan order, one balanced
|
|
# ceil/floor partition per host-count, descending bucket order within
|
|
# each plan, a stable exhaustion signal, and a real pthread_testcancel()
|
|
# cancellation point. White-box #include of
|
|
# ../src/plugins/parjob_allocator.c itself (the file under test) --
|
|
# simpler than sched_seqjob_allocator_test's own white-box stack since
|
|
# parjob_allocator.c's still-stubbed my_alloc()/parjob_prepare_allocation()
|
|
# bodies (untouched by this task -- task 4.2's job) make no calls into
|
|
# core.c/resource.c/schedobj.c/host_iter.c at all, so none of those need
|
|
# to be pulled in here. Only my_alloc()/prepare_allocation() themselves
|
|
# are never called by this file's tests -- they exercise
|
|
# parjob_plan_iter_init()/_next()/_fini() directly.
|
|
sched_parjob_combinatorial_test = executable(
|
|
'sched_parjob_combinatorial_test',
|
|
['test_parjob_combinatorial.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps],
|
|
install: false)
|
|
|
|
# Register as meson tests so `meson test --suite scheduler` runs them all.
|
|
# detect_leaks=0 matches the suite convention (fixtures are not torn down).
|
|
test('scheduler test', scheduler_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
test('scheduler job-update test', sched_job_update_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
test('scheduler handlers test', sched_handlers_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
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',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
test('scheduler picker config fields test', sched_picker_config_fields_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
test('scheduler picker fcfs test', sched_picker_fcfs_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
test('scheduler picker fcfs session test', sched_picker_fcfs_session_test, suite: 'scheduler',
|
|
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'])
|
|
test('scheduler core events test',
|
|
sched_core_events_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
test('scheduler core session test',
|
|
sched_core_session_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
test('scheduler core clock test',
|
|
sched_core_clock_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
test('scheduler core full cycle test',
|
|
sched_core_full_cycle_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
test('scheduler driver translate test',
|
|
sched_driver_translate_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
test('scheduler resval ownership test',
|
|
sched_resval_ownership_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
test('scheduler driver decision cb test',
|
|
sched_driver_decision_cb_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
test('scheduler driver session ordering test',
|
|
sched_driver_session_ordering_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
test('scheduler resource accounting test',
|
|
sched_resource_accounting_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
test('scheduler snapshot save load test',
|
|
sched_snapshot_save_load_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
test('scheduler recording path validation test',
|
|
sched_recording_path_validation_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
test('scheduler record lifecycle test',
|
|
sched_record_lifecycle_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
test('scheduler admin request test',
|
|
sched_admin_request_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
test('scheduler sim startup test',
|
|
sched_sim_startup_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
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'])
|
|
test('scheduler sim alt events test',
|
|
sched_sim_alt_events_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
test('scheduler sim record output test',
|
|
sched_sim_record_output_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
test('scheduler sim equivalence test',
|
|
sched_sim_equivalence_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
test('scheduler sim session ordering test',
|
|
sched_sim_session_ordering_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
test('scheduler sim reconcile unaccounted test',
|
|
sched_sim_reconcile_unaccounted_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
test('scheduler sim resource contention test',
|
|
sched_sim_resource_contention_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
test('scheduler sim round boundary reconciliation test',
|
|
sched_sim_round_boundary_reconciliation_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
test('scheduler sim snapshot reconcile gap test',
|
|
sched_sim_snapshot_reconcile_gap_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
test('scheduler sim contention parity test',
|
|
sched_sim_contention_parity_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
test('scheduler sim e2e original motivation test',
|
|
sched_sim_e2e_original_motivation_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
test('scheduler repl execution control test',
|
|
sched_repl_execution_control_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
test('scheduler repl round rollup test',
|
|
sched_repl_round_rollup_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
test('scheduler repl event echo test',
|
|
sched_repl_event_echo_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
test('scheduler repl step verbosity test',
|
|
sched_repl_step_verbosity_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
test('scheduler repl prompt context test',
|
|
sched_repl_prompt_context_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
test('scheduler sim print decision gate test',
|
|
sched_sim_print_decision_gate_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
test('scheduler repl breakpoints inspection test',
|
|
sched_repl_breakpoints_inspection_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
test('scheduler repl resource table test',
|
|
sched_repl_resource_table_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
test('scheduler repl limit table test',
|
|
sched_repl_limit_table_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
test('scheduler repl help test',
|
|
sched_repl_help_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
test('scheduler repl snapshot params test',
|
|
sched_repl_snapshot_params_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
test('scheduler repl equivalence test',
|
|
sched_repl_equivalence_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
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
|
|
# sched_scheduler_connect_test) plus `-Wl,--wrap=strdup` to make a chosen
|
|
# strdup() inside make_alloc() fail.
|
|
sched_make_allocs_oom_test_srcs = ['test_sched_make_allocs_oom.c']
|
|
foreach f : scheduler_srcs
|
|
if f != 'src/main.c'
|
|
sched_make_allocs_oom_test_srcs += ['../' + f]
|
|
endif
|
|
endforeach
|
|
|
|
sched_make_allocs_oom_test = executable(
|
|
'sched_make_allocs_oom_test',
|
|
sched_make_allocs_oom_test_srcs,
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_deps, unity_dep],
|
|
link_args: ['-Wl,--wrap=strdup'],
|
|
install: false)
|
|
|
|
test('scheduler make_allocs OOM test',
|
|
sched_make_allocs_oom_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
test('scheduler decision publish retry test',
|
|
sched_scheduler_decision_publish_retry_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
test('scheduler backpressure test',
|
|
sched_scheduler_backpressure_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
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'])
|
|
test('scheduler limit plugin test', sched_limit_plugin_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
test('scheduler builtin fcfs cursor uaf test',
|
|
sched_builtin_fcfs_cursor_uaf_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
test('scheduler alloc plan iter test',
|
|
sched_alloc_plan_iter_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
test('scheduler host iter test',
|
|
sched_host_iter_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
test('scheduler alloc cache test',
|
|
sched_alloc_cache_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
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'])
|
|
# Leak detection stays on: every fixture tears down its ctx, core and plugin.
|
|
test('scheduler alloc equivalence seqjob test',
|
|
sched_alloc_equivalence_seqjob_test, suite: 'scheduler')
|
|
# Leak detection stays on (as for the seqjob characterization above).
|
|
test('scheduler alloc equivalence parjob test',
|
|
sched_alloc_equivalence_parjob_test, suite: 'scheduler')
|
|
# Leak detection stays on: every fixture tears down its ctx and core.
|
|
test('scheduler alloc runner test',
|
|
sched_alloc_runner_test, suite: 'scheduler')
|
|
test('scheduler seqjob rewrap equivalence test',
|
|
sched_seqjob_rewrap_equivalence_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
test('scheduler parjob combinatorial test',
|
|
sched_parjob_combinatorial_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
test('scheduler cache dispatch test',
|
|
sched_cache_dispatch_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
test('scheduler cache dispatch compound test',
|
|
sched_cache_dispatch_compound_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
|
|
# scheduler-allocation spec, task 5.3 (Req 4.1, 4.2, 4.3): the capstone
|
|
# end-to-end integration test for this whole feature -- drives a real
|
|
# maxTasks>1 parallel job through the full production dispatch path
|
|
# (sched_init()'s real, live sched_allocator() thread -> the real, `static`
|
|
# sched_make_allocation()/sched_make_primary_alloc_() choke point -> the
|
|
# real parjob_allocator.c my_alloc() -> the real host_iter.c host iterator
|
|
# -> a real multi-host xce_job_alloc_t commit), asserting the resulting
|
|
# job->allocs/decision->u.alloc spans exactly 2 hosts with the correct
|
|
# per-host slot counts. Same real-scheduler_srcs link technique as
|
|
# sched_snapshot_load_allocator_regression_test/sched_cache_dispatch_test
|
|
# above (see this test file's own header comment for the full rationale).
|
|
scheduler_parjob_e2e_multislot_test_srcs = [
|
|
'test_parjob_e2e_multislot.c']
|
|
foreach f : scheduler_srcs
|
|
if f != 'src/main.c'
|
|
scheduler_parjob_e2e_multislot_test_srcs += ['../' + f]
|
|
endif
|
|
endforeach
|
|
|
|
sched_parjob_e2e_multislot_test = executable(
|
|
'sched_parjob_e2e_multislot_test',
|
|
scheduler_parjob_e2e_multislot_test_srcs,
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_deps, unity_dep],
|
|
link_args: ['-Wl,--wrap=xcecli_start',
|
|
'-Wl,--wrap=xcecli_join'],
|
|
install: false)
|
|
|
|
test('scheduler parjob e2e multislot test',
|
|
sched_parjob_e2e_multislot_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
|
|
# resreq-maxtasks-wiring spec, task 3.1 (Req 1.1, 1.3, 3.1, 3.2, 5.6): the
|
|
# dedicated integration test file for this feature's two live ingest call
|
|
# sites -- fresh ingest reflects a real multi-task job's requested task
|
|
# count (Req 1.1), fresh ingest and snapshot-restore ingest derive the
|
|
# IDENTICAL task count for an equivalent job (Req 1.3/5.6's own comparative
|
|
# claim), and a single-task job's real host-selection/dispatch outcome is
|
|
# unaffected by this feature (Req 3.1/3.2). Same real-scheduler_srcs link
|
|
# technique as sched_parjob_e2e_multislot_test/sched_snapshot_load_
|
|
# allocator_regression_test above (see this test file's own header comment
|
|
# for the full rationale -- one link technique for the whole file avoids a
|
|
# duplicate-symbol conflict with meson's own separate compilation of
|
|
# core.c/core_events.c/snapshot_load.c below).
|
|
sched_maxtasks_wiring_ingest_test_srcs = [
|
|
'test_maxtasks_wiring_ingest.c']
|
|
foreach f : scheduler_srcs
|
|
if f != 'src/main.c'
|
|
sched_maxtasks_wiring_ingest_test_srcs += ['../' + f]
|
|
endif
|
|
endforeach
|
|
|
|
sched_maxtasks_wiring_ingest_test = executable(
|
|
'sched_maxtasks_wiring_ingest_test',
|
|
sched_maxtasks_wiring_ingest_test_srcs,
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_deps, unity_dep],
|
|
link_args: ['-Wl,--wrap=xcecli_start',
|
|
'-Wl,--wrap=xcecli_join'],
|
|
install: false)
|
|
|
|
test('scheduler maxtasks wiring ingest test',
|
|
sched_maxtasks_wiring_ingest_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
|
|
# resreq-maxtasks-wiring spec, task 3.2 remediation round (Req 1.4, 5.4, and
|
|
# design.md's "Project Invariant Cross-Check" driver/simulation parity
|
|
# commitment): proves the REAL, `static` simulation-driver translator chain
|
|
# (sim_process_replay_event_message() -> replay_event_to_core_event(),
|
|
# sim_loop.c) -- not a hand-built mirror of it -- applies this feature's
|
|
# task-count wiring correctly, by feeding a hand-built, in-memory
|
|
# ReplayEvent{jobsPush} capnp message through the REAL function and pushing
|
|
# its own real output through the identical xce_core_push_events()/
|
|
# core_build_job() ingest chain. Same white-box #include pattern as
|
|
# sched_sim_event_loop_test (core.c, core_clock.c, core_events.c,
|
|
# core_session.c, decision.c, plugin.c, plugins/builtin_fcfs.c, recording.c,
|
|
# recording_session.c, repl.c and siblings, sim.c, sim_loop.c, sim_picker.c,
|
|
# sim_record.c, sim_verify.c, snapshot.c/snapshot_wire.c/snapshot_load.c) --
|
|
# see this test file's own header comment for why it is a separate file
|
|
# from sched_maxtasks_wiring_ingest_test (that file links the whole real
|
|
# scheduler_srcs object list for its own test 3, which would collide with
|
|
# this file's white-box #include of core_events.c/sim_loop.c into the same
|
|
# translation unit).
|
|
sched_maxtasks_wiring_sim_driver_parity_test = executable(
|
|
'sched_maxtasks_wiring_sim_driver_parity_test',
|
|
['test_maxtasks_wiring_sim_driver_parity.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps],
|
|
install: false)
|
|
|
|
test('scheduler maxtasks wiring sim driver parity test',
|
|
sched_maxtasks_wiring_sim_driver_parity_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
|
|
# scheduler-sim-live-allocation spec, task 3.1 (Req 1.1, 1.2, 5.1, boundary:
|
|
# Unified Picker/Allocator Threads): proves sched_job_picker()/
|
|
# sched_allocator() -- relocated out of scheduler.c into their own file,
|
|
# sched_election.c, and re-typed to cast their void* arg directly to
|
|
# xce_sched_core_t* -- run correctly when pthread_create() is handed
|
|
# nothing but a bare xce_sched_core_t*, the exact shape a future
|
|
# simulation driver (task 4.1) will use. Same real-scheduler_srcs link
|
|
# technique as sched_scheduler_dispatch_commit_test above (scheduler_srcs,
|
|
# defined in the parent meson.build, minus src/main.c, built via a loop so
|
|
# 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'])
|
|
|
|
# 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
|
|
# sched_sim_driver_run() (sim_loop.c) itself -- not just the relocated
|
|
# thread pair in isolation (task 3.1's own sched_election_sim_fixture_test
|
|
# above) -- genuinely dispatches a job against simulation mode's own core
|
|
# state when driven from a real `.replay` stream, closing the always-PEND
|
|
# gap sim_picker_thread_fn() (now removed) documented as its own "known
|
|
# scope boundary". Same real-scheduler_srcs link technique as
|
|
# 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'])
|
|
|
|
# scheduler-sim-live-allocation spec, task 4.3 (Req 2.2, boundary: Unified
|
|
# Picker/Allocator Threads, Limit Plugin Core-Safe Matching): proves a
|
|
# host-scoped limit registered directly against simulation mode's real core
|
|
# (sim_bootstrap_limit_plugin()) is matched -- and its usage instance
|
|
# created -- during a genuine seqjob/parjob dispatch attempt driven through
|
|
# the real sched_job_picker()/sched_allocator() thread pair, closing the
|
|
# gap task 4.1 left (bug-1829: the seqjob/parjob allocator plugin's own
|
|
# 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'])
|
|
|
|
# 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
|
|
# multi-job, capacity-insufficient contention fixture on BOTH a normal-mode-
|
|
# shaped core (xce_scheduler_t) and a simulation-mode-shaped core
|
|
# (xce_sched_sim_driver_t) side by side, confirming identical admission
|
|
# 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'])
|
|
|
|
# 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-
|
|
# scoped limit that actively matches every contending job on both drivers
|
|
# (Requirement 3.2's "capacity constrained by a matching limit" /
|
|
# 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'])
|
|
|
|
# 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'])
|
|
|
|
# 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'])
|
|
|
|
# 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
|
|
# AND host-scoped limit configured in a real SnapshotEntry's Conf4Sched,
|
|
# carried through a real `.replay` file, driven end to end via the real,
|
|
# unmodified sched_sim_driver_run() -- confirming `info limit`'s own
|
|
# backing accessors (limit_get_configured_limits()/limit_get_usage_
|
|
# 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'])
|
|
|
|
# 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
|
|
# simulation mode (sim_alloc.c's session-less wrapper allocators) --
|
|
# carries the session start in whole seconds as `from`, stamped by
|
|
# sched_make_primary_alloc_() from the session core. Same real-
|
|
# scheduler_srcs link technique as sched_parjob_e2e_multislot_test.
|
|
sched_alloc_from_stamp_test_srcs = ['test_sched_alloc_from_stamp.c']
|
|
foreach f : scheduler_srcs
|
|
if f != 'src/main.c'
|
|
sched_alloc_from_stamp_test_srcs += ['../' + f]
|
|
endif
|
|
endforeach
|
|
|
|
sched_alloc_from_stamp_test = executable(
|
|
'sched_alloc_from_stamp_test',
|
|
sched_alloc_from_stamp_test_srcs,
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_deps, unity_dep],
|
|
link_args: ['-Wl,--wrap=xcecli_start',
|
|
'-Wl,--wrap=xcecli_join'],
|
|
install: false)
|
|
|
|
test('scheduler alloc from stamp test',
|
|
sched_alloc_from_stamp_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
|
|
|
# scheduler-sim-discrete-clock spec (task 1.1, Req 2.3-2.5): unit tests for
|
|
# the --sim-speed deprecation warning (../src/cli_compat.c), and -- in later
|
|
# tasks -- the discrete-clock and end-to-end command-line tests. Sources are
|
|
# the test file and cli_compat.c ONLY: the white-box sim #includes live in
|
|
# the test file itself (listing sim sources here too would define every
|
|
# symbol twice). XCE_SCHEDULER_BIN points the end-to-end tests at the built
|
|
# xce_scheduler, which `depends: scheduler` guarantees is built first.
|
|
sched_sim_discrete_clock_test = executable(
|
|
'sched_sim_discrete_clock_test',
|
|
['test_sim_discrete_clock.c', '../src/cli_compat.c'],
|
|
include_directories:[incdir],
|
|
dependencies: [scheduler_test_deps, libedit_dep],
|
|
c_args: ['-DXCE_SCHEDULER_BIN="' + scheduler.full_path() + '"'],
|
|
install: false)
|
|
|
|
test('scheduler sim discrete clock test',
|
|
sched_sim_discrete_clock_test, suite: 'scheduler',
|
|
env: ['ASAN_OPTIONS=detect_leaks=0'],
|
|
depends: scheduler)
|