文件
rtos-watch-debug-bridge/phone-debug-bridge/tests/native_ui.py
T

99 行
5.4 KiB
Python

"""Verify ui.py against both native Glyphix emulator profiles (not a physical S2).
Build deviceprobe QuickApps first. Supply a compatible vendor global/launcher
image using --seed (or initialize the probe image). Never attaches to an
existing Inspector or terminates another user's emulator.
"""
import argparse
import hashlib
import json
from pathlib import Path
import shutil
import socket
import subprocess
import sys
import time
PROJECT = Path(__file__).resolve().parents[1]
ROOT = PROJECT.parent
sys.path.insert(0, str(PROJECT))
from ui import Inspector
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('--output', required=True, type=Path)
parser.add_argument('--seed', type=Path, default=ROOT / 'com.sydxky.rtos.deviceprobe/.glyphix-work/image/generic-watch-466x466',
help='Initialized vendor image containing global/, global.pkg and apps/emulator.launcher.pkg')
args = parser.parse_args()
output = args.output.resolve()
output.mkdir(parents=True, exist_ok=True)
results = []
for shape, device in [('round', '466x466'), ('rect', '390x450')]:
with socket.socket() as sock:
if sock.connect_ex(('127.0.0.1', 14201)) == 0:
raise RuntimeError('Inspector port in use; will not attach to another runtime')
folder = output / shape
image = folder / 'image'
image.mkdir(parents=True, exist_ok=True)
seed = args.seed.resolve()
shutil.copytree(seed / 'global', image / 'global', dirs_exist_ok=True)
shutil.copy2(seed / 'global.pkg', image / 'global.pkg')
(image / 'apps').mkdir(exist_ok=True)
shutil.copy2(seed / 'apps/emulator.launcher.pkg', image / 'apps/emulator.launcher.pkg')
name = 'com.sydxky.rtos.deviceprobe'
package = ROOT / name / '.glyphix-work/dist' / ('generic-watch-' + device + '-quickapp') / name / 'bundle.pkg'
shutil.copy2(package, image / 'apps' / (name + '.pkg'))
(image / 'pkgs.db').write_text(json.dumps({'apps': {p: {'uri': 'pkg://' + p} for p in (name, 'emulator.launcher')}, 'dials': {}}), encoding='utf-8')
command = [str(ROOT / 'temp/glyphix-v0.7.2-windows-x64/bin/glyphix-emu.exe'), '--config', 'pkgs.db', '--target', name, '--inspector']
command += ['--width', '624', '--height', '624', '--dpi', '326', '--font-size', '32', '--round', '--surface', 'surface/surface-466x466.json'] if shape == 'round' else ['--width', '390', '--height', '450', '--dpi', '321', '--font-size', '29']
command += ['--memory-profile', '8192', '--font-map', 'font-faces', '--font-family', 'sans-serif']
client = Inspector('http://127.0.0.1:14201')
item = {'profile': shape, 'evidence_scope': 'native_emulator_not_S2', 'package_sha256': hashlib.sha256(package.read_bytes()).hexdigest(), 'passed': False}
results.append(item)
with open(folder / 'stdout.log', 'w', encoding='utf-8') as out, open(folder / 'stderr.log', 'w', encoding='utf-8') as err:
proc = subprocess.Popen(command, cwd=image, stdin=subprocess.PIPE, stdout=out, stderr=err, creationflags=subprocess.CREATE_NO_WINDOW)
try:
for _ in range(70):
if proc.poll() is not None:
raise RuntimeError('Emulator exited before Inspector startup')
try:
client.request('/logs')
break
except OSError:
time.sleep(.3)
else:
raise TimeoutError('Inspector did not start')
time.sleep(1)
item['before'] = client.screenshot(folder / 'before.png')
item['initial_visible'] = client.exists(('text', '点击次数:0'))
client.click(('text', '点击验证'))
item['after_visible'] = client.exists(('text', '点击次数:1'))
item['after'] = client.screenshot(folder / 'after.png')
plan = json.loads((PROJECT / 'examples/probe-inspector.json').read_text(encoding='utf-8'))
plan['steps'][0]['value'] = '点击次数:1'
plan['steps'][2]['value'] = '点击次数:2'
planfile = folder / 'plan.json'
planfile.write_text(json.dumps(plan, ensure_ascii=False), encoding='utf-8')
run = subprocess.run([sys.executable, str(PROJECT / 'ui.py'), '--target', 'inspector', '--inspector', client.base, 'run', str(planfile), '--output', str(folder / 'plan-results')], capture_output=True, timeout=90)
item['plan_exit'] = run.returncode
item['passed'] = item['initial_visible'] and item['after_visible'] and run.returncode == 0
if run.returncode:
raise RuntimeError(run.stderr.decode('utf-8', 'replace') or 'UI plan failed')
except Exception as error:
item['error'] = type(error).__name__
raise
finally:
if proc.poll() is None:
proc.terminate()
proc.wait(timeout=10)
proc.stdin.close()
(output / 'results.json').write_text(json.dumps(results, ensure_ascii=False, indent=2), encoding='utf-8')
print(json.dumps(item, ensure_ascii=True), flush=True)
time.sleep(2)
return 0 if all(item['passed'] for item in results) else 1
if __name__ == '__main__':
sys.exit(main())