aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorblasty <peter@haxx.in>2026-09-29 13:55:30 +0200
committerblasty <peter@haxx.in>2026-09-29 13:55:30 +0200
commit432a8e5f57b65d38a2a377a54994dd6b73216742 (patch)
tree5e76ece8bbb9576b6ce3fe11074635073c115cea /tests
parentOffer a writable database location instead of failing the open (diff)
downloadida-tui-432a8e5f57b65d38a2a377a54994dd6b73216742.tar.gz
ida-tui-432a8e5f57b65d38a2a377a54994dd6b73216742.tar.xz
ida-tui-432a8e5f57b65d38a2a377a54994dd6b73216742.zip
Spawn TUI panes in slosh, the multiplexer we actually use
`pane spawn` knew tmux and zellij, so under slosh every entry point answered "error: not inside tmux or zellij" — the agent skill described a workflow that could not run. slosh is now the first thing autodetected ($SLOSH, then $ZELLIJ, then $TMUX), and a slosh pane id is a bare integer, so a registry row written before this commit still routes its own stop/capture/keys. Everything goes through the control socket, always the JSON form ($SLOSH_BIN -s $SLOSH_SESSION cmd): the bare-verb alias answers unwrapped, and a parser written for one shape silently finds nothing in the other. $SLOSH_BIN rather than `slosh` because a session may have been started from a build tree that is not on $PATH. Spawning is the one place slosh differs in kind. Its `split` verb only ever makes a shell pane, and typing a command into somebody's shell is the thing not to do — a pane that was *given* a command is the one with alive/exit_code to poll and `rerun` to repeat. So spawn applies a one-tab layout whose pane carries command= and a declared purpose=idatui:<hex>, finds it by that purpose (declared purposes are locked, so the TUI cannot relabel itself out from under us, and titles change anyway), then move-panes it into the tab we were called from: it lands beside the caller with its pty and scrollback intact, and the layout's now-empty tab removes itself. --detached restores focus afterwards, since slosh focuses what it creates and moves. The rest follows the zellij precedent. A dead command pane stays on screen as a husk, which _pane_alive must read as dead or a launcher that died on startup would burn the whole 300s readiness timeout instead of reporting "pane exited during startup". `capture` cuts the pane's content_* rect out of `snapshot` (which is the whole composited session) and hops tabs if the pane is parked in another one, because only the active tab is composed at all. `keys` keeps taking tmux-flavoured names and turns them into the bytes a terminal sends: it focuses the target, writes with `raw`, and restores focus — `send` would be decoded as session input first, where C-a is slosh's own leader and never reaches the TUI. --size stays tmux-only and now says so for whichever mux is in play. The two RPC integration tests gated on $TMUX/$ZELLIJ, so they skipped silently under slosh; they accept $SLOSH now. Verified against the live session, not just in unit checks: a probe pane spawns, reports alive, captures its own output, receives real keystrokes and dies on close; `pane spawn --open targets/echo` reaches ready:true with 128 functions, `drive where` answers, `pane keys Tab` flips listing to pseudocode on screen, and `pane stop` leaves an empty registry and no husk. Env inheritance is unchanged from zellij (a pane gets the session server's environment, not the caller's) — the probe printed PROBE_VAR=[].
Diffstat (limited to 'tests')
-rw-r--r--tests/test_rawimage_rpc.py6
-rw-r--r--tests/test_trace_rpc.py6
2 files changed, 6 insertions, 6 deletions
diff --git a/tests/test_rawimage_rpc.py b/tests/test_rawimage_rpc.py
index a6e7661..4e00b35 100644
--- a/tests/test_rawimage_rpc.py
+++ b/tests/test_rawimage_rpc.py
@@ -16,7 +16,7 @@ fall apart:
This test spawns a real pane on a real Thumb blob and checks all three.
-Requires: tmux or zellij, IDA (idalib). ~2min.
+Requires: slosh or tmux, IDA (idalib). ~2min.
~/ida-venv/bin/python tests/test_rawimage_rpc.py
"""
@@ -96,8 +96,8 @@ def stop_pane(sock, timeout=60):
def main() -> int:
- if not os.environ.get("TMUX") and not os.environ.get("ZELLIJ"):
- print("SKIP: not inside tmux or zellij (test spawns a pane)")
+ if not any(os.environ.get(v) for v in ("SLOSH", "TMUX", "ZELLIJ")):
+ print("SKIP: not inside slosh or tmux (test spawns a pane)")
return 0
if not os.path.exists(BLOB):
print(f"SKIP: no blob at {BLOB}")
diff --git a/tests/test_trace_rpc.py b/tests/test_trace_rpc.py
index 9b0f2e0..0baab22 100644
--- a/tests/test_trace_rpc.py
+++ b/tests/test_trace_rpc.py
@@ -7,7 +7,7 @@ every trace verb through the RPC socket, validating the JSON responses an agent
would see. It exercises the serialization, the settle/timeout machinery, and
the response shape that a driver depends on.
-Requires: tmux or zellij, IDA (idalib), and a trace. Records a fresh trace with the QEMU
+Requires: slosh or tmux, IDA (idalib), and a trace. Records a fresh trace with the QEMU
tracer if built; falls back to /tmp/echotrace.0.log if present; skips with a
message otherwise.
@@ -105,8 +105,8 @@ def stop_pane(sock, timeout=60):
def main() -> int:
global PASS, FAIL
- if not os.environ.get("TMUX") and not os.environ.get("ZELLIJ"):
- print(" skip: not inside tmux or zellij (test spawns a pane)")
+ if not any(os.environ.get(v) for v in ("SLOSH", "TMUX", "ZELLIJ")):
+ print(" skip: not inside slosh or tmux (test spawns a pane)")
return 0
with tempfile.TemporaryDirectory() as tmp: