Files
qemu-ios/contrib/ipod-emu/tests/test-display-session.py
T

111 lines
4.3 KiB
Python

#!/usr/bin/env python3
"""Relances natives dans une session de test déjà démarrée (firmware non distribué)."""
import argparse
import http.server
import json
import os
from pathlib import Path
import runpy
import subprocess
import threading
import time
import uuid
def main():
p = argparse.ArgumentParser(description=__doc__)
p.add_argument('--emu-home', type=Path, required=True)
p.add_argument('--agent-port', type=int, required=True)
p.add_argument('--action', choices=('respring', 'reset'), required=True)
p.add_argument('--cycles', type=int, default=3)
p.add_argument('--output', type=Path, required=True)
args = p.parse_args()
if args.cycles < 1:
p.error('--cycles doit être positif')
home = args.emu_home.resolve()
run = home / 'run'
bindir = Path(__file__).resolve().parents[1] / 'bin'
os.environ.update(IPOD_EMU_HOME=str(home), IPOD_AGENT_PORT=str(args.agent_port))
Agent = runpy.run_path(str(bindir / 'ipod-agent'))['Agent']
def call(*fields, data=None):
a = Agent(timeout=10)
try:
ok, body, detail = a.call(*fields, data=data)
if not ok:
raise RuntimeError(body.decode(errors='replace'))
return body
finally:
a.f.close()
a.s.close()
def springboard():
return next(line.split()[0] for line in call('ps').decode().splitlines()
if line.endswith(' SpringBoard'))
nonce = uuid.uuid4().hex.encode()
marker = '/private/var/mobile/Library/test-display-' + nonce.decode()
class Fixture(http.server.BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header('Content-Length', str(len(nonce)))
self.end_headers()
self.wfile.write(nonce)
def log_message(self, *unused):
pass
server = http.server.ThreadingHTTPServer(('127.0.0.1', 0), Fixture)
threading.Thread(target=server.serve_forever, daemon=True).start()
url = f'http://10.0.2.2:{server.server_port}/preuve'
args.output.mkdir(parents=True, exist_ok=True)
qpid = (run / 'qemu.pid').read_text()
npid = (run / 'netd.pid').read_text()
inode = (run / 'nand').stat().st_ino
results = []
try:
call('put', marker, '600', len(nonce), data=nonce)
for cycle in range(args.cycles):
oldpid = springboard()
offset = (run / 'serial.log').stat().st_size
started = time.monotonic()
subprocess.run([str(bindir / 'ipod-emu'), args.action, '-W'],
check=True, timeout=340)
newpid = springboard()
fresh = (run / 'serial.log').read_bytes()[offset:]
if args.action == 'reset':
assert b'Darwin Kernel Version' in fresh
else:
assert oldpid != newpid
assert b'Darwin Kernel Version' not in fresh
assert b'locked=0 passcode=0' in call('screen')
assert (run / 'qemu.pid').read_text() == qpid
assert (run / 'netd.pid').read_text() == npid
assert (run / 'nand').stat().st_ino == inode
assert call('get', marker) == nonce
assert nonce in call('fetch', url)
call('launch', 'com.apple.calculator', '-')
time.sleep(3)
assert call('front').strip() == b'com.apple.calculator'
capture = args.output.resolve() / f'{args.action}-{cycle + 1}.png'
subprocess.run([str(bindir / 'ipod-qmp'), 'screenshot', str(capture)],
check=True, timeout=15)
result = dict(cycle=cycle + 1, seconds=round(time.monotonic() - started, 1),
qemu_pid=int(qpid), netd_pid=int(npid), springboard_pid=newpid,
unlocked=True, nand_preserved=True, http=True,
net=call('net').decode(), front='com.apple.calculator')
results.append(result)
print(json.dumps(result, ensure_ascii=False), flush=True)
(args.output / 'validation.json').write_text(
json.dumps(results, ensure_ascii=False, indent=2) + '\n')
call('rm', marker)
call('sync')
finally:
server.shutdown()
server.server_close()
if __name__ == '__main__':
main()