summaryrefslogtreecommitdiff
path: root/test/fs.py
diff options
context:
space:
mode:
Diffstat (limited to 'test/fs.py')
-rw-r--r--test/fs.py367
1 files changed, 222 insertions, 145 deletions
diff --git a/test/fs.py b/test/fs.py
index 2ffd5098..819a78d6 100644
--- a/test/fs.py
+++ b/test/fs.py
@@ -72,7 +72,7 @@ def session(binary, root, name, *options, socket_name=None, file=None, tty=False
time.sleep(.005)
with Client(address) as client:
if network is not None:
- for dial in client.read('/self/listeners').decode().splitlines():
+ for dial in client.read('/listeners').decode().splitlines():
parts = dial.split('!')
if parts[0] in ['tcp', 'quic']:
assert len(parts) == 3 and 0 < int(parts[2]) < 65536, dial
@@ -101,60 +101,136 @@ def session(binary, root, name, *options, socket_name=None, file=None, tty=False
def new_pane(client, contents):
- serial = int(client.read('/self/new/ctl').split()[0])
- client.write(f'/self/pane/{serial}/body', contents)
+ serial = int(client.read('/new').split()[0])
+ if contents:
+ client.write(f'/pane/{serial}/body', contents)
return serial
def look(client, path, source=None):
+ """A right click on `path` from a pane (a fresh scratch by default)."""
serial = source if source is not None else new_pane(client, b'')
- client.write(f'/self/pane/{serial}/body', path.encode(), truncate=True)
- client.write(f'/self/pane/{serial}/event', f'ML0 {len(path.encode())}\n'.encode())
- rows = client.read('/self/index').splitlines()
- opened = int(rows[-1].split()[0])
- assert opened != serial, f'Look did not open {path}'
- return opened
+ client.write(f'/pane/{serial}/ctl', f'look {path}\n'.encode())
+ results = [int(row) for row in client.read('/ctl').split()]
+ assert len(results) == 1 and results[0] != serial, (path, results)
+ return results[0]
def execute(client, serial, command):
- text = command.encode()
- client.write(f'/self/pane/{serial}/body', text, truncate=True)
- client.write(f'/self/pane/{serial}/event', f'MX0 {len(text)}\n'.encode())
+ """A middle click on `command` from a pane."""
+ client.write(f'/pane/{serial}/ctl', f'exec {command}\n'.encode())
-def discovery(binary):
+def walk_tree(client, path='/', skip=('/new', '/log', '/os', '/screen')):
+ """Stat every entry below `path`, as `find` does, without opening anything."""
+ seen = []
+ for name in client.list(path):
+ child = (path.rstrip('/') + '/' + name)
+ info = client.stat(child)
+ seen.append((child, info))
+ if info['dir'] and child not in skip:
+ seen.extend(walk_tree(client, child, skip))
+ return seen
+
+
+def discovery(binary, embedded=False):
with tempfile.TemporaryDirectory(prefix='pardes-discovery-') as directory:
- with session(binary, Path(directory), 'discovery') as (client, _):
- before = client.read('/self/index')
- entries = client.list('/self/new')
- assert {'README', 'ctl', 'body', 'addr', 'data', 'event'} <= set(entries)
- guide = client.read('/self/README')
- assert guide == client.read('/self/new/README')
- assert b'Each open creates a separate pane' in guide
- # Walk and stat each entry, as a filesystem browser does, without open.
- from ninep import string
- for name in entries:
- client.fid += 1
- fid = client.fid
- client.rpc(110, struct.pack('<IIH', 1, fid, 3) +
- string('self') + string('new') + string(name))
+ root = Path(directory)
+ with session(binary, root, 'discovery') as (client, _):
+ top = client.list('/')
+ assert top[:9] == ['README', 'index', 'ctl', 'new', 'log', 'screen', 'listeners', 'pane', 'os'], top
+ assert 'self' not in top and 'cons' not in top, top
+ assert ('src' in top) == embedded, (top, embedded)
+ before = client.read('/index')
+ guide = client.read('/README')
+ assert guide.count(b'\n') <= 45 and b'exec Msg' in guide and b'/new' in guide, guide
+ assert client.stat('/README')['length'] == len(guide)
+ # ls/stat/find over the whole tree, without opening, creates nothing.
+ seen = walk_tree(client)
+ names = {path for path, _ in seen}
+ assert {'/index', '/ctl', '/new', '/log', '/pane/1', '/pane/1/body', '/pane/1/name',
+ '/pane/1/sel', '/pane/1/ctl', '/pane/1/tag', '/pane/1/event'} <= names, sorted(names)
+ assert '/pane/1/pty' not in names, 'the fixture file pane grew a pty/'
+ assert not any(name.startswith('/self') or name.endswith('/rdsel') or name.endswith('/wrsel')
+ for name in names), sorted(names)
+ for path, info in seen:
+ assert info['mode'] in (0o755, 0o644, 0o666, 0o444, 0o222, 0o555), (path, info)
+ assert info['mtime'] > 0, (path, info)
+ assert client.read('/index') == before, 'browsing created a pane'
+ assert client.stat('/index')['length'] == len(before) > 0
+ index = client.stat('/index')
+ assert index['mode'] == 0o444 and client.stat('/ctl')['mode'] == 0o666
+ assert client.stat('/pane/1/body')['mode'] == 0o666 and client.stat('/pane')['mode'] == 0o755
+ fixture = int(before.split()[0])
+ assert before.split()[1:3] == [b'text', b'0'] and before.endswith(b'/discovery.txt\n'), before
+ # Before any command, /ctl reports the editor.
+ status = dict(line.split(maxsplit=1) for line in client.read('/ctl').decode().splitlines())
+ assert int(status['pid']) > 0 and status['version'] and int(status['panes']) == 1, status
+ # /new: one pane per open, its serial is the file's content.
+ log = client.open('/log')
+ first = int(client.read('/new').split()[0])
+ second = int(client.read('/new').split()[0])
+ assert first != second and first != fixture, (first, second)
+ assert client.read_fid(log) == f'new {first} {root}/+New\n'.encode()
+ assert client.read_fid(log) == f'new {second} {root}/+New\n'.encode()
+ assert set(client.list('/pane')) == {str(fixture), str(first), str(second)}
+ client.write(f'/pane/{first}/body', b'first pane', truncate=True)
+ assert client.read(f'/pane/{first}/body') == b'first pane'
+ assert client.read(f'/pane/{second}/body') == b''
+ assert client.stat(f'/pane/{first}/body')['length'] == len(b'first pane')
+ rows = {int(row.split()[0]): row.split() for row in client.read('/index').splitlines()}
+ assert rows[first][1:3] == [b'text', b'1'] and rows[second][1:3] == [b'text', b'0'], rows
+ # name: read the file name, write to rename; sel: the selection.
+ assert client.read(f'/pane/{first}/name') == f'{root}/+New\n'.encode()
+ client.write(f'/pane/{first}/name', b'notes.txt\n')
+ assert client.read(f'/pane/{first}/name') == f'{root}/notes.txt\n'.encode()
+ assert client.read_fid(log) == f'rename {first} {root}/notes.txt\n'.encode()
+ assert client.stat(f'/pane/{first}/name')['length'] == len(f'{root}/notes.txt\n')
+ client.write(f'/pane/{first}/addr', b'#0,#5')
+ client.write(f'/pane/{first}/ctl', b'dot=addr\n')
+ assert client.read(f'/pane/{first}/sel') == b'first'
+ assert client.stat(f'/pane/{first}/sel')['length'] == 5
+ client.write(f'/pane/{first}/sel', b'FIRST')
+ assert client.read(f'/pane/{first}/body') == b'FIRST pane'
+ assert client.read(f'/pane/{first}/sel') == b''
+ # exec Msg shows text; exec Save writes the named file; exec Del closes.
+ client.write(f'/pane/{first}/ctl', b'exec Msg hello from 9P\n')
+ assert 'hello from 9P' in ''.join(cell[0] for cell in client.screen()['cells'])
+ client.write(f'/pane/{first}/ctl', b'exec Save\n')
+ assert (root / 'notes.txt').read_bytes() == b'FIRST pane'
+ assert client.read_fid(log) == f'save {first} {root}/notes.txt\n'.encode()
+ assert client.read('/ctl') == f'{first}\n'.encode()
+ client.write('/ctl', b'exec Del\n')
+ assert client.read_fid(log) == f'del {second} {root}/+New\n'.encode()
+ assert str(second) not in client.list('/pane')
+ # look through /ctl opens a file; the serial reads back.
+ (root / 'opened.txt').write_bytes(b'one\ntwo\nthree\n')
+ client.write('/ctl', f'look {root}/opened.txt:2\n'.encode())
+ opened = int(client.read('/ctl'))
+ assert opened not in (fixture, first, second), opened
+ assert client.read(f'/pane/{opened}/body') == b'one\ntwo\nthree\n'
+ assert client.read(f'/pane/{opened}/name') == f'{root}/opened.txt\n'.encode()
+ assert client.read_fid(log) == f'new {opened} {root}/opened.txt\n'.encode()
+ client.write(f'/pane/{first}/ctl', f'look {root}/opened.txt:3\n'.encode())
+ assert client.read('/ctl') == f'{opened}\n'.encode(), 'a repeated look targets the open pane'
+ assert set(client.list('/pane')) == {str(fixture), str(first), str(opened)}
+ # Writing an event record back still performs the action it names.
+ client.write(f'/pane/{first}/body', b'Msg via event', truncate=True)
+ client.write(f'/pane/{first}/event', b'FX0 13\n')
+ assert 'via event' in ''.join(cell[0] for cell in client.screen()['cells'])
+ for bad in [b'Look x\n', b'Exec Msg x\n', b'put\n', b'name x\n', b'del\n']:
try:
- client.rpc(124, struct.pack('<I', fid))
- finally:
- client.close(fid)
- assert client.read('/self/index') == before, 'browsing created a pane'
- first = int(client.read('/self/new/ctl').split()[0])
- second = int(client.read('/self/new/ctl').split()[0])
- assert first != second
- client.write(f'/self/pane/{first}/body', b'first pane', truncate=True)
- assert client.read(f'/self/pane/{first}/body') == b'first pane'
- assert client.read(f'/self/pane/{second}/body') == b''
- before_ids = set(client.list('/self/pane'))
- client.write('/self/new/body', b'created with text', truncate=True)
- made = set(client.list('/self/pane')) - before_ids
- assert len(made) == 1
- assert client.read('/self/pane/' + made.pop() + '/body') == b'created with text'
- print('9P discovery: listing/stat/README are inert; opens create independent panes')
+ client.write('/ctl', bad)
+ except OSError:
+ pass
+ else:
+ raise AssertionError(f'{bad!r} was accepted')
+ client.close(log)
+ if embedded:
+ assert client.read('/src/pardes.zig').startswith(b'const std')
+ assert client.stat('/src/pardes.zig')['mode'] == 0o444
+ assert b'pub const Pardes' in client.read(f'/pane/{look(client, "/virtual/src/pardes.zig")}/body')
+ print('9P discovery: listing/stat/find are inert; new, ctl, name, sel and log behave')
def test(binary, quic=False):
@@ -188,14 +264,14 @@ def test(binary, quic=False):
with session(binary, root, 'renamed', '--9p=explicit', socket_name='explicit') as (named, named_address):
assert named_address.name == 'pardes-9p-explicit.sock'
assert not (root / 'pardes-9p-renamed.sock').exists()
- assert named.read('/self/pane/1/body') == b'initial\n'
+ assert named.read('/pane/1/body') == b'initial\n'
with session(binary, root, 'first') as (client, address):
- assert set(client.list('/')) == {'os', 'self'}
- assert {'pane', 'index', 'new'} <= set(client.list('/self'))
- assert client.read('/self/pane/1/body') == b'initial\n'
+ assert {'pane', 'index', 'new', 'ctl', 'log', 'os'} <= set(client.list('/'))
+ assert 'self' not in client.list('/')
+ assert client.read('/pane/1/body') == b'initial\n'
assert client.read('/os' + str(root / 'first.txt')) == b'initial\n'
assert 'first.txt' in client.list('/os' + str(root))
- assert client.read('/self/pane/1/../1/body') == b'initial\n'
+ assert client.read('/pane/1/../1/body') == b'initial\n'
assert client.read('/os' + str(root) + '/../' + root.name + '/first.txt') == b'initial\n'
listing = root / 'listing'
@@ -207,9 +283,9 @@ def test(binary, quic=False):
assert set(small.list('/os' + str(listing))) == {
f'entry-{number:02}' for number in range(24)}
- frozen = client.open('/self/screen')
+ frozen = client.open('/screen')
before = bytearray(client.read_fid(frozen, count=31))
- client.write('/self/pane/1/body', b'screen changed\n')
+ client.write('/pane/1/body', b'screen changed\n')
while chunk := client.read_fid(frozen, len(before)):
before.extend(chunk)
client.close(frozen)
@@ -220,12 +296,12 @@ def test(binary, quic=False):
payload = ('const value = "λ";\n' * 3000).encode()
serial = new_pane(client, payload)
- body = f'/self/pane/{serial}/body'
+ body = f'/pane/{serial}/body'
assert client.read(body) == payload
client.write(body, b'replaced\n', truncate=True)
assert client.read(body) == b'replaced\n'
- event = client.open(f'/self/pane/{serial}/event')
+ event = client.open(f'/pane/{serial}/event')
client.write(body, b'event\n')
record = client.read_fid(event)
assert record.startswith(b'EI') and b'event\n' in record, record
@@ -242,82 +318,83 @@ def test(binary, quic=False):
missing = False
try:
- client.read('/self/pane/4294967295/body')
+ client.read('/pane/4294967295/body')
except OSError:
missing = True
assert missing
assert client.read(body) == b'replaced\nevent\n'
- source = look(client, '/virtual/src/pardes.zig')
- assert b'pub const Pardes' in client.read(f'/self/pane/{source}/body')
+ if 'src' in client.list('/'):
+ source = look(client, '/virtual/src/pardes.zig')
+ assert b'pub const Pardes' in client.read(f'/pane/{source}/body')
(root / 'index').write_bytes(b'OS takes precedence\n')
opened = look(client, 'index')
- assert client.read(f'/self/pane/{opened}/body') == b'OS takes precedence\n'
+ assert client.read(f'/pane/{opened}/body') == b'OS takes precedence\n'
opened = look(client, '/n/self/index')
- index = client.read(f'/self/pane/{opened}/body')
+ index = client.read(f'/pane/{opened}/body')
assert index.split()[0] == b'1' and b'first.txt' in index, index
(root / 'explicit.txt').write_bytes(b'explicit OS mount\n')
opened = look(client, '/n/os' + str(root / 'explicit.txt'))
- assert client.read(f'/self/pane/{opened}/body') == b'explicit OS mount\n'
+ assert client.read(f'/pane/{opened}/body') == b'explicit OS mount\n'
own = root / 'pardes-9p-second.sock'
with session(binary, root, 'second', '--mount=peer=' + str(address),
'--mount=own=' + str(own)) as (remote, _):
- opened = look(remote, '/n/own/self/pane/1/body')
- assert remote.read(f'/self/pane/{opened}/body') == b'initial\n'
- opened = look(remote, '/n/peer/self/pane/' + str(serial) + '/body')
- assert remote.read(f'/self/pane/{opened}/body') == b'replaced\nevent\n'
- remote.write(f'/self/pane/{opened}/body', b'saved to peer\n', truncate=True)
- remote.write(f'/self/pane/{opened}/ctl', b'put\n')
+ opened = look(remote, '/n/own/pane/1/body')
+ assert remote.read(f'/pane/{opened}/body') == b'initial\n'
+ opened = look(remote, '/n/peer/pane/' + str(serial) + '/body')
+ assert remote.read(f'/pane/{opened}/body') == b'replaced\nevent\n'
+ remote.write(f'/pane/{opened}/body', b'saved to peer\n', truncate=True)
+ remote.write(f'/pane/{opened}/ctl', b'exec Save\n')
assert client.read(body) == b'saved to peer\n'
large = b'mounted file contents\n' * 60000
large_path = root / 'large.txt'
large_path.write_bytes(large)
opened = look(remote, '/n/peer/os' + str(large_path))
- assert remote.read(f'/self/pane/{opened}/body') == large
+ assert remote.read(f'/pane/{opened}/body') == large
edited = large[:-3] + b'edited\n'
- remote.write(f'/self/pane/{opened}/body', edited, truncate=True)
- remote.write(f'/self/pane/{opened}/ctl', b'put\n')
+ remote.write(f'/pane/{opened}/body', edited, truncate=True)
+ remote.write(f'/pane/{opened}/ctl', b'exec Save\n')
assert large_path.read_bytes() == edited
assert client.read('/os' + str(large_path)) == edited
with session(binary, root, 'runtime') as (remote, own_address):
control = new_pane(remote, b'')
execute(remote, control, 'Mount peer ' + str(address))
- opened = look(remote, '/n/peer/self/pane/1/body', source=control)
- assert remote.read(f'/self/pane/{opened}/body') == client.read('/self/pane/1/body')
+ opened = look(remote, '/n/peer/pane/1/body', source=control)
+ assert remote.read(f'/pane/{opened}/body') == client.read('/pane/1/body')
execute(remote, control, 'Mount peer ' + str(own_address))
execute(remote, control, 'Unmount peer')
- remote.write(f'/self/pane/{opened}/body', b'runtime mounted Save\n', truncate=True)
- remote.write(f'/self/pane/{opened}/ctl', b'put\n')
- assert client.read('/self/pane/1/body') == b'runtime mounted Save\n'
- assert remote.read('/self/pane/1/body') == b'initial\n'
+ remote.write(f'/pane/{opened}/body', b'runtime mounted Save\n', truncate=True)
+ remote.write(f'/pane/{opened}/ctl', b'exec Save\n')
+ assert client.read('/pane/1/body') == b'runtime mounted Save\n'
+ assert remote.read('/pane/1/body') == b'initial\n'
roots = look(remote, '/n', source=control)
- assert b'/n/peer/\n' in remote.read(f'/self/pane/{roots}/body')
- remote.write(f'/self/pane/{opened}/ctl', b'delete\n')
+ assert b'/n/peer/\n' in remote.read(f'/pane/{roots}/body')
+ remote.write(f'/pane/{opened}/ctl', b'exec Del\n')
execute(remote, control, 'Unmount peer')
- remote.write(f'/self/pane/{roots}/ctl', b'get\n')
- assert remote.read(f'/self/pane/{roots}/body') == b'/n/os/\n/n/self/\n'
+ remote.write(f'/pane/{roots}/ctl', b'get\n')
+ assert remote.read(f'/pane/{roots}/body') == b'/n/os/\n/n/self/\n'
execute(remote, control, 'Mount peer ' + str(own_address))
- opened = look(remote, '/n/peer/self/pane/1/body', source=control)
- assert remote.read(f'/self/pane/{opened}/body') == b'initial\n'
+ opened = look(remote, '/n/peer/pane/1/body', source=control)
+ assert remote.read(f'/pane/{opened}/body') == b'initial\n'
with session(binary, root, 'mounted-startup', '--mount=peer=' + str(address),
- file='/n/peer/self/pane/1/body:1') as (remote, _):
- assert remote.read('/self/pane/1/body') == b'runtime mounted Save\n'
+ file='/n/peer/pane/1/body:1') as (remote, _):
+ assert remote.read('/pane/1/body') == b'runtime mounted Save\n'
- client.write(f'/self/pane/{serial}/ctl', b'delete\n')
- assert str(serial) not in client.list('/self/pane')
+ client.write(f'/pane/{serial}/ctl', b'exec Del\n')
+ assert str(serial) not in client.list('/pane')
for tty in [False, True]:
name = 'restore tty space' if tty else 'restore detached space'
with session(binary, root, name, tty=tty) as (old, address):
- old.write('/self/pane/1/body', b'dumped state\n', truncate=True)
+ old.write('/pane/1/body', b'dumped state\n', truncate=True)
control = new_pane(old, b'')
execute(old, control, 'Restore ' + str(root / 'missing dump.zon'))
- assert old.read('/self/pane/1/body') == b'dumped state\n'
+ assert old.read('/pane/1/body') == b'dumped state\n'
execute(old, control, 'Mount own ' + str(address))
execute(old, control, 'Dump')
saved = root / (name + '.dump.zon')
@@ -325,12 +402,12 @@ def test(binary, quic=False):
while not saved.exists():
assert time.monotonic() < deadline, 'Dump did not write its state'
time.sleep(.005)
- held_body = old.open('/self/pane/1/body')
- held_screen = old.open('/self/screen')
- old_ids = {int(row.split()[0]) for row in old.read('/self/index').splitlines()}
+ held_body = old.open('/pane/1/body')
+ held_screen = old.open('/screen')
+ old_ids = {int(row.split()[0]) for row in old.read('/index').splitlines()}
assert old.read_fid(held_body) == b'dumped state\n'
assert old.read_fid(held_screen, count=1) == b'{'
- old.write('/self/pane/1/body', b'changed after dump\n', truncate=True)
+ old.write('/pane/1/body', b'changed after dump\n', truncate=True)
try:
execute(old, control, 'Restore ' + str(saved))
except (EOFError, ConnectionResetError, BrokenPipeError):
@@ -342,15 +419,15 @@ def test(binary, quic=False):
else:
raise AssertionError('Restore left an old body fid usable')
with Client(address) as restored:
- restored_ids = [int(row.split()[0]) for row in restored.read('/self/index').splitlines()]
+ restored_ids = [int(row.split()[0]) for row in restored.read('/index').splitlines()]
assert len(restored_ids) == 2 and old_ids.isdisjoint(restored_ids), restored_ids
file_id, control_id = restored_ids
- contents = restored.read(f'/self/pane/{file_id}/body')
- assert contents == b'dumped state\n', (contents, saved.read_text(), restored.read('/self/index'))
- assert restored.read(f'/self/pane/{control_id}/body') == b'Dump'
+ contents = restored.read(f'/pane/{file_id}/body')
+ assert contents == b'dumped state\n', (contents, saved.read_text(), restored.read('/index'))
+ assert restored.read(f'/pane/{control_id}/body') == b'', 'commands ran through ctl, not the body'
assert restored.screen()['cols'] == 80
opened = look(restored, '/n/own/os' + str(root / (name + '.txt')), source=control_id)
- assert restored.read(f'/self/pane/{opened}/body') == b'initial\n'
+ assert restored.read(f'/pane/{opened}/body') == b'initial\n'
with session(binary, root, 'forwarding') as (client, address):
child_dir = root / 'child-working-directory'
@@ -362,25 +439,25 @@ def test(binary, quic=False):
for word, expected, selected, reuse in [('space name.txt:2:4', spaced.read_bytes(), [14, 14], False),
('/n/self/pane/1/body', b'initial\n', None, False),
('/virtual/pane/1/body:1:2-4', b'initial\n', [1, 4], True)]:
- before = {int(row.split()[0]) for row in client.read('/self/index').splitlines()}
+ before = {int(row.split()[0]) for row in client.read('/index').splitlines()}
result = subprocess.run([binary, '--tty', word], cwd=child_dir, env=env,
capture_output=True, timeout=3)
assert result.returncode == 0, (word, result.stderr)
- after = {int(row.split()[0]) for row in client.read('/self/index').splitlines()}
+ after = {int(row.split()[0]) for row in client.read('/index').splitlines()}
if reuse:
assert after == before
else:
opened, = after - before
- assert client.read(f'/self/pane/{opened}/body') == expected
- assert client.read('/self/pane/1/body') == b'initial\n'
+ assert client.read(f'/pane/{opened}/body') == expected
+ assert client.read('/pane/1/body') == b'initial\n'
if selected is not None:
- addr = client.open(f'/self/pane/{opened}/addr')
- client.write(f'/self/pane/{opened}/ctl', b'addr=dot\n')
+ addr = client.open(f'/pane/{opened}/addr')
+ client.write(f'/pane/{opened}/ctl', b'addr=dot\n')
actual = list(map(int, client.read_fid(addr).split()))
client.close(addr)
assert actual == selected, (word, actual, selected)
- addr = client.open('/self/pane/1/addr', 2)
- ctl = client.open('/self/pane/1/ctl', 1)
+ addr = client.open('/pane/1/addr', 2)
+ ctl = client.open('/pane/1/ctl', 1)
for fid, text in [(addr, b'#0,#3'), (ctl, b'limit=addr\n'), (addr, b'#0')]:
client.rpc(118, struct.pack('<IQI', fid, 0, len(text)) + text)
try:
@@ -398,7 +475,7 @@ def test(binary, quic=False):
finally:
client.close(addr)
client.close(ctl)
- client.read('/self/pane/1/ctl')
+ client.read('/pane/1/ctl')
control = new_pane(client, b'')
execute(client, control, 'Dump')
@@ -407,10 +484,10 @@ def test(binary, quic=False):
while not saved.exists():
assert time.monotonic() < deadline, 'forwarding fixture Dump did not finish'
time.sleep(.005)
- before = client.read('/self/index')
+ before = client.read('/index')
inherited = {key: env[key] for key in ['PARDES_9P', 'PARDES_PANE', 'PARDES_FORWARD_LOOK']}
cases = [
- ('mount', ['--mount=peer=' + str(address), '/n/peer/self/pane/1/body'], None),
+ ('mount', ['--mount=peer=' + str(address), '/n/peer/pane/1/body'], None),
('name', ['--9p=forwarded-name'], 'forwarded-name'),
('tcp', ['--9p-tcp=tcp!127.0.0.1!0'], None),
('load', ['-l', str(saved)], None),
@@ -425,19 +502,19 @@ def test(binary, quic=False):
launch=[*([] if name == 'shells' else ['--tty']), *options],
inherited=inherited) as (local, local_address):
assert local_address != address
- index = local.read('/self/index').splitlines()
+ index = local.read('/index').splitlines()
if name == 'mount':
assert len(index) == 1 and b'/n/peer/' in index[0], index
- assert local.read('/self/pane/1/body') == b'initial\n'
+ assert local.read('/pane/1/body') == b'initial\n'
elif name == 'load':
- assert local.read('/self/index') == before
- assert local.read('/self/pane/1/body') == b'initial\n'
+ assert local.read('/index') == before
+ assert local.read('/pane/1/body') == b'initial\n'
else:
assert len(index) == (3 if name == 'shells' else 1), index
if name in ['tcp', 'quic']:
- assert (name + '!127.0.0.1!').encode() in local.read('/self/listeners')
- assert client.read('/self/index') == before
- assert client.read('/self/pane/1/body') == b'initial\n'
+ assert (name + '!127.0.0.1!').encode() in local.read('/listeners')
+ assert client.read('/index') == before
+ assert client.read('/pane/1/body') == b'initial\n'
for name, identity, word in [
('stale-file', dict(inherited, PARDES_9P=str(root / 'absent.sock')), str(spaced)),
@@ -450,11 +527,11 @@ def test(binary, quic=False):
launch=['--tty', *([word] if word else [])]) as (local, local_address):
assert local_address != address
if word == str(spaced):
- assert local.read('/self/pane/1/body') == spaced.read_bytes()
+ assert local.read('/pane/1/body') == spaced.read_bytes()
elif word:
- assert word.encode() in local.read('/self/index') or word in ''.join(
+ assert word.encode() in local.read('/index') or word in ''.join(
cell[0] for cell in local.screen()['cells'])
- assert client.read('/self/index') == before
+ assert client.read('/index') == before
for tty in [False, True]:
name = 'lsp-tty' if tty else 'lsp-detached'
@@ -463,23 +540,23 @@ def test(binary, quic=False):
execute(client, control, 'Lspinfo')
deadline = time.monotonic() + 3
while True:
- matches = [int(row.split()[0]) for row in client.read('/self/index').splitlines()
+ matches = [int(row.split()[0]) for row in client.read('/index').splitlines()
if b'+Lsp' in row]
if matches:
break
assert time.monotonic() < deadline, (name, 'Lspinfo did not complete')
time.sleep(.005)
assert len(matches) == 1, matches
- result = client.read(f'/self/pane/{matches[0]}/body')
+ result = client.read(f'/pane/{matches[0]}/body')
assert result.startswith(b'backend: zls-inproc+lsp-client\n'), result
assert b'protocol servers (lsp-client):' in result, result
- assert client.read('/self/pane/1/body') == b'initial\n'
+ assert client.read('/pane/1/body') == b'initial\n'
assert '+Lsp' in ''.join(cell[0] for cell in client.screen()['cells'])
with session(binary, root, 'highlight') as (client, _):
- client.write('/self/pane/1/ctl', b'name keywords.zig\n')
+ client.write('/pane/1/name', b'keywords.zig\n')
source = b'// padding\n' * 9999 + b'fn check() void {\n if (true) return;\n}\n'
- client.write('/self/pane/1/body', source, truncate=True)
+ client.write('/pane/1/body', source, truncate=True)
screen = client.screen()
assert len(screen['cells']) == screen['cols'] * screen['rows']
found = set()
@@ -508,9 +585,9 @@ def test(binary, quic=False):
client.write(wire_path, b'written through long filename\n', truncate=True)
assert path.read_bytes() == b'written through long filename\n'
opened = look(client, '/n/os' + str(path))
- assert client.read(f'/self/pane/{opened}/body') == path.read_bytes()
+ assert client.read(f'/pane/{opened}/body') == path.read_bytes()
opened = look(client, '/n/os' + str(directory))
- listing = client.read(f'/self/pane/{opened}/body')
+ listing = client.read(f'/pane/{opened}/body')
for path in directory.iterdir():
assert ('/n/os' + str(path)).encode() in listing
if quic:
@@ -526,66 +603,66 @@ def quic_test(binary):
ports = {}
with session(binary, root, 'server', '--9p-tcp=tcp!' + host + '!0',
'--9p-quic=quic!' + host + '!0', tty=tty, network=ports) as (unix, address):
- assert set(unix.read('/self/listeners').decode().splitlines()) == {
+ assert set(unix.read('/listeners').decode().splitlines()) == {
'unix!' + str(address), 'tcp!' + host + '!' + str(ports['TCP']),
'quic!' + host + '!' + str(ports['QUIC'])}
with Client((host, ports['TCP'])) as tcp:
- unix_body = unix.open('/self/pane/1/body')
- tcp_body = tcp.open('/self/pane/1/body')
+ unix_body = unix.open('/pane/1/body')
+ tcp_body = tcp.open('/pane/1/body')
with session(binary, root, 'client') as (remote, _):
control = new_pane(remote, b'')
dial = 'quic!' + host + '!' + str(ports['QUIC'])
execute(remote, control, 'Mount peer ' + dial)
- opened = look(remote, '/n/peer/self/pane/1/body', source=control)
- body = f'/self/pane/{opened}/body'
+ opened = look(remote, '/n/peer/pane/1/body', source=control)
+ body = f'/pane/{opened}/body'
assert remote.read(body) == b'initial\n'
payload = 'saved café λ\n'.encode() + b'x' * (3 * 8192 + 27) + b'\n'
remote.write(body, payload, truncate=True)
- remote.write(f'/self/pane/{opened}/ctl', b'put\n')
+ remote.write(f'/pane/{opened}/ctl', b'exec Save\n')
assert unix.read_fid(unix_body) == payload[:unix.msize - 11]
- assert tcp.read('/self/pane/1/body') == payload
- tcp.write('/self/pane/1/body', b'TCP to QUIC Get\n', truncate=True)
- remote.write(f'/self/pane/{opened}/ctl', b'get\n')
+ assert tcp.read('/pane/1/body') == payload
+ tcp.write('/pane/1/body', b'TCP to QUIC Get\n', truncate=True)
+ remote.write(f'/pane/{opened}/ctl', b'get\n')
assert remote.read(body) == b'TCP to QUIC Get\n'
assert unix.read_fid(unix_body) == b'TCP to QUIC Get\n'
assert tcp.read_fid(tcp_body) == b'TCP to QUIC Get\n'
- screen_pane = look(remote, '/n/peer/self/screen', source=control)
- screen = json.loads(remote.read(f'/self/pane/{screen_pane}/body'))
+ screen_pane = look(remote, '/n/peer/screen', source=control)
+ screen = json.loads(remote.read(f'/pane/{screen_pane}/body'))
assert len(screen['cells']) == screen['cols'] * screen['rows']
assert 'TCP to QUIC Get' in ''.join(cell[0] for cell in screen['cells'])
large = ('normal λ line\n' * 20000).encode()
fixture = root / 'large.txt'
fixture.write_bytes(large)
large_pane = look(remote, '/n/peer/os' + str(fixture), source=control)
- assert remote.read(f'/self/pane/{large_pane}/body') == large
+ assert remote.read(f'/pane/{large_pane}/body') == large
edited = b'QUIC file saved\n'
- remote.write(f'/self/pane/{large_pane}/body', edited, truncate=True)
- remote.write(f'/self/pane/{large_pane}/ctl', b'put\n')
+ remote.write(f'/pane/{large_pane}/body', edited, truncate=True)
+ remote.write(f'/pane/{large_pane}/ctl', b'exec Save\n')
assert fixture.read_bytes() == edited
for pane in [opened, screen_pane, large_pane]:
- remote.write(f'/self/pane/{pane}/ctl', b'delete\n')
+ remote.write(f'/pane/{pane}/ctl', b'exec Del\n')
execute(remote, control, 'Unmount peer')
roots = look(remote, '/n', source=control)
- assert remote.read(f'/self/pane/{roots}/body') == b'/n/os/\n/n/self/\n'
+ assert remote.read(f'/pane/{roots}/body') == b'/n/os/\n/n/self/\n'
assert unix.read_fid(unix_body) == b'TCP to QUIC Get\n'
assert tcp.read_fid(tcp_body) == b'TCP to QUIC Get\n'
control = new_pane(unix, b'')
execute(unix, control, 'Mount own ' + dial)
- own = look(unix, '/n/own/self/pane/1/body', source=control)
- assert unix.read(f'/self/pane/{own}/body') == b'TCP to QUIC Get\n'
- unix.write(f'/self/pane/{own}/body', b'same-session QUIC Save\n', truncate=True)
- unix.write(f'/self/pane/{own}/ctl', b'put\n')
+ own = look(unix, '/n/own/pane/1/body', source=control)
+ assert unix.read(f'/pane/{own}/body') == b'TCP to QUIC Get\n'
+ unix.write(f'/pane/{own}/body', b'same-session QUIC Save\n', truncate=True)
+ unix.write(f'/pane/{own}/ctl', b'exec Save\n')
assert unix.read_fid(unix_body) == b'same-session QUIC Save\n'
assert tcp.read_fid(tcp_body) == b'same-session QUIC Save\n'
- unix.write(f'/self/pane/{own}/ctl', b'delete\n')
+ unix.write(f'/pane/{own}/ctl', b'exec Del\n')
execute(unix, control, 'Unmount own')
unix.close(unix_body)
tcp.close(tcp_body)
if __name__ == '__main__':
- if len(sys.argv) == 3 and sys.argv[2] == '--discovery':
- discovery(str(Path(sys.argv[1]).resolve()))
+ if len(sys.argv) in [3, 4] and sys.argv[2] == '--discovery':
+ discovery(str(Path(sys.argv[1]).resolve()), embedded=sys.argv[3:] == ['--embedded'])
raise SystemExit(0)
if len(sys.argv) not in [2, 3] or (len(sys.argv) == 3 and sys.argv[2] != '--quic'):
raise SystemExit('usage: fs.py <pardes> [--quic | --discovery]')