diff options
Diffstat (limited to 'test/fs.py')
| -rw-r--r-- | test/fs.py | 91 |
1 files changed, 89 insertions, 2 deletions
@@ -622,11 +622,11 @@ def workflow_canary(binary): rows = client.read(f'/pane/{grep}/body').decode() assert 'a.txt:2' in rows and 'b.txt:2' in rows, rows client.remove(f'/pane/{grep}') - execute_refused(client, a, 'Grep zzqqnomatch', 'grep: pattern not found') + execute_refused(client, a, 'Grep zzqqnomatch', 'Grep: pattern not found') found = made_by(a, b'Find b.txt\n') assert 'b.txt' in client.read(f'/pane/{found}/body').decode() client.remove(f'/pane/{found}') - execute_refused(client, a, 'Find zzqqnomatch', 'find: name not found') + execute_refused(client, a, 'Find zzqqnomatch', 'Find: name not found') # A plain word looked at is found in the pane, after its dot. client.write(f'/pane/{a}/dot', b' 0 0 ') @@ -953,6 +953,20 @@ def test(binary, quic=False): with Client(address, msize=256) as small: assert set(small.list('/os' + str(listing))) == { f'entry-{number:02}' for number in range(24)} + # 64 KiB frames: a ctl line with no newline, whole in its one + # Twrite, runs with it however long -- the cutoff for a write + # that may go on is the frame the client asked for, less 24. + with Client(address, msize=65536) as big: + assert big.msize == 65536 + ctl = big.open('/pane/1/ctl', 1) + line = b'bogus' + b'x' * 20000 + try: + big.rpc(118, struct.pack('<IQI', ctl, 0, len(line)) + line) + except OSError: + pass # refused with its write (a line over 1024 bytes), not held + else: + raise AssertionError('a whole 20000-byte line waited for a newline') + big.close(ctl) frozen = client.open('/screen') before = bytearray(client.read_fid(frozen, count=31)) @@ -1224,6 +1238,79 @@ def test(binary, quic=False): cell[0] for cell in local.screen()['cells']) assert client.read('/index') == before + # --wait (acme's E): a launch inside a pane lasts until the pane it + # opened is deleted, as an $EDITOR must; one on a file already open + # waits on that pane; a session that goes away ends it with 1. + with session(binary, root, 'wait') as (client, address): + status = dict(line.split(maxsplit=1) for line in client.read('/status').decode().splitlines()) + env = {k: v for k, v in os.environ.items() if k != 'PARDES_FORWARD_LOOK'} + env.update(PARDES_9P=str(address), PARDES_PANE='1', PARDES_PID=status['pid']) + edited = root / 'wait edit.txt' + edited.write_bytes(b'edit me\n') + + def serials(): + return {int(row.split()[0]) for row in client.read('/index').splitlines()} + + def launch(flag): + before = serials() + child = subprocess.Popen([binary, flag, str(edited)], cwd=root, env=env, + stdout=subprocess.DEVNULL, stderr=subprocess.PIPE) + deadline = time.monotonic() + 3 + while child.poll() is None and not serials() - before and time.monotonic() < deadline: + time.sleep(.01) + return child + + first = launch('--wait') + opened, = serials() - {1} + second = launch('-w') + time.sleep(.5) + assert first.poll() is None and second.poll() is None, (first.stderr.read(), second.stderr.read()) + assert serials() == {1, opened} + client.write(f'/pane/{opened}/body', b'edited\n', truncate=True) + execute(client, opened, 'Save') + client.remove(f'/pane/{opened}') + deleted = time.monotonic() + assert first.wait(timeout=5) == 0 + # Woken by the `del` record, not a poll. + assert time.monotonic() - deleted < .05, time.monotonic() - deleted + assert second.wait(timeout=5) == 0 + assert edited.read_bytes() == b'edited\n' + # A name not there yet opens a pane named it, as acme's B does, + # and Save creates it: git's and fish's temporary files are. + fresh = root / 'wait new.txt' + before = serials() + made = subprocess.Popen([binary, '--wait', fresh.name], cwd=root, env=env, + stdout=subprocess.DEVNULL, stderr=subprocess.PIPE) + deadline = time.monotonic() + 3 + while not serials() - before: + assert made.poll() is None, made.stderr.read() + assert time.monotonic() < deadline, 'a new name opened no pane' + time.sleep(.01) + named, = serials() - before + assert str(fresh).encode() in client.read('/index') + client.write(f'/pane/{named}/body', b'new\n') + execute(client, named, 'Save') + client.remove(f'/pane/{named}') + assert made.wait(timeout=5) == 0 + assert fresh.read_bytes() == b'new\n' + orphan = launch('--wait') + assert orphan.poll() is None + assert orphan.wait(timeout=5) == 1 + + # A launch with no terminal to draw on (a pty that is no one's + # controlling terminal) says so and exits 1, no error trace. + master, slave = os.openpty() + try: + env = {k: v for k, v in os.environ.items() if not k.startswith('PARDES_')} + env.update(HOME=str(root), XDG_RUNTIME_DIR=str(root), TERM='xterm-256color') + result = subprocess.run([binary, '--tty', 'x.txt'], cwd=root, env=env, stdin=slave, stdout=slave, + stderr=subprocess.PIPE, start_new_session=True, timeout=10) + finally: + os.close(master) + os.close(slave) + assert result.returncode == 1, result + assert b'pardes: no terminal to draw on' in result.stderr and b'.zig:' not in result.stderr, result.stderr + for tty in [False, True]: name = 'lsp-tty' if tty else 'lsp-detached' with session(binary, root, name, tty=tty) as (client, _): |
