diff --git a/src/scheduler/src/repl_trace_render_outcome.c b/src/scheduler/src/repl_trace_render_outcome.c index b5ac425e..0f343dc0 100644 --- a/src/scheduler/src/repl_trace_render_outcome.c +++ b/src/scheduler/src/repl_trace_render_outcome.c @@ -248,9 +248,12 @@ static void put_pend(FILE* f, const sched_trace_pend_out_t* p) return; } + /* 0 is libxce's "no main reason set" (preason.c), not a code */ rtr_indent(f, 2); fprintf(f, "main reason: %s\n", - rtr_reason_name(r->main_reason, buf, sizeof(buf))); + (r->main_reason == 0) + ? "none" + : rtr_reason_name(r->main_reason, buf, sizeof(buf))); /* entries tied to no host (a shared resource carries host "") */ for (k = 0; (r->host_based_reasons != NULL) && (k < r->nhost_reasons); diff --git a/src/scheduler/testsuite/test_repl_trace_e2e.c b/src/scheduler/testsuite/test_repl_trace_e2e.c index 6b16f1b9..f804a1a4 100644 --- a/src/scheduler/testsuite/test_repl_trace_e2e.c +++ b/src/scheduler/testsuite/test_repl_trace_e2e.c @@ -338,6 +338,7 @@ static void test_step_mode_full_all_jobs_and_file_copy(void) "\n cluster-wide check failed; no placement plans tried\n", "\n single requirement not satisfied\n", "\n outcome: PEND\n", + "\n main reason: none\n", "\n resource license: NO_RESOURCE\n", "\n resource limit=cluster_slots: NO_RESOURCE\n"); TEST_ASSERT_NULL(strstr(b, "plan 1")); @@ -362,7 +363,7 @@ static void test_step_mode_full_all_jobs_and_file_copy(void) "\n alternative 2/2 not satisfied\n", "\n no alternative chosen: none of the 2 alternatives was " "satisfied\n", - "\n outcome: PEND\n"); + "\n outcome: PEND\n", "\n main reason: none\n"); free(b); /* 105, session 5: per-host shortfall rows next to limit rows, the diff --git a/src/scheduler/testsuite/test_trace_render.c b/src/scheduler/testsuite/test_trace_render.c index 3a8541c6..1dc8cf84 100644 --- a/src/scheduler/testsuite/test_trace_render.c +++ b/src/scheduler/testsuite/test_trace_render.c @@ -865,6 +865,42 @@ static void test_pend_outcome_null_entries(void) sched_trace_rec_free(rec); } +/* A pend whose set carries no main reason (0, preason.c's "none set"), as + * every pend the allocator builds from per-host and per-resource reasons + * does: the line says none instead of a bare code. */ +static void test_pend_outcome_without_main_reason(void) +{ + xce_sched_trace_rec_t* rec; + xce_res_reason_t rr = { "license", "", PREASON_NO_RESOURCE }; + xce_res_reason_t* rrp[1] = { &rr }; + xce_job_preason_t jr; + char* out; + + rec = new_rec(XCE_TRACE_LEVEL_FULL, XCE_TRACE_LINE_BOUND_DEFAULT, + XCE_TRACE_REC_DECISION); + TEST_ASSERT_NOT_NULL(rec); + set_selection(rec); + set_glimits(rec, 0, NULL, NULL); + + memset(&jr, 0, sizeof(jr)); + jr.nres_reasons = 1; + jr.res_based_reasons = rrp; + rec->outcome = SCHED_TRACE_OUTCOME_PEND; + rec->pend.reasons = &jr; /* read only by the renderer */ + + out = render(rec, XCE_REPL_UNITS_RAW); + assert_golden( + "[trace] job 1-2-1000-42 session 7 position 3 level full\n" + SEL_LINE NO_LIMITS_LINE + " outcome: PEND\n" + " main reason: none\n" + " resource license: NO_RESOURCE\n", + out); + free(out); + rec->pend.reasons = NULL; + sched_trace_rec_free(rec); +} + /* ---- no-decision and reconstructed records (2.4, 2.5) ------------------- */ static void test_no_decision_not_found(void) @@ -1277,6 +1313,7 @@ int main(void) RUN_TEST(test_dispatch_outcome_cap); RUN_TEST(test_pend_outcome); RUN_TEST(test_pend_outcome_null_entries); + RUN_TEST(test_pend_outcome_without_main_reason); RUN_TEST(test_no_decision_not_found); RUN_TEST(test_no_decision_no_schedobj); RUN_TEST(test_no_decision_internal_error_keeps_hierarchy);