#!/usr/bin/env python3 """Exercise an authored final-size guard through native source and fixed apps.""" import argparse import http.client import json from pathlib import Path import select import struct import subprocess import tempfile from check_tui import Terminal from check_document_peer import (certificates, connect, edit as peer_edit, hello, request as peer_request, start, stop) def run(binary, program, store, *args): command = [str(binary)] if program is not None: command += ['--program', str(program)] command += ['--store', str(store), *map(str, args)] return subprocess.run(command, capture_output=True, timeout=15) def edit(binary, program, store, payload, key, revision, offset, remove, body): payload.write_bytes(body) return run(binary, program, store, 'edit', key, revision, offset, remove, payload) def result(process, status, revision): assert process.returncode == status, (process.returncode, process.stderr) channel = process.stdout if status == 0 else process.stderr value = json.loads(channel) assert value['revision'] == str(revision), value if status: assert value['error'] == 'limit' if status == 2 else value['error'] == 'conflict' def body(binary, program, store, expected): shown = run(binary, program, store, 'show', 'note') assert shown.returncode == 0 and shown.stdout == expected return int(json.loads(shown.stderr)['revision']) class Server: def __init__(self, binary, program, store): command = [str(binary), '--store', str(store), '--port', '0'] if program is not None: command += ['--program', str(program)] self.process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) ready, _, _ = select.select([self.process.stdout], [], [], 10) if not ready: self.process.kill() raise AssertionError('document server did not start') line = self.process.stdout.readline() if not line: raise AssertionError(self.process.communicate(timeout=5)) self.port = json.loads(line)['port'] def request(self, method, data=b'', expected=None): headers = {'Content-Length': str(len(data))} if expected is not None: headers['If-None-Match' if expected == 0 else 'If-Match'] = ( '*' if expected == 0 else f'"{expected}"') connection = http.client.HTTPConnection('127.0.0.1', self.port, timeout=15) try: connection.request(method, '/objects/note', data, headers) response = connection.getresponse() return response.status, response.getheader('ETag'), response.read() finally: connection.close() def close(self): self.process.terminate() _, error = self.process.communicate(timeout=10) assert self.process.returncode == 0, error[-1000:] stats = json.loads(error) assert stats['active'] == stats['retained_payload_bytes'] == 0 def splice(offset, remove, insert): return struct.pack('