"""Real native automation and HTTP clients editing the same authored document.""" from concurrent.futures import ThreadPoolExecutor import json import socket import struct import subprocess def check_edits(editor, binary, root, directory, serving, rpc, header, records, checks): storage = directory / 'edited-objects' program = root / 'examples/editor.pure' file = directory / 'insertion.bin' def local(*args, body=None, code=0, source=program, budget=None): if body is not None: file.write_bytes(body) args = (*args, str(file)) command = [str(editor), '--program', str(source), '--store', str(storage)] if budget is not None: command += ['--budget', str(budget)] result = subprocess.run(command + [str(arg) for arg in args], capture_output=True, timeout=20) assert result.returncode == code, (command, args, result.stdout, result.stderr) return result initial = 'Pureμ—μ„œ μ•ˆλ…• 🌏\n'.encode() created = local('edit', 'note', 0, 0, 0, body=initial) assert json.loads(created.stdout)['revision'] == '1' start = initial.index('μ•ˆλ…•'.encode()) inserted = 'λ°˜κ°€μ›Œ'.encode() expected = initial[:start] + inserted + initial[start + len('μ•ˆλ…•'.encode()):] local('edit', 'note', 1, start, len('μ•ˆλ…•'.encode()), body=inserted) shown = local('show', 'note') assert shown.stdout == expected and json.loads(shown.stderr)['revision'] == '2' checks.append('native authored byte edit and fresh native process restore UTF-8 content') stale = local('edit', 'note', 1, 0, 0, body=b'bad', code=3) assert json.loads(stale.stderr) == {'error': 'conflict', 'revision': '2'} local('edit', 'note', 2, 0xffffffff, 0, body=b'bad', code=2) assert local('show', 'note').stdout == expected checks.append('native stale revision and invalid byte position preserve the committed document') reordered = directory / 'edit-reordered.pure' reordered.write_text('layout E { tag: bytes[1]; remove: u32le; start: u32le; body: bytes; } ' 'on get { let o = store.read(request.key); reply(o, o.body); } ' 'on put { let e = view(E, request.body); ' 'let s = store.splice(request.key, request.revision, e.start, e.remove, e.body); reply(s, e.body); }') local('edit', 'note', 2, len(expected), 0, body=b'!', source=reordered) expected += b'!' assert local('show', 'note', source=reordered).stdout == expected checks.append('native convenience editor derives unaligned reordered field positions from the authored program') custom = directory / 'edit-custom.pure' custom.write_text('on get { let o = store.read(request.key); reply(o, o.body); } ' 'on put { let s = store.splice(request.key, request.revision, 0, 0, request.body); reply(s); }') local('edit', 'custom', 0, 0, 0, body=b'ignored', source=custom, code=2) applied = local('apply', 'custom', 0, body=b'custom input', source=custom) assert json.loads(applied.stdout) == {'revision': '1', 'reply_bytes': 0} assert local('show', 'custom', source=custom).stdout == b'custom input' checks.append('raw native apply runs another authored input contract without changing the executor') with serving(binary, storage, program=program) as server: assert rpc(server, 'GET', 'note')[2] == expected status, headers, body = rpc(server, 'PUT', 'note', struct.pack('