test(xce-test-cli-ux): build reusable pty-driven black-box CLI harness

clitest_spawn/send_line/send_partial/send_tab/send_signal/wait_for_text/
wait_for_exit/kill_and_reap launch the real compiled xce_test behind a
genuine pty (so isatty/g_interactive/libedit behave as a real terminal),
with stderr routed to a separate pipe for real stream-separation testing.
All waits are poll()-bounded with an explicit timeout so a future
regression can't hang the whole test suite. This is the shared
infrastructure tasks 2.3, 3.5, and all of Validation phase (4.1-4.4)
will build their black-box scenarios on top of. One smoke test proves
launch/send/capture/exit-code/stream-separation end to end.
1290/1290 controller suite passing (+1).

Task 1.7 of .kiro/specs/xce-test-cli-ux/tasks.md.
Foundation phase (1.1-1.7) now complete.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019jaMf9QEwpugH2W9KAuc7f
This commit is contained in:
Rongsong Shen 2026-09-09 11:06:31 +00:00
parent b70228c558
commit 4d1f247674
No known key found for this signature in database
GPG key ID: 5BCDAAE0123E9FE2
5 changed files with 593 additions and 2 deletions

View file

@ -16,6 +16,12 @@
* pty-driven black-box CLI harness that task 1.7 builds separately (that
* one will live in test_test_cli.c and is needed for interactive-only
* surfaces like tab completion that a plain pipe can't exercise).
*
* resolve_xce_test_path() below is deliberately non-static (task 1.7):
* test_test_cli.c's pty-driven harness needs the exact same "find the real
* built xce_test binary next to this test binary" logic and reuses this
* copy via an `extern` declaration rather than duplicating it -- see this
* project's own consolidation-over-copy-paste convention.
*/
#define _GNU_SOURCE
#include <fcntl.h>
@ -38,7 +44,7 @@
* and `controller_unit_test` into the same target dir) -- resolving via
* /proc/self/exe's directory avoids depending on the caller's cwd or an
* env var that could go stale. */
static int resolve_xce_test_path(char* out, size_t outsz)
int resolve_xce_test_path(char* out, size_t outsz)
{
char self[PATH_MAX];
ssize_t n;