summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-27 17:41:55 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:14 -0300
commit542dd489149e33915d19878a277e23b3a9c0b070 (patch)
treeaeb557581446621c366a2d3cd5888d25b37c5916 /test
parentc11ffe24f022d61cdd479e1ee946033c42e9a08c (diff)
downloadpardes-542dd489149e33915d19878a277e23b3a9c0b070.tar.gz
pardes-542dd489149e33915d19878a277e23b3a9c0b070.zip
Record /log whether or not anyone reads it, with the editor's messages in it
/log is now one ring (64 KiB, 4 KiB on the board) that records new, del, rename and save, and a msg line for everything the editor says. An open freezes it, so cat log shows what happened lately and ends; writing follow to that same open makes reads past it wait for newer records, and a follower the ring outran reads lost N first. The message log keeps the pane's serial, not its reusable slot. A test now fails when the tree serves a file /README never mentions; it caught pty/status, now documented along with typing through pty/data. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'test')
-rw-r--r--test/fs.py24
-rw-r--r--test/panes.zig1
2 files changed, 18 insertions, 7 deletions
diff --git a/test/fs.py b/test/fs.py
index 33bcdfa9..48104e3f 100644
--- a/test/fs.py
+++ b/test/fs.py
@@ -185,7 +185,11 @@ def discovery(binary, embedded=False):
# An open of /pane/new makes a pane and the read names it; each
# open makes another. A stat makes none, which is why new can be
# listed at all: ls -l stats every name a listing gave it.
- log = client.open('/log')
+ # /log answers the recent past and ends; `follow` written to the
+ # same open makes its reads past that wait for new records.
+ log = client.open('/log', 2)
+ frozen = len(client.read_fid(log))
+ client.rpc(118, struct.pack('<IQI', log, 0, 7) + b'follow\n')
first = int(client.read('/pane/new'))
assert first == newest(client)
second = int(client.read('/pane/new'))
@@ -193,8 +197,14 @@ def discovery(binary, embedded=False):
assert 'new' in client.list('/pane'), 'new should be visible to ls'
client.stat('/pane/new')
assert newest(client) == second, 'a stat of new made a pane'
- assert client.read_fid(log) == f'new {first} {root}/+New\n'.encode()
- assert client.read_fid(log) == f'new {second} {root}/+New\n'.encode()
+ # What the editor said is in the stream too, and the fixture's own
+ # `new` lands on whichever side of the open its first update did.
+ def pane_event():
+ while (record := client.read_fid(log, frozen)).startswith((b'msg ', f'new {fixture} '.encode())):
+ pass
+ return record
+ assert pane_event() == f'new {first} {root}/+New\n'.encode()
+ assert pane_event() == f'new {second} {root}/+New\n'.encode()
assert set(client.list('/pane')) == {'new', 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'
@@ -206,7 +216,7 @@ def discovery(binary, embedded=False):
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 pane_event() == f'rename {first} {root}/notes.txt\n'.encode()
assert client.stat(f'/pane/{first}/name')['length'] == len(f'{root}/notes.txt\n')
# Copying addr onto dot selects that range; sel reads and replaces it.
client.write(f'/pane/{first}/addr', b'#0,#5')
@@ -223,11 +233,11 @@ def discovery(binary, embedded=False):
assert client.read(f'/pane/{first}/dirty') == b'1\n'
client.write(f'/pane/{first}/exec', b'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 pane_event() == f'save {first} {root}/notes.txt\n'.encode()
assert client.read('/exec') == f'{first}\n'.encode()
assert client.read(f'/pane/{first}/dirty') == b'0\n'
client.remove(f'/pane/{second}')
- assert client.read_fid(log) == f'del {second} {root}/+New\n'.encode()
+ assert pane_event() == f'del {second} {root}/+New\n'.encode()
assert str(second) not in client.list('/pane')
# look opens a file; the serial reads back.
(root / 'opened.txt').write_bytes(b'one\ntwo\nthree\n')
@@ -236,7 +246,7 @@ def discovery(binary, embedded=False):
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()
+ assert pane_event() == f'new {opened} {root}/opened.txt\n'.encode()
client.write(f'/pane/{first}/look', f'{root}/opened.txt:3\n'.encode())
assert client.read('/look') == f'{opened}\n'.encode(), 'a repeated look targets the open pane'
assert {str(fixture), str(first), str(opened)} <= set(client.list('/pane'))
diff --git a/test/panes.zig b/test/panes.zig
index 2d3aed43..2f307cb5 100644
--- a/test/panes.zig
+++ b/test/panes.zig
@@ -2193,6 +2193,7 @@ test "document panes ignore terminal output without allocating terminal state" {
const p = try Pardes.init(allocator.allocator(), .{ .tty_only = true });
defer p.deinit();
const pane = try p.setTestFile("document body\n");
+ p.update(.tick); // the step that installed it records it in /log
while (p.nextEffect()) |_| {}
const revision = pane.file.?.revision;
const allocations = allocator.alloc_index;