diff options
Diffstat (limited to 'test')
| -rw-r--r-- | test/monkey9p.py | 12 | ||||
| -rw-r--r-- | test/panes.zig | 10 | ||||
| -rw-r--r-- | test/selfmount.py | 39 | ||||
| -rw-r--r-- | test/snapshot.zig | 5 | ||||
| -rw-r--r-- | test/snapshots/chordcut.snap | 15 | ||||
| -rw-r--r-- | test/snapshots/lspcomplete.snap | 20 |
6 files changed, 74 insertions, 27 deletions
diff --git a/test/monkey9p.py b/test/monkey9p.py index 4d190bbc..87e386b3 100644 --- a/test/monkey9p.py +++ b/test/monkey9p.py @@ -674,8 +674,9 @@ def served_lines(data, sizes, room): (fs.md, tree.zig write): each ended line, and the unended tail of a piece shorter than a Twrite holds (`room`, msize less 24), which is whole in itself, as acme takes each write; a piece that fills its Twrite may go - on, and its tail waits for the next. A line written a byte a Twrite is - so as many lines as bytes.""" + on, and its tail waits for the next, and so does one of a multiple of + 4096 bytes, where a writer's buffer filled. A line written a byte a + Twrite is so as many lines as bytes.""" lines, pending, at = [], b'', 0 for size in sizes: piece = data[at:at + size] @@ -683,7 +684,7 @@ def served_lines(data, sizes, room): pending += piece *done, pending = pending.split(b'\n') lines += done - if pending and len(piece) < room: + if pending and len(piece) < room and len(piece) % 4096 != 0: lines.append(pending) pending = b'' if pending: @@ -1615,7 +1616,10 @@ def chunked_equals_whole(ctx, res): whole_n, chunk_n = dir_names(whole), dir_names(chunked) if whole_n != chunk_n: return f'{path}: whole {whole_n} != chunked({size}) {chunk_n}' - elif whole != chunked: + elif whole != chunked and w.read_all(fid) != chunked: + # A live file (a tag says `running`, then `exit 0`) may change + # between the two reads: only chunks that no whole read matches, + # read again, are a chunking fault. return f'{path}: whole {whole[:200]!r} != chunked({size}) {chunked[:200]!r}' finally: w.clunk(fid) diff --git a/test/panes.zig b/test/panes.zig index d7fa3514..6f321abf 100644 --- a/test/panes.zig +++ b/test/panes.zig @@ -981,10 +981,12 @@ const TtySelectionTests = struct { const target = p.rects[1]; const tx = target.x + config.GUTTER + 2; const ty = bodyY(p, target); - p.update(.{ .mouse = .{ .button = .left, .kind = .press, .col = tx, .row = ty } }); - p.update(.{ .mouse = .{ .button = .right, .kind = .press, .col = tx, .row = ty } }); - p.update(.{ .mouse = .{ .button = .right, .kind = .release, .col = tx, .row = ty } }); - p.update(.{ .mouse = .{ .button = .left, .kind = .release, .col = tx, .row = ty } }); + // Shift: over a program that tracks the mouse the chord is + // pardes's only so, and elsewhere Shift changes nothing. + p.update(.{ .mouse = .{ .button = .left, .kind = .press, .col = tx, .row = ty, .shift = true } }); + p.update(.{ .mouse = .{ .button = .right, .kind = .press, .col = tx, .row = ty, .shift = true } }); + p.update(.{ .mouse = .{ .button = .right, .kind = .release, .col = tx, .row = ty, .shift = true } }); + p.update(.{ .mouse = .{ .button = .left, .kind = .release, .col = tx, .row = ty, .shift = true } }); var written: std.Io.Writer.Allocating = .init(p.gpa); defer written.deinit(); while (p.nextEffect()) |effect| { diff --git a/test/selfmount.py b/test/selfmount.py index 6534aa25..86c32fa8 100644 --- a/test/selfmount.py +++ b/test/selfmount.py @@ -20,6 +20,7 @@ import signal import struct import sys import termios +import threading import time sys.path.insert(0, str(Path(__file__).resolve().parent)) @@ -127,12 +128,42 @@ def run(binary): return exits[-1].split()[2] time.sleep(.1) return 'timeout' + # 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 + # every line is either heard once, in order, or a loss is said. + heard = [] + + def follow(): + with Client(sock) as follower: + fid = follower.open('/log', 2) + start = len(follower.read_fid(fid)) + follower.rpc(118, struct.pack('<IQI', fid, 0, len(b'follow new\n')) + b'follow new\n') + ready.set() + deadline = time.monotonic() + 60 + while time.monotonic() < deadline: + record = follower.read_fid(fid, start).decode() + heard.append(record) + if 'mnt-0999' in record: + return + ready = threading.Event() + reader = threading.Thread(target=follow, daemon=True) + reader.start() + check(ready.wait(10), 'a follower of the log is waiting') got = run(f"seq -f 'Msg mnt-%04g' 0 999 > {mount}/exec\n".encode()) check(got == '0', f'a 1000-line burst written through the mount ({got!r})') - log = client.read('/log').decode() - said = [line.split(' ', 2)[2] for line in log.splitlines() if line.startswith('msg ') and 'mnt-' in line] - check(said == ['mnt-%04d' % i for i in range(1000)], f'each line of it ran once, whole ({len(said)} said)') - check('exit 127' not in log, 'no piece of a line ran as a command') + reader.join(60) + for r in heard: + if r.startswith(('err ', 'exit ')): + print(' heard: ' + r.rstrip()) + said = [r.rstrip('\n').split(' ', 2)[2] for r in heard if r.startswith('msg ') and 'mnt-' in r] + lost = [r for r in heard if r.startswith('lost ')] + numbers = [int(s[4:]) for s in said] + check(numbers == list(range(numbers[0] if numbers else 0, 1000)), + f'each line it heard ran once, whole, in order, through the last ({len(said)} heard)') + check(len(said) == 1000 or (lost and heard.index(lost[0]) < heard.index(next(r for r in heard if 'mnt-' in r))), + f'no line was lost unsaid ({len(said)} heard, {lost!r})') + check(not any('exit 127' in r for r in heard), 'no piece of a line ran as a command') scratch = int(client.read('/pane/new')) maker = "import sys; sys.stdout.write('Edit ,a\\n' + ''.join('line %05d of the block\\n' % i for i in range(2500)) + '.\\n')" check(run(f'python3 -c "{maker}" > {mount}/pane/{scratch}/ctl\n'.encode()) == '0', 'a 50 KB Edit block written through the mount') diff --git a/test/snapshot.zig b/test/snapshot.zig index a176da7a..5522fbb9 100644 --- a/test/snapshot.zig +++ b/test/snapshot.zig @@ -1489,6 +1489,11 @@ fn buttonCode(name: []const u8) ?u16 { const base = buttonCode(name["ctrl-".len..]) orelse return null; return base + 16; } + // Shift: over a program that tracks the mouse, pardes's own gesture. + if (std.mem.startsWith(u8, name, "shift-")) { + const base = buttonCode(name["shift-".len..]) orelse return null; + return base + 4; + } if (std.mem.eql(u8, name, "left")) return 0; if (std.mem.eql(u8, name, "middle")) return 1; if (std.mem.eql(u8, name, "right")) return 2; diff --git a/test/snapshots/chordcut.snap b/test/snapshots/chordcut.snap index 1baef7ec..fddd9e92 100644 --- a/test/snapshots/chordcut.snap +++ b/test/snapshots/chordcut.snap @@ -124,9 +124,10 @@ snapstyle clickdismiss press middle 59 23 release middle 59 23 stable 700 15000 -# tty paste chord: a mouse-listening app gets the click forwarded (SGR, -# body-relative) then the register between bracketed-paste markers — -# cat -v prints the received bytes visibly +# tty paste chord: over a mouse-listening app the chord is pardes's with +# Shift held; the app gets a click where the text goes (SGR, body-relative) +# then the register between bracketed-paste markers — cat -v prints the +# received bytes visibly press left 35 23 release left 35 23 stable 400 5000 @@ -135,10 +136,10 @@ stable 600 8000 text stty -icanon -echo; printf '\x1b[?2004h\x1b[?1000h\x1b[?1006h'; cat -v key enter stable 700 8000 -press left 40 25 -press right 40 25 -release right 40 25 -release left 40 25 +press shift-left 40 25 +press shift-right 40 25 +release shift-right 40 25 +release shift-left 40 25 stable 700 8000 snap ttyprobe # a plain prompt (mouse modes off) gets no click bytes — just the paste; diff --git a/test/snapshots/lspcomplete.snap b/test/snapshots/lspcomplete.snap index d9e165a1..eaa26c61 100644 --- a/test/snapshots/lspcomplete.snap +++ b/test/snapshots/lspcomplete.snap @@ -1,4 +1,8 @@ -# Tab after a dot in insert mode: "what could go here". The answer is a +# Tab after a dot in insert mode: "what could go here". +# +# Each wait for zls's answer allows a minute: it returns as soon as the answer +# is drawn (2 s alone), and a zls slowed by a loaded machine (the parallel +# snap run) took over 15 s, which failed the old wait. The answer is a # `+Search` buffer of zls's candidates, one row each at the cursor (a # completion item names no declaration) — nothing is inserted and nothing pops # up. @@ -62,8 +66,8 @@ key tab # The rows that prove it: `verdigris` and `cinnabar` can only have come from # resolving the switch's condition to `Shade` and asking what it declares. # Line 8 still reads `.` and nothing else — a completion INSERTS NOTHING. -wait 15000 +Search -stable 700 15000 +wait 60000 +Search +stable 700 30000 snap completion # Two more Tabs. Every one of them answers, and every answer REFILLS the one # `+Search` rather than opening its twin. The SECOND press is already the whole @@ -78,7 +82,7 @@ settle 150 key tab settle 150 key tab -stable 700 20000 +stable 700 30000 snap refill # The pane is still in insert mode, which is right — the query answered beside # the cursor and typing goes on — so walking the answer means leaving it first, @@ -127,8 +131,8 @@ key end text . stable 400 5000 key tab -wait 15000 +Search -stable 700 15000 +wait 60000 +Search +stable 700 30000 snap nosemi # ...and a construct still hanging OPEN. The switch has no closing brace at # all — the one `}` in the file closes it and leaves the function unclosed — @@ -148,6 +152,6 @@ key end text . stable 400 5000 key tab -wait 15000 +Search -stable 700 15000 +wait 60000 +Search +stable 700 30000 snap nobrace |
