From 40261b7e96bf3a4514a0e7ee5b9772c9e0e506f8 Mon Sep 17 00:00:00 2001 From: Rongsong Shen Date: Thu, 30 Apr 2026 05:04:47 +0000 Subject: [PATCH] feat: implement sched_meet_host_selection using eval_select_simple (6-5) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the always-return-1 stub with a real implementation that: - Returns 1 immediately when s == NULL or s->root == NULL (no constraint) - Builds a host_eval_ctx_t from w->resvals and calls eval_select_simple - Uses a zero-resource stack context when resvals.caps == 0 so constant sub-expressions (SEL_TRUE, SEL_FALSE, SEL_ANY) still evaluate correctly - On OOM (build_host_eval_ctx returns NULL), conservatively passes the host - Maps eval_select_simple result: >0 → 1 (match), <=0 → 0 (no-match) Add #define UNIT_TEST 1 to test.c, remove redundant #ifdef guard, and add three new TDD tests covering NULL select, SEL_TRUE, and SEL_FALSE. All 6 tests pass. --- src/scheduler/src/resource.c | 31 +++++++++++++- src/scheduler/testsuite/test.c | 76 +++++++++++++++++++++++++++++++++- 2 files changed, 103 insertions(+), 4 deletions(-) diff --git a/src/scheduler/src/resource.c b/src/scheduler/src/resource.c index 1ebdbf7..c7a814b 100644 --- a/src/scheduler/src/resource.c +++ b/src/scheduler/src/resource.c @@ -179,8 +179,35 @@ free_host_eval_ctx(host_eval_ctx_t* ctx) int sched_meet_host_selection(xce_scheduler_t* sched, xce_sched_worker_t* w, xce_select_t* s) { - /* FIXME: add real work later */ - return 1; + (void)sched; + + if (s == NULL || s->root == NULL) return 1; + + int num_res = (int)w->resvals.caps; + + /* When num_res == 0, build_host_eval_ctx returns NULL (no resource slots). + * Use an empty stack-allocated context so eval_select_simple can still + * evaluate constant sub-expressions (SEL_TRUE, SEL_FALSE, SEL_ANY). */ + host_eval_ctx_t empty_ctx = { .num_res = 0, .numvals = NULL, .strvals = NULL }; + host_eval_ctx_t* hctx; + + if (num_res <= 0) { + hctx = &empty_ctx; + } else { + hctx = build_host_eval_ctx(w, num_res); + if (hctx == NULL) { + /* OOM: conservatively pass host */ + return 1; + } + } + + int rc = eval_select_simple(s->root, hctx); + if (hctx != &empty_ctx) { + free_host_eval_ctx(hctx); + } + + /* eval_select_simple: 1=match, 0=no-match, <0=error (treat as no-match) */ + return (rc > 0) ? 1 : 0; } static int sched_check_shared_satisfy_(xce_scheduler_t* sched, xvec_t* total, diff --git a/src/scheduler/testsuite/test.c b/src/scheduler/testsuite/test.c index d8b7313..81085ff 100644 --- a/src/scheduler/testsuite/test.c +++ b/src/scheduler/testsuite/test.c @@ -1,3 +1,4 @@ +#define UNIT_TEST 1 #include #include #include @@ -122,9 +123,77 @@ test_sel_optimize_set_at_scheduler_startup(void) sel_optimize_set(1); TEST_ASSERT_EQUAL_INT(1, sel_get_optimize_level()); /* reset for clean test isolation */ -#ifdef UNIT_TEST sel_optimize_test_reset(); -#endif +} + +static void +test_meet_host_selection_null_select_passes(void) +{ + /* A NULL select pointer means no expression — always pass */ + xce_scheduler_t sched; + memset(&sched, 0, sizeof(sched)); + xce_sched_worker_t w; + memset(&w, 0, sizeof(w)); + zarray_init(&w.resvals, 4, NULL); + + int rc = sched_meet_host_selection(&sched, &w, NULL); + TEST_ASSERT_EQUAL_INT(1, rc); + + zarray_fini(&w.resvals); +} + +static void +test_meet_host_selection_always_true_passes(void) +{ + xce_scheduler_t sched; + memset(&sched, 0, sizeof(sched)); + sel_optimize_set(1); + sel_node_table_init(); + + xce_sched_worker_t w; + memset(&w, 0, sizeof(w)); + zarray_init(&w.resvals, 4, NULL); + + /* SEL_TRUE root — must pass any host */ + xce_select_node_t* root = makeSelectNode(SEL_TRUE, 0, 0); + TEST_ASSERT_NOT_NULL(root); + + xce_select_t sel = { .root = root }; + int rc = sched_meet_host_selection(&sched, &w, &sel); + TEST_ASSERT_EQUAL_INT(1, rc); + + zarray_fini(&w.resvals); + gc_clear_marks(); + gc_sweep_select_nodes(NULL, 0); + sel_node_table_fini(); + sel_optimize_test_reset(); +} + +static void +test_meet_host_selection_always_false_fails(void) +{ + xce_scheduler_t sched; + memset(&sched, 0, sizeof(sched)); + sel_optimize_set(1); + sel_node_table_init(); + + xce_sched_worker_t w; + memset(&w, 0, sizeof(w)); + zarray_init(&w.resvals, 4, NULL); + + /* SEL_FALSE root — must fail every host */ + xce_select_node_t* root = makeSelectNode(SEL_FALSE, 0, 0); + TEST_ASSERT_NOT_NULL(root); + + xce_select_t sel = { .root = root }; + int rc = sched_meet_host_selection(&sched, &w, &sel); + TEST_ASSERT_EQUAL_INT(0, rc); + + zarray_fini(&w.resvals); + gc_clear_marks(); + gc_sweep_select_nodes(NULL, 0); + sel_node_table_fini(); + sel_optimize_test_reset(); } #define TEST(x) \ @@ -143,6 +212,9 @@ int main(int argc, char* argv[]) TEST(test_build_host_eval_ctx_float); TEST(test_scheduler_t_has_atomic_gc_fields); TEST(test_sel_optimize_set_at_scheduler_startup); + TEST(test_meet_host_selection_null_select_passes); + TEST(test_meet_host_selection_always_true_passes); + TEST(test_meet_host_selection_always_false_fails); return UNITY_END(); }