diff options
Diffstat (limited to 'test')
| -rw-r--r-- | test/fs.py | 31 | ||||
| -rw-r--r-- | test/selfmount.py | 26 |
2 files changed, 57 insertions, 0 deletions
@@ -1085,6 +1085,37 @@ def edit_commands(binary): assert time.monotonic() - began < .5 and not done.is_set(), 'the editor waited on the command' worker.join(timeout=15) assert done.is_set() + # On the same connection: the Edit's write is held, and a read sent + # after it is answered first; a Tflush of it stops it, changes + # nothing, and frees the way for the next Edit. + def send(kind, tag, payload): + client.socket.sendall(struct.pack('<IBH', 7 + len(payload), kind, tag) + payload) + + def answer(): + size, kind, tag = struct.unpack('<IBH', client.receive(7)) + return kind, tag, client.receive(size - 7) + ctl = client.open(f'/pane/{a}/ctl', 1) + status = client.open('/status', 0) + line = b'Edit , | sleep 1; cat\n' + began = time.monotonic() + send(118, 900, struct.pack('<IQI', ctl, 0, len(line)) + line) + send(116, 901, struct.pack('<IQI', status, 0, 4096)) + first = answer() + assert first[1] == 901 and first[0] == 117 and time.monotonic() - began < .5, (first[:2], time.monotonic() - began) + second = answer() + assert second[1] == 900 and second[0] == 119, second + line = b'Edit , | sleep 5; tr a-z A-Z\n' + send(118, 902, struct.pack('<IQI', ctl, 0, len(line)) + line) + time.sleep(.3) + send(108, 903, struct.pack('<H', 902)) + tags = sorted(answer()[1] for _ in range(2)) + assert tags == [902, 903], tags + client.close(ctl) + client.close(status) + time.sleep(1) + client.write(f'/pane/{a}/ctl', b'Edit , | cat\n') + time.sleep(4.5) + assert client.read(f'/pane/{a}/body') == b'APPLE\nFIG\nPEAR\n', client.read(f'/pane/{a}/body') # X: each open file whose line matches; w writes it. client.write(f'/pane/{a}/ctl', b'Edit X/b\\.txt$/ ,s/apple/APPLE/\n') assert client.read(f'/pane/{b}/body') == b'APPLE pie\n' diff --git a/test/selfmount.py b/test/selfmount.py index 0111e6ac..c8a81df9 100644 --- a/test/selfmount.py +++ b/test/selfmount.py @@ -291,6 +291,32 @@ def run(binary): said_many = many.read_text() if many.exists() else '' many.unlink(missing_ok=True) check(ran == '9' and 'Too many open files' in said_many, f'an open past the 64 records is EMFILE ({ran!r}, {said_many[-80:]!r})') + # An Edit whose command runs is held, not waited on: through the + # mount, a status read beside a slow one answers at once, and a + # command that reads this session's own tree runs. + edited = int(client.read('/pane/new')) + client.write(f'/pane/{edited}/body', b'pear\napple\n') + took = Path(f'/tmp/{name}.took') + ran = run((f"echo 'Edit , | sleep 3; sort' > {mount}/pane/{edited}/ctl & sleep .5; " + f"s=$(date +%s%N); timeout 5 cat {mount}/status > /dev/null; e=$(date +%s%N); " + f"echo $(( (e - s) / 1000000 )) > {took}; wait\n").encode()) + ms = int(took.read_text()) if took.exists() else -1 + took.unlink(missing_ok=True) + check(ran == '0' and 0 <= ms < 1000, f'a status read beside a slow Edit answers at once ({ms} ms)') + check(client.read(f'/pane/{edited}/body') == b'apple\npear\n', 'and the slow Edit applied') + ran = run(f"echo 'Edit $ < cat {mount}/pane/{edited}/body' > {mount}/pane/{edited}/ctl\n".encode()) + check(ran == '0' and client.read(f'/pane/{edited}/body') == b'apple\npear\napple\npear\n', + f'an Edit whose command reads the session through its mount ({ran!r})') + # An interrupted Edit write is flushed: its command is stopped and + # nothing changes, and the next Edit runs. + flushed = Path(f'/tmp/{name}.flushed') + ran = run((f"timeout -s INT 1 sh -c \"echo 'Edit , | sleep 4; tr a-z A-Z' > {mount}/pane/{edited}/ctl\"; " + f"echo $? > {flushed}; sleep 1; echo 'Edit 1 | tr p P' > {mount}/pane/{edited}/ctl; echo $? >> {flushed}\n").encode()) + codes = flushed.read_text().split() if flushed.exists() else [] + flushed.unlink(missing_ok=True) + time.sleep(4.5) + check(codes == ['124', '0'] and client.read(f'/pane/{edited}/body') == b'aPPle\npear\napple\npear\n', + f'an interrupted Edit changes nothing, and the next runs ({codes!r}, {client.read(f"/pane/{edited}/body")!r})') client.write('/exec', b'Msg still here\n') text = ''.join(cell[0] for cell in client.screen()['cells']) check('still here' in text, 'the editor answers after all of that') |
