diff --git a/.kiro/specs/xce-test-e2e-primitives/tasks.md b/.kiro/specs/xce-test-e2e-primitives/tasks.md index 6bccea73..86f04ef9 100644 --- a/.kiro/specs/xce-test-e2e-primitives/tasks.md +++ b/.kiro/specs/xce-test-e2e-primitives/tasks.md @@ -47,7 +47,7 @@ - _Requirements: 3.4_ - _Boundary: JoblistCount_ - _Depends: 1.1, 3.1_ -- [ ] 5.2 `expect-jobs N` assertion +- [x] 5.2 `expect-jobs N` assertion - Add `cmd_expect_jobs`: pass when the current job count equals `N`; otherwise print expected vs actual and return `<0`. - Observable: `expect-jobs ` succeeds; `expect-jobs ` fails the session and prints expected/actual. - _Requirements: 5.1, 5.2_ diff --git a/src/controller/testsuite/test.c b/src/controller/testsuite/test.c index 064502c9..fa5cd816 100644 --- a/src/controller/testsuite/test.c +++ b/src/controller/testsuite/test.c @@ -117,6 +117,7 @@ extern int cmd_runtasks(int, char*[]); extern int cmd_setpend(int, char*[]); extern int cmd_jobinfo(int, char*[]); extern int cmd_echo(int, char*[]); +extern int cmd_expect_jobs(int, char*[]); static int worker_house_keeping(void*); /* Session verdict / loop state (xce-test-e2e-primitives task 1.1). @@ -201,6 +202,7 @@ static command_t client_commands[] = { { "workerlist", cmd_workerlist, "list workers" }, { "qctrl", cmd_qctrl, "queue control" }, { "joblist", cmd_joblist, "list jobs" }, + { "expect-jobs", cmd_expect_jobs, "assert current job count" }, { "shutdown", cmd_shutdown, "shutdown xce controller" }, { "jobrun", cmd_jobrun, "run a job" }, { "jobsub", cmd_jobsub, "submit a job" }, @@ -965,6 +967,60 @@ int cmd_joblist(int argc, char* argv[]) return 0; } +/* `expect-jobs N` assertion (xce-test-e2e-primitives task 5.2, Req 5.1/5.2, + * design.md:116-117). + * + * Passes (returns 0) when the current job count equals N; otherwise prints the + * expected vs actual count and returns a negative errno-style value so + * preprocess_and_run records the session as failed (Req 1.1). + * + * A malformed argument (missing or non-numeric N) is itself an assertion + * failure, not a no-op. A failed joblist query is treated as a failure too: we + * cannot determine the count, so we never silently equate "query failed" with + * "zero jobs" (Req 5.2 reports actual; a failed query has no trustworthy + * actual). */ +int cmd_expect_jobs(int argc, char* argv[]) +{ + long expected; + char* end; + int count; + + if (argc != 2) { + printf("expect-jobs \n"); + return -EINVAL; + } + + errno = 0; + expected = strtol(argv[1], &end, 10); + + if ((errno != 0) || (end == argv[1]) || (*end != '\0') || (expected < 0)) { + printf("expect-jobs: invalid count '%s' (expected a non-negative " + "integer)\n", + argv[1]); + return -EINVAL; + } + + /* Print-free count via the shared helper. A negative rc means the query + * itself failed (e.g. no reachable master) — that is an assertion failure, + * not "0 jobs". */ + count = joblist_query(NULL, NULL, 0); + + if (count < 0) { + printf("expect-jobs: could not determine job count (joblist query " + "failed)\n"); + return count; + } + + if (count != (int)expected) { + printf("expect-jobs: expected %ld, actual %d\n", expected, count); + return -EINVAL; + } + + printf("expect-jobs: ok (%d)\n", count); + + return 0; +} + static void print_jobinfo(xce_job_t* job) { char idstring[128];