summaryrefslogtreecommitdiff
path: root/test/selfmount.py
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-10-01 11:09:59 -0300
committerGabriel Schneider <[email protected]>2026-10-01 11:10:37 -0300
commit36a9bfbaba649da3d988608f1cc7834e567df95d (patch)
tree432831507023d906f3f5ad46969202c92232bf15 /test/selfmount.py
parentc5e5db988e59689b44feb42c59090c07687bcd42 (diff)
downloadpardes-36a9bfbaba649da3d988608f1cc7834e567df95d.tar.gz
pardes-36a9bfbaba649da3d988608f1cc7834e567df95d.zip
Every pane pardes spawns gets $PARDES_MOUNT, the session's own directory under 9ns --mntgen ($NINE_MOUNT/pardes/<name>), unset when it is not known
9ns says --mntgen with NINE_MNTGEN=1 (cloud9). Under `9ns --unix` the mount is the server it dialled, never this session (its socket does not exist until it starts), so it stays unset there; scripts fall back to `9p -a "unix!$PARDES_9P"`. Nothing is statted: the name comes from the session's socket and the environment. selfmount checks both modes. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'test/selfmount.py')
-rw-r--r--test/selfmount.py48
1 files changed, 48 insertions, 0 deletions
diff --git a/test/selfmount.py b/test/selfmount.py
index 8d78487d..0111e6ac 100644
--- a/test/selfmount.py
+++ b/test/selfmount.py
@@ -27,6 +27,46 @@ sys.path.insert(0, str(Path(__file__).resolve().parent))
from ninep import Client
+def unix_mount(ns, binary, served, env, name, fixture):
+ """A second editor under `9ns --unix <the first's socket>`, on the
+ fixture (a command runs from a file's pane, not a terminal's): what its
+ command pane sees in $PARDES_MOUNT."""
+ second = name + 'u'
+ sock = f'{os.environ["XDG_RUNTIME_DIR"]}/pardes-9p-{second}.sock'
+ out = Path(f'/tmp/{second}.mount')
+ env = dict(env, PARDES_DUMP=f'/tmp/{second}.dump.zon')
+ pid, master = pty.fork()
+ if pid == 0:
+ os.execve(ns, ['9ns', '--unix', served, '--', binary, '--tty', '--9p=' + second, str(fixture)], env)
+ fcntl.ioctl(master, termios.TIOCSWINSZ, struct.pack('HHHH', 30, 100, 0, 0))
+ os.set_blocking(master, False)
+ try:
+ deadline = time.monotonic() + 30
+ while time.monotonic() < deadline and not out.exists():
+ try:
+ os.read(master, 65536)
+ except OSError:
+ pass
+ if os.path.exists(sock) and not out.with_suffix('.sent').exists():
+ time.sleep(.3)
+ with Client(sock) as client:
+ client.write('/ctl', b'Shell sh\n')
+ client.write('/exec', f'echo "${{PARDES_MOUNT-unset}}" > {out}.tmp; mv {out}.tmp {out}\n'.encode())
+ out.with_suffix('.sent').touch()
+ time.sleep(.1)
+ return out.read_text().strip() if out.exists() else 'timeout'
+ finally:
+ os.kill(pid, signal.SIGTERM)
+ time.sleep(.2)
+ try:
+ os.kill(pid, signal.SIGKILL)
+ except ProcessLookupError:
+ pass
+ os.waitpid(pid, 0)
+ for path in (out, out.with_suffix('.sent'), Path(f'/tmp/{second}.dump.zon')):
+ path.unlink(missing_ok=True)
+
+
def run(binary):
ns = shutil.which('9ns') or str(Path.home() / '.local/bin/9ns')
runtime = os.environ.get('XDG_RUNTIME_DIR')
@@ -128,6 +168,14 @@ def run(binary):
return exits[-1].split()[2]
time.sleep(.1)
return 'timeout'
+ # A pane's command finds the session's own directory in
+ # $PARDES_MOUNT (9ns --mntgen says NINE_MNTGEN=1).
+ check(run(f'test "$PARDES_MOUNT" = {mount} && grep -q . "$PARDES_MOUNT/index"\n'.encode()) == '0',
+ '$PARDES_MOUNT is the session under the mntgen mount, and it answers')
+ # Under `9ns --unix` the mount is another server, never this
+ # session: a second editor started there leaves it unset.
+ seen_mount = unix_mount(ns, binary, sock, env, name, fixture)
+ check(seen_mount == 'unset', f'under 9ns --unix $PARDES_MOUNT is unset ({seen_mount!r})')
# Followed from before the burst: a fresh open of the log reads
# only what its 64 KiB ring still holds, which a burst this size
# outgrows, and a follower the ring outruns reads `lost N`, so