feat: 开源蟹蟹输入RTOS适配改版并采用MIT商用许可

这个提交包含在:
sydxky 于 2026-11-14 12:10:10 +08:00 提交
当前提交 29374caffd
116 个文件已更改
+351523

没有与搜索条件相匹配的文件

+119
查看文件
@@ -0,0 +1,119 @@
"""Run real Glyphix native UI tests through its local Inspector (Python stdlib).
Build the input app and the minimal test fixture first; see the root README. No production
credentials, paid requests, Windows input injection or third party modules.
"""
import argparse
import datetime
import hashlib
import json
import pathlib
import shutil
import socket
import subprocess
import time
import urllib.parse
import urllib.request
ROOT = pathlib.Path(__file__).resolve().parents[1]
APPS = ['inputmethod', 'imefixture']
PROFILES = ['round', 'rect', 'round-quickapp', 'rect-quickapp']
BASE = 'http://127.0.0.1:14201'
def sha256(path):
return hashlib.sha256(path.read_bytes()).hexdigest().upper()
def request(path, params=None, method='GET'):
url = BASE + path + ('?' + urllib.parse.urlencode(params) if params else '')
with urllib.request.urlopen(urllib.request.Request(url, method=method), timeout=15) as response:
data = response.read()
try:
return json.loads(data)
except (ValueError, UnicodeDecodeError):
return data.decode('utf-8', errors='replace')
def evaluate(script):
return request('/fn/eval', {'lang': 'js', 'script': script}, 'POST')
def resume():
request('/control', {'pause': 'false'}, 'POST')
def snapshot(name, output):
try:
tree = request('/snapshot.json')
(output / (name + '.tree.json')).write_text(json.dumps(tree, ensure_ascii=False), encoding='utf-8')
with urllib.request.urlopen(BASE + '/snapshot/' + tree['frames'][-1]['snapshot'], timeout=15) as response:
(output / (name + '.png')).write_bytes(response.read())
finally:
# Capturing Inspector history pauses the runtime, including gestures/timers.
resume()
def prepare(profile, work):
device = 'generic-watch-' + ('466x466' if profile.startswith('round') else '390x450')
image = work / profile / 'image'
image.mkdir(parents=True, exist_ok=True)
seed = ROOT / 'com.sydxky.rtos.imefixture/.glyphix-work/image/generic-watch-466x466'
if not (seed / 'global.pkg').is_file() or not (seed / 'apps/emulator.launcher.pkg').is_file():
raise RuntimeError('Missing global assets/launcher: launch the round fixture emulator once with gx emulate first.')
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')
artifacts = {}
for app in APPS:
package = 'com.sydxky.rtos.' + app
build = ROOT / package / '.glyphix-work'
if profile.endswith('-quickapp'):
source = build / 'dist' / (device + '-quickapp') / package / 'bundle.pkg'
else:
source = build / 'image' / device / 'apps' / (package + '.pkg')
shutil.copy2(source, image / 'apps' / (package + '.pkg'))
artifacts[app] = {'path': str(source), 'sha256': sha256(source), 'ux_sha256': sha256(ROOT / package / 'src/main/index.ux')}
packages = ['com.sydxky.rtos.' + app for app in APPS] + ['emulator.launcher']
(image / 'pkgs.db').write_text(json.dumps({'apps': {p: {'uri': 'pkg://' + p} for p in packages}, 'dials': {}}), encoding='utf-8')
return image, artifacts
def start(profile, work, first_app):
# Do not attach to or terminate another user's running emulator.
with socket.socket() as probe:
if probe.connect_ex(('127.0.0.1', 14201)) == 0:
raise RuntimeError('Inspector port 14201 is already in use; close the other emulator first.')
image, artifacts = prepare(profile, work)
executable = ROOT / 'temp/glyphix-v0.7.2-windows-x64/bin/glyphix-emu.exe'
args = [str(executable), '--config', 'pkgs.db', '--target', 'com.sydxky.rtos.' + first_app, '--inspector']
if profile.startswith('round'):
args += ['--width', '624', '--height', '624', '--dpi', '326', '--font-size', '32', '--round', '--surface', 'surface/surface-466x466.json']
else:
args += ['--width', '390', '--height', '450', '--dpi', '321', '--font-size', '29']
args += ['--memory-profile', '8192', '--font-map', 'font-faces', '--font-family', 'sans-serif']
stdout = open(work / profile / 'stdout.log', 'w', encoding='utf-8')
stderr = open(work / profile / 'stderr.log', 'w', encoding='utf-8')
# Keep stdin open: the vendor emulator exits when its console input sees EOF.
process = subprocess.Popen(args, cwd=image, stdin=subprocess.PIPE, stdout=stdout, stderr=stderr, creationflags=subprocess.CREATE_NO_WINDOW)
try:
deadline = time.time() + 20
while time.time() < deadline:
if process.poll() is not None:
raise RuntimeError('Emulator exited before Inspector was ready; inspect ' + str(work / profile / 'stderr.log'))
try:
request('/logs')
time.sleep(1)
return process, artifacts
except OSError:
time.sleep(0.25)
raise RuntimeError('Inspector startup timed out')
except BaseException:
if process.poll() is None:
process.terminate()
process.wait(timeout=10)
raise
finally:
stdout.close()
stderr.close()