0e9ae602
refactor(test): one owner for the agent suite's daemon bring-up
a73x 2026-08-13 21:17
Commit message
test/agent.sh
| Old | New | ||
|---|---|---|---|
| @@ -222,6 +222,32 @@ wait_ready() { | |||
| 222 | return 1 | 222 | return 1 |
| 223 | } | 223 | } |
| 224 | 224 | ||
| 225 | # start_ready PIDVAR LOG SOCK ARGS... — bring a daemon up and wait for it to | ||
| 226 | # answer, storing its pid in the named variable and calling `why` with the | ||
| 227 | # whole story if either half fails. The bring-up is identical in every scenario | ||
| 228 | # that needs a plain daemon, and a scenario that got only PART of it right — a | ||
| 229 | # pid but no readiness wait — would fail later, somewhere else, as a flake. | ||
| 230 | # | ||
| 231 | # PIDVAR is set the INSTANT the pid is known, before the readiness wait and | ||
| 232 | # whatever that wait decides. That ordering is the load-bearing part: a daemon | ||
| 233 | # that came up and then never answered is still a daemon this run started, and | ||
| 234 | # a version that only assigned on success would leave it running past cleanup. | ||
| 235 | # | ||
| 236 | # The two scenarios that do NOT use this (the TUI and the QUIC tear) want a | ||
| 237 | # daemon that failed to come up to be a stashed message rather than an | ||
| 238 | # immediate return, and folding that in would cost more than it saves. | ||
| 239 | start_ready() { | ||
| 240 | _var="$1" | ||
| 241 | _log="$2" | ||
| 242 | _sock="$3" | ||
| 243 | shift 3 | ||
| 244 | eval "$_var=\$(start_daemon \"\$_log\" \"\$@\")" | ||
| 245 | eval "_pid=\$$_var" | ||
| 246 | [ -n "$_pid" ] || why "daemon never printed an up-line [$(cat "$_log")]" || return 1 | ||
| 247 | wait_ready "$_sock" || why "daemon never answered on $_sock" || return 1 | ||
| 248 | return 0 | ||
| 249 | } | ||
| 250 | |||
| 225 | now_ms() { python3 -c 'import time; print(int(time.time() * 1000))'; } | 251 | now_ms() { python3 -c 'import time; print(int(time.time() * 1000))'; } |
| 226 | 252 | ||
| 227 | echo "agent: ports ${PORT_TEAR}/${PORT_RELAY}/${PORT_QUIET}/${PORT_SINK}, tmp $TMP" | 253 | echo "agent: ports ${PORT_TEAR}/${PORT_RELAY}/${PORT_QUIET}/${PORT_SINK}, tmp $TMP" |
| @@ -232,9 +258,7 @@ echo "agent: ports ${PORT_TEAR}/${PORT_RELAY}/${PORT_QUIET}/${PORT_SINK}, tmp $T | |||
| 232 | # in `exit_code` the command's rather than a guess. | 258 | # in `exit_code` the command's rather than a guess. |
| 233 | scen_marks() { | 259 | scen_marks() { |
| 234 | [ -x /bin/bash ] || { WHY="no /bin/bash to inject marks into"; return 2; } | 260 | [ -x /bin/bash ] || { WHY="no /bin/bash to inject marks into"; return 2; } |
| 235 | D_MARKS=$(start_daemon "$TMP/marks.log" --sock "$SOCK_MARKS" --shell /bin/bash) | 261 | start_ready D_MARKS "$TMP/marks.log" "$SOCK_MARKS" --sock "$SOCK_MARKS" --shell /bin/bash || return 1 |
| 236 | [ -n "$D_MARKS" ] || why "daemon never printed an up-line [$(cat "$TMP/marks.log")]" || return 1 | ||
| 237 | wait_ready "$SOCK_MARKS" || why "daemon never answered on $SOCK_MARKS" || return 1 | ||
| 238 | 262 | ||
| 239 | timeout 20 "$MUXA" run --sock "$SOCK_MARKS" --timeout 8000 'true' >"$TMP/m1" 2>&1 | 263 | timeout 20 "$MUXA" run --sock "$SOCK_MARKS" --timeout 8000 'true' >"$TMP/m1" 2>&1 |
| 240 | _rc=$? | 264 | _rc=$? |
| @@ -399,9 +423,7 @@ run_scenario "ephemeral TUI: alt_screen seen, quit driven, death reported as JSO | |||
| 399 | # question a markless session can answer two different ways, and "I don't | 423 | # question a markless session can answer two different ways, and "I don't |
| 400 | # know" is not one of them. | 424 | # know" is not one of them. |
| 401 | scen_settle() { | 425 | scen_settle() { |
| 402 | D_SETTLE=$(start_daemon "$TMP/settle.log" --sock "$SOCK_SETTLE" --shell /bin/sh) | 426 | start_ready D_SETTLE "$TMP/settle.log" "$SOCK_SETTLE" --sock "$SOCK_SETTLE" --shell /bin/sh || return 1 |
| 403 | [ -n "$D_SETTLE" ] || why "daemon never printed an up-line [$(cat "$TMP/settle.log")]" || return 1 | ||
| 404 | wait_ready "$SOCK_SETTLE" || why "daemon never answered on $SOCK_SETTLE" || return 1 | ||
| 405 | 427 | ||
| 406 | timeout 20 "$MUXA" run --sock "$SOCK_SETTLE" --settle 300 --timeout 10000 'sleep 1' >"$TMP/s1" 2>&1 | 428 | timeout 20 "$MUXA" run --sock "$SOCK_SETTLE" --settle 300 --timeout 10000 'sleep 1' >"$TMP/s1" 2>&1 |
| 407 | _rc=$? | 429 | _rc=$? |
| @@ -622,10 +644,8 @@ run_scenario "quic: a tear with no path back fails with the whole story" scen_te | |||
| 622 | # happened, and the honest answer (still running) would have been one field. | 644 | # happened, and the honest answer (still running) would have been one field. |
| 623 | scen_keepalive() { | 645 | scen_keepalive() { |
| 624 | quic_gate || return $? | 646 | quic_gate || return $? |
| 625 | D_QUIET=$(start_daemon "$TMP/quiet.log" --sock "$SOCK_QUIET" --shell /bin/bash \ | 647 | start_ready D_QUIET "$TMP/quiet.log" "$SOCK_QUIET" --sock "$SOCK_QUIET" --shell /bin/bash \ |
| 626 | --quic "127.0.0.1:$PORT_QUIET" --key "$KEY") | 648 | --quic "127.0.0.1:$PORT_QUIET" --key "$KEY" || return 1 |
| 627 | [ -n "$D_QUIET" ] || why "daemon never printed an up-line [$(cat "$TMP/quiet.log")]" || return 1 | ||
| 628 | wait_ready "$SOCK_QUIET" || why "daemon never answered on $SOCK_QUIET" || return 1 | ||
| 629 | 649 | ||
| 630 | timeout 40 "$MUXA" await --quic "127.0.0.1:$PORT_QUIET" --key "$KEY" --timeout 20000 >"$TMP/q3" 2>&1 | 650 | timeout 40 "$MUXA" await --quic "127.0.0.1:$PORT_QUIET" --key "$KEY" --timeout 20000 >"$TMP/q3" 2>&1 |
| 631 | _rc=$? | 651 | _rc=$? |