feat(xce-test-e2e-primitives): session verdict + exit code + abort/continue + comment handling (task 1.1)

This commit is contained in:
Rongsong Shen 2026-06-19 15:32:11 +00:00
parent 64ab210cbf
commit 481e197928
2 changed files with 164 additions and 7 deletions

View file

@ -117,6 +117,21 @@ extern int cmd_setpend(int, char*[]);
extern int cmd_jobinfo(int, char*[]);
static int worker_house_keeping(void*);
/* Session verdict / loop state (xce-test-e2e-primitives task 1.1).
*
* g_session_failed set to 1 the first time any command in the session
* fails; drives the process exit code in main().
* g_continue_on_error when set (via `set continue-on-error`), a failing
* command does not stop the read loop; the session still
* exits non-zero at the end.
* g_last_status status of the most recently executed command
* (0 == success, non-zero == failure). Future tasks
* expose this as the `$?` auto-variable.
*/
static int g_session_failed = 0;
static int g_continue_on_error = 0;
static int g_last_status = 0;
static idgen_ctx_t idctx;
delaymgr_t delaymgr;
@ -385,6 +400,51 @@ int execute_line(char* line)
return rc;
}
/* Main-loop wrapper around execute_line that implements the session verdict
* (xce-test-e2e-primitives task 1.1):
* - blank / whitespace-only lines and `#`-comment lines are ignored;
* - normal lines run via execute_line; g_last_status / g_session_failed are
* updated from the result;
* - in default (abort) mode a failure stops the loop; under
* g_continue_on_error the loop keeps running but the failure is recorded.
*
* Returns 0 to keep the read loop running, non-zero to request that the loop
* stop (abort-on-failure). The leading `!` shell-escape and `$`-substitution
* are intentionally handled in later tasks (2.1 / 3.1); this function is the
* single chokepoint where they will be added.
*/
int preprocess_and_run(char* line)
{
char* p = line;
int rc;
/* Skip leading whitespace to classify the line. */
while ((*p == ' ') || (*p == '\t')) {
p++;
}
/* Ignore blank / whitespace-only lines and `#` comments. */
if ((*p == '\0') || (*p == '#')) {
return 0;
}
rc = execute_line(line);
g_last_status = (rc < 0) ? (rc) : 0;
if (rc < 0) {
SET_ERROR(-rc);
g_session_failed = 1;
if (!g_continue_on_error) {
return 1; /* abort: stop the read loop */
}
} else {
add_history(line);
}
return 0;
}
int cmd_help(int argc, char* argv[])
{
int i;
@ -1791,6 +1851,15 @@ int cmd_set(int argc, char* argv[])
return 0;
}
/* Session verdict toggle (xce-test-e2e-primitives task 1.1):
* `set continue-on-error` keeps the read loop running after a failing
* command (the session still exits non-zero). It is not a per-context
* setting, so it is handled here ahead of the key/value path. */
if ((argc == 2) && (strcmp(argv[1], "continue-on-error") == 0)) {
g_continue_on_error = 1;
return 0;
}
if (argc != 3) {
printf("set <key> <value>\n");
return -EINVAL;
@ -2520,14 +2589,12 @@ int main(int argc, char* argv[])
s = buf;
rc = execute_line(s);
if (rc < 0) {
SET_ERROR(-rc);
} else {
add_history(s);
}
rc = preprocess_and_run(s);
free(buf);
if (rc) {
break; /* abort-on-failure requested loop stop */
}
}
return 0;
return g_session_failed ? 1 : 0;
}