mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-09 20:58:31 +09:00
[Fix] (TraceReplay): support local Android retrace reports
This commit is contained in:
@@ -256,9 +256,9 @@ jobs:
|
||||
width: 854
|
||||
height: 480
|
||||
crop_x: 0
|
||||
crop_y: 0
|
||||
crop_width: 0
|
||||
crop_height: 0
|
||||
crop_y: 10
|
||||
crop_width: 140
|
||||
crop_height: 158
|
||||
timeout_seconds: 1800
|
||||
- name: minecraft-1.21.4-fabric-xaero-world-map-in-world
|
||||
trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-xaero-world-map-in-world.tgz
|
||||
|
||||
@@ -42,6 +42,18 @@ die() {
|
||||
exit 2
|
||||
}
|
||||
|
||||
host_path_for_adb() {
|
||||
if command -v cygpath >/dev/null 2>&1; then
|
||||
cygpath -w "$1"
|
||||
else
|
||||
printf '%s' "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
adb_device_path() {
|
||||
MSYS_NO_PATHCONV=1 MSYS2_ARG_CONV_EXCL='*' "${ADB}" "$@"
|
||||
}
|
||||
|
||||
next_arg() {
|
||||
if [ "$#" -lt 2 ]; then
|
||||
die "$1 requires a value"
|
||||
@@ -146,17 +158,17 @@ collect_run_diagnostics() {
|
||||
diagnostics_dir="$1"
|
||||
mkdir -p "${diagnostics_dir}"
|
||||
"${ADB}" logcat -d -t 2000 > "${diagnostics_dir}/logcat.txt" || true
|
||||
"${ADB}" shell pidof "${package_name}" > "${diagnostics_dir}/pidof.txt" 2>&1 || true
|
||||
"${ADB}" shell dumpsys activity activities > "${diagnostics_dir}/activity.txt" 2>&1 || true
|
||||
"${ADB}" shell run-as "${package_name}" ls -laR "${app_dir}" > "${diagnostics_dir}/app-files.txt" 2>&1 || true
|
||||
"${ADB}" exec-out run-as "${package_name}" cat "${app_dir}/output/retrace.log" > "${diagnostics_dir}/retrace.log" || true
|
||||
"${ADB}" exec-out run-as "${package_name}" cat "${app_dir}/output/mobilegl.log" > "${diagnostics_dir}/mobilegl.log" || true
|
||||
adb_device_path shell pidof "${package_name}" > "${diagnostics_dir}/pidof.txt" 2>&1 || true
|
||||
adb_device_path shell dumpsys activity activities > "${diagnostics_dir}/activity.txt" 2>&1 || true
|
||||
adb_device_path shell run-as "${package_name}" ls -laR "${app_dir}" > "${diagnostics_dir}/app-files.txt" 2>&1 || true
|
||||
adb_device_path exec-out run-as "${package_name}" cat "${app_dir}/output/retrace.log" > "${diagnostics_dir}/retrace.log" || true
|
||||
adb_device_path exec-out run-as "${package_name}" cat "${app_dir}/output/mobilegl.log" > "${diagnostics_dir}/mobilegl.log" || true
|
||||
}
|
||||
|
||||
copy_app_artifact() {
|
||||
source_path="$1"
|
||||
destination_path="$2"
|
||||
if ! "${ADB}" exec-out run-as "${package_name}" cat "${source_path}" > "${destination_path}"; then
|
||||
if ! adb_device_path exec-out run-as "${package_name}" cat "${source_path}" > "${destination_path}"; then
|
||||
echo "trace-replay-ci.sh: warning: failed to copy ${source_path}" >&2
|
||||
rm -f "${destination_path}"
|
||||
fi
|
||||
@@ -171,14 +183,14 @@ prepare_fixture() {
|
||||
extracted_trace="${fixture_dir}/${trace_file}"
|
||||
test -f "${extracted_trace}" || die "trace file not found in archive: ${trace_file}"
|
||||
|
||||
"${ADB}" push "${extracted_trace}" "/data/local/tmp/mobilegl-${safe_case}.trace"
|
||||
"${ADB}" push "${golden_path}" "/data/local/tmp/mobilegl-${safe_case}.golden.png"
|
||||
adb_device_path push "$(host_path_for_adb "${extracted_trace}")" "/data/local/tmp/mobilegl-${safe_case}.trace"
|
||||
adb_device_path push "$(host_path_for_adb "${golden_path}")" "/data/local/tmp/mobilegl-${safe_case}.golden.png"
|
||||
if [ -n "${alternate_golden_path}" ]; then
|
||||
"${ADB}" push "${alternate_golden_path}" "/data/local/tmp/mobilegl-${safe_case}.alternate-golden.png"
|
||||
adb_device_path push "$(host_path_for_adb "${alternate_golden_path}")" "/data/local/tmp/mobilegl-${safe_case}.alternate-golden.png"
|
||||
fi
|
||||
"${ADB}" shell chmod 0644 "/data/local/tmp/mobilegl-${safe_case}.trace" "/data/local/tmp/mobilegl-${safe_case}.golden.png"
|
||||
adb_device_path shell chmod 0644 "/data/local/tmp/mobilegl-${safe_case}.trace" "/data/local/tmp/mobilegl-${safe_case}.golden.png"
|
||||
if [ -n "${alternate_golden_path}" ]; then
|
||||
"${ADB}" shell chmod 0644 "/data/local/tmp/mobilegl-${safe_case}.alternate-golden.png"
|
||||
adb_device_path shell chmod 0644 "/data/local/tmp/mobilegl-${safe_case}.alternate-golden.png"
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -187,12 +199,12 @@ copy_fixture_to_app() {
|
||||
golden_tmp="/data/local/tmp/mobilegl-${safe_case}.golden.png"
|
||||
alternate_golden_tmp="/data/local/tmp/mobilegl-${safe_case}.alternate-golden.png"
|
||||
|
||||
"${ADB}" shell run-as "${package_name}" rm -rf "${app_dir}"
|
||||
"${ADB}" shell run-as "${package_name}" mkdir -p "${app_dir}/input" "${app_dir}/output"
|
||||
"${ADB}" shell run-as "${package_name}" cp "${trace_tmp}" "${app_dir}/input/trace.trace"
|
||||
"${ADB}" shell run-as "${package_name}" cp "${golden_tmp}" "${app_dir}/input/golden.png"
|
||||
adb_device_path shell run-as "${package_name}" rm -rf "${app_dir}"
|
||||
adb_device_path shell run-as "${package_name}" mkdir -p "${app_dir}/input" "${app_dir}/output"
|
||||
adb_device_path shell run-as "${package_name}" cp "${trace_tmp}" "${app_dir}/input/trace.trace"
|
||||
adb_device_path shell run-as "${package_name}" cp "${golden_tmp}" "${app_dir}/input/golden.png"
|
||||
if [ -n "${alternate_golden_path}" ]; then
|
||||
"${ADB}" shell run-as "${package_name}" cp "${alternate_golden_tmp}" "${app_dir}/input/alternate-golden.png"
|
||||
adb_device_path shell run-as "${package_name}" cp "${alternate_golden_tmp}" "${app_dir}/input/alternate-golden.png"
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -211,9 +223,9 @@ run_retrace() {
|
||||
fi
|
||||
|
||||
mkdir -p "${result_dir}"
|
||||
"${ADB}" install -r "${apk_file}"
|
||||
"${ADB}" install -r "$(host_path_for_adb "${apk_file}")"
|
||||
copy_fixture_to_app
|
||||
"${ADB}" shell am force-stop "${package_name}"
|
||||
adb_device_path shell am force-stop "${package_name}"
|
||||
"${ADB}" logcat -c
|
||||
set -- am start -W -a top.mobilegl.plugin.TRACE_REPLAY \
|
||||
-n "${package_name}/top.mobilegl.plugin.trace.TraceReplayActivity" \
|
||||
@@ -240,14 +252,14 @@ run_retrace() {
|
||||
--ei crop_y "${crop_y}" \
|
||||
--ei crop_width "${crop_width}" \
|
||||
--ei crop_height "${crop_height}"
|
||||
"${ADB}" shell "$@"
|
||||
adb_device_path shell "$@"
|
||||
|
||||
app_exited=0
|
||||
for _ in $(seq 1 "${timeout_seconds}"); do
|
||||
if "${ADB}" shell run-as "${package_name}" ls "${app_dir}/output/result.json" >/dev/null 2>&1; then
|
||||
if adb_device_path shell run-as "${package_name}" ls "${app_dir}/output/result.json" >/dev/null 2>&1; then
|
||||
break
|
||||
fi
|
||||
if ! "${ADB}" shell pidof "${package_name}" >/dev/null 2>&1; then
|
||||
if ! adb_device_path shell pidof "${package_name}" >/dev/null 2>&1; then
|
||||
app_exited=1
|
||||
break
|
||||
fi
|
||||
@@ -255,7 +267,7 @@ run_retrace() {
|
||||
done
|
||||
|
||||
collect_run_diagnostics "${result_dir}"
|
||||
if ! "${ADB}" shell run-as "${package_name}" ls "${app_dir}/output/result.json" >/dev/null 2>&1; then
|
||||
if ! adb_device_path shell run-as "${package_name}" ls "${app_dir}/output/result.json" >/dev/null 2>&1; then
|
||||
if [ "${app_exited}" -eq 1 ]; then
|
||||
echo "trace-replay-ci.sh: app process exited before result.json was created" >&2
|
||||
else
|
||||
@@ -275,7 +287,7 @@ run_retrace() {
|
||||
cat "${result_dir}/app-files.txt" >&2 || true
|
||||
exit 1
|
||||
fi
|
||||
"${ADB}" exec-out run-as "${package_name}" cat "${app_dir}/output/result.json" > "${result_dir}/result.json"
|
||||
adb_device_path exec-out run-as "${package_name}" cat "${app_dir}/output/result.json" > "${result_dir}/result.json"
|
||||
cat "${result_dir}/result.json"
|
||||
copy_app_artifact "${app_dir}/output/actual.png" "${result_dir}/${safe_case}-${backend}-actual.png"
|
||||
copy_app_artifact "${app_dir}/output/${safe_case}-diff.png" "${result_dir}/${safe_case}-${backend}-diff.png"
|
||||
|
||||
@@ -444,6 +444,10 @@ add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-xaero-minimap-in-worl
|
||||
TARGET_CALL 2553500
|
||||
WIDTH 854
|
||||
HEIGHT 480
|
||||
CROP_X 0
|
||||
CROP_Y 10
|
||||
CROP_WIDTH 140
|
||||
CROP_HEIGHT 158
|
||||
)
|
||||
|
||||
add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-xaero-world-map-in-world
|
||||
|
||||
@@ -13,6 +13,18 @@ const CASES = [
|
||||
"minecraft-1.21.4-main-menu",
|
||||
"minecraft-1.21.4-in-world",
|
||||
"minecraft-1.21.4-fabric-sodium-in-world",
|
||||
"minecraft-1.21.4-fabric-common-mods-in-world",
|
||||
"minecraft-1.21.4-fabric-common-mods-inventory",
|
||||
"minecraft-1.21.4-fabric-rei-inventory",
|
||||
"minecraft-1.21.4-fabric-xaero-minimap-in-world",
|
||||
"minecraft-1.21.4-fabric-xaero-world-map-in-world",
|
||||
"minecraft-1.21.4-fabric-journeymap-in-world",
|
||||
"minecraft-1.21.4-fabric-modernui-inventory",
|
||||
"minecraft-1.21.4-fabric-rei-inventory-normal-world",
|
||||
"minecraft-1.21.4-fabric-xaero-minimap-in-world-normal-world",
|
||||
"minecraft-1.21.4-fabric-xaero-world-map-in-world-normal-world",
|
||||
"minecraft-1.21.4-fabric-journeymap-in-world-normal-world",
|
||||
"minecraft-1.21.4-fabric-modernui-inventory-normal-world",
|
||||
"minecraft-1.21.4-fabric-iris-bsl-in-world",
|
||||
"minecraft-1.21.4-fabric-iris-makeup-ultrafast-in-world",
|
||||
"minecraft-1.21.4-fabric-iris-super-duper-vanilla-in-world",
|
||||
|
||||
@@ -0,0 +1,280 @@
|
||||
#!/usr/bin/env python3
|
||||
import argparse
|
||||
import json
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
FIXTURES = ROOT / "tools" / "trace_replay" / "fixtures"
|
||||
RESULT_ROOT = ROOT / ".trace-work" / "android-retrace-result"
|
||||
FIXTURE_ROOT = ROOT / ".trace-work" / "android-retrace-fixture"
|
||||
SUMMARY_DIR = ROOT / ".trace-work" / "android-retrace-summary"
|
||||
SUMMARY_HTML = "mobilegl-android-retrace-overview.html"
|
||||
|
||||
BACKENDS = {
|
||||
"DirectGLES": {
|
||||
"apk": ROOT / "android-plugin" / "app" / "build" / "outputs" / "apk" / "esprytTrace" / "debug" / "MobileGL-EsprytTrace-debug.apk",
|
||||
"package": "top.mobilegl.plugin.espryt.trace",
|
||||
"use_angle": False,
|
||||
"use_pbuffer": False,
|
||||
},
|
||||
"DirectVulkan": {
|
||||
"apk": ROOT / "android-plugin" / "app" / "build" / "outputs" / "apk" / "magmaTrace" / "debug" / "MobileGL-MagmaTrace-debug.apk",
|
||||
"package": "top.mobilegl.plugin.magma.trace",
|
||||
"use_angle": False,
|
||||
"use_pbuffer": False,
|
||||
},
|
||||
}
|
||||
|
||||
CASES = [
|
||||
{
|
||||
"name": "OpenRA",
|
||||
"trace_archive": "openra.tgz",
|
||||
"trace_file": "openra.trace",
|
||||
"golden": "openra.0000031249.png",
|
||||
"target_call": 31249,
|
||||
"width": 640,
|
||||
"height": 480,
|
||||
"crop_x": 1,
|
||||
"crop_y": 1,
|
||||
"crop_width": 638,
|
||||
"crop_height": 478,
|
||||
"timeout_seconds": 180,
|
||||
},
|
||||
{"name": "minecraft-1.21.4-startup", "golden": "minecraft-1.21.4-startup.0000092195.png", "target_call": 92195, "timeout_seconds": 180},
|
||||
{"name": "minecraft-1.21.4-main-menu", "golden": "minecraft-1.21.4-main-menu.0000481787.png", "alternate_golden": "minecraft-1.21.4-main-menu.0000481787-mali.png", "target_call": 481787, "timeout_seconds": 180},
|
||||
{"name": "minecraft-1.21.4-in-world", "golden": "minecraft-1.21.4-in-world.0000280000.png", "target_call": 280000, "timeout_seconds": 900},
|
||||
{"name": "minecraft-1.21.4-fabric-sodium-in-world", "golden": "minecraft-1.21.4-fabric-sodium-in-world.0000923340.png", "target_call": 923340, "timeout_seconds": 1800},
|
||||
{"name": "minecraft-1.21.4-fabric-common-mods-in-world", "golden": "minecraft-1.21.4-fabric-common-mods-in-world.0000522084.png", "target_call": 522084, "timeout_seconds": 1800},
|
||||
{"name": "minecraft-1.21.4-fabric-common-mods-inventory", "golden": "minecraft-1.21.4-fabric-common-mods-inventory.0000728558.png", "target_call": 728558, "timeout_seconds": 1800},
|
||||
{"name": "minecraft-1.21.4-fabric-rei-inventory", "golden": "minecraft-1.21.4-fabric-rei-inventory.0005431826.png", "target_call": 5431826, "timeout_seconds": 1800},
|
||||
{"name": "minecraft-1.21.4-fabric-xaero-minimap-in-world", "golden": "minecraft-1.21.4-fabric-xaero-minimap-in-world.0002553500.png", "target_call": 2553500, "crop_y": 10, "crop_width": 140, "crop_height": 158, "timeout_seconds": 1800},
|
||||
{"name": "minecraft-1.21.4-fabric-xaero-world-map-in-world", "golden": "minecraft-1.21.4-fabric-xaero-world-map-in-world.0001598209.png", "target_call": 1598209, "timeout_seconds": 1800},
|
||||
{"name": "minecraft-1.21.4-fabric-journeymap-in-world", "golden": "minecraft-1.21.4-fabric-journeymap-in-world.0002632392.png", "target_call": 2632392, "timeout_seconds": 1800},
|
||||
{"name": "minecraft-1.21.4-fabric-modernui-inventory", "golden": "minecraft-1.21.4-fabric-modernui-inventory.0004907381.png", "target_call": 4907381, "timeout_seconds": 1800},
|
||||
{"name": "minecraft-1.21.4-fabric-rei-inventory-normal-world", "golden": "minecraft-1.21.4-fabric-rei-inventory-normal-world.0006599207.png", "target_call": 6599207, "timeout_seconds": 1800},
|
||||
{"name": "minecraft-1.21.4-fabric-xaero-minimap-in-world-normal-world", "golden": "minecraft-1.21.4-fabric-xaero-minimap-in-world-normal-world.0003893975.png", "target_call": 3893975, "crop_y": 10, "crop_width": 140, "crop_height": 158, "timeout_seconds": 1800},
|
||||
{"name": "minecraft-1.21.4-fabric-xaero-world-map-in-world-normal-world", "golden": "minecraft-1.21.4-fabric-xaero-world-map-in-world-normal-world.0002099794.png", "target_call": 2099794, "timeout_seconds": 1800},
|
||||
{"name": "minecraft-1.21.4-fabric-journeymap-in-world-normal-world", "golden": "minecraft-1.21.4-fabric-journeymap-in-world-normal-world.0005099482.png", "target_call": 5099482, "timeout_seconds": 1800},
|
||||
{"name": "minecraft-1.21.4-fabric-modernui-inventory-normal-world", "golden": "minecraft-1.21.4-fabric-modernui-inventory-normal-world.0008585354.png", "target_call": 8585354, "timeout_seconds": 1800},
|
||||
{"name": "minecraft-1.21.4-fabric-iris-bsl-in-world", "golden": "minecraft-1.21.4-fabric-iris-bsl-in-world.0000110725.png", "alternate_golden": "minecraft-1.21.4-fabric-iris-bsl-in-world.0000110725-mali.png", "target_call": 110725, "timeout_seconds": 900},
|
||||
{"name": "minecraft-1.21.4-fabric-iris-makeup-ultrafast-in-world", "golden": "minecraft-1.21.4-fabric-iris-makeup-ultrafast-in-world.0000095322.png", "target_call": 95322, "timeout_seconds": 900},
|
||||
{"name": "minecraft-1.21.4-fabric-iris-super-duper-vanilla-in-world", "golden": "minecraft-1.21.4-fabric-iris-super-duper-vanilla-in-world.0000141559.png", "target_call": 141559, "timeout_seconds": 900},
|
||||
{"name": "minecraft-1.21.4-fabric-iris-sundial-lite-in-world", "golden": "minecraft-1.21.4-fabric-iris-sundial-lite-in-world.0000150023.png", "target_call": 150023, "timeout_seconds": 900},
|
||||
{"name": "minecraft-1.21.4-fabric-iris-complementary-reimagined-in-world", "golden": "minecraft-1.21.4-fabric-iris-complementary-reimagined-in-world.0000151297.png", "target_call": 151297, "timeout_seconds": 900},
|
||||
{"name": "minecraft-1.21.4-fabric-iris-complementary-unbound-in-world", "golden": "minecraft-1.21.4-fabric-iris-complementary-unbound-in-world.0000146559.png", "target_call": 146559, "timeout_seconds": 900},
|
||||
{"name": "minecraft-1.21.4-fabric-iris-mellow-in-world", "golden": "minecraft-1.21.4-fabric-iris-mellow-in-world.0000096143.png", "target_call": 96143, "timeout_seconds": 900},
|
||||
{"name": "minecraft-1.21.4-fabric-iris-nostalgia-in-world", "golden": "minecraft-1.21.4-fabric-iris-nostalgia-in-world.0000153808-linux-mesa.png", "alternate_golden": "minecraft-1.21.4-fabric-iris-nostalgia-in-world.0000153808.png", "target_call": 153808, "timeout_seconds": 900},
|
||||
{"name": "minecraft-1.21.4-fabric-iris-bliss-in-world", "golden": "minecraft-1.21.4-fabric-iris-bliss-in-world.0000113511.png", "target_call": 113511, "timeout_seconds": 900},
|
||||
{"name": "minecraft-1.21.4-fabric-iris-chocapic-v6-lite-in-world", "golden": "minecraft-1.21.4-fabric-iris-chocapic-v6-lite-in-world.0000125124-linux-mesa.png", "target_call": 125124, "timeout_seconds": 900},
|
||||
{"name": "minecraft-1.21.4-fabric-iris-iterationt-in-world", "golden": "minecraft-1.21.4-fabric-iris-iterationt-in-world.0000110538.png", "target_call": 110538, "timeout_seconds": 900},
|
||||
{"name": "minecraft-1.21.4-fabric-iris-iterationt-nodsa-in-world", "golden": "minecraft-1.21.4-fabric-iris-iterationt-nodsa-in-world.0000115019.png", "target_call": 115019, "timeout_seconds": 900},
|
||||
{"name": "minecraft-1.21.4-fabric-iris-photon-v1.1-in-world", "golden": "minecraft-1.21.4-fabric-iris-photon-v1.1-in-world.0000159866.png", "target_call": 159866, "timeout_seconds": 900},
|
||||
{"name": "minecraft-1.21.4-fabric-iris-photon-v1.3b-in-world", "golden": "minecraft-1.21.4-fabric-iris-photon-v1.3b-in-world.0000172128.png", "target_call": 172128, "timeout_seconds": 900},
|
||||
{"name": "minecraft-1.21.4-fabric-iris-derivative-main-d24.4.14-in-world", "golden": "minecraft-1.21.4-fabric-iris-derivative-main-d24.4.14-in-world.0000145353.png", "target_call": 145353, "timeout_seconds": 900},
|
||||
]
|
||||
|
||||
|
||||
def safe_case(name):
|
||||
return "".join(ch if ch.isalnum() or ch in "._-" else "_" for ch in name)
|
||||
|
||||
|
||||
def is_lfs_pointer(path):
|
||||
return path.exists() and path.read_bytes()[:80].startswith(b"version https://git-lfs.github.com/spec/v1")
|
||||
|
||||
|
||||
def bash_path(path):
|
||||
path = Path(path).resolve()
|
||||
drive = path.drive.rstrip(":").lower()
|
||||
parts = path.parts[1:]
|
||||
return "/" + drive + "/" + "/".join(parts)
|
||||
|
||||
|
||||
def case_with_defaults(case):
|
||||
merged = {
|
||||
"trace_archive": f"{case['name']}.tgz",
|
||||
"trace_file": "trace.trace",
|
||||
"width": 854,
|
||||
"height": 480,
|
||||
"ssim_threshold": "0.99",
|
||||
"crop_x": 0,
|
||||
"crop_y": 0,
|
||||
"crop_width": 0,
|
||||
"crop_height": 0,
|
||||
"timeout_seconds": 900,
|
||||
}
|
||||
merged.update(case)
|
||||
return merged
|
||||
|
||||
|
||||
def mark_skipped(case, backend, reason):
|
||||
result_dir = RESULT_ROOT / f"{safe_case(case['name'])}-{backend}"
|
||||
result_dir.mkdir(parents=True, exist_ok=True)
|
||||
result = {
|
||||
"passed": False,
|
||||
"statusCode": 2,
|
||||
"message": reason,
|
||||
"tracePath": str(FIXTURES / case["trace_archive"]),
|
||||
"goldenPath": str(FIXTURES / case["golden"]),
|
||||
"alternateGoldenPaths": [],
|
||||
"matchedGoldenPath": "",
|
||||
"actualPath": "",
|
||||
"diffPath": "",
|
||||
"backend": backend,
|
||||
"targetCall": case["target_call"],
|
||||
"width": case["width"],
|
||||
"height": case["height"],
|
||||
"cropX": case["crop_x"],
|
||||
"cropY": case["crop_y"],
|
||||
"cropWidth": case["crop_width"],
|
||||
"cropHeight": case["crop_height"],
|
||||
"ssim": -1,
|
||||
"ssimThreshold": float(case["ssim_threshold"]),
|
||||
"mismatchPixels": -1,
|
||||
}
|
||||
(result_dir / "result.json").write_text(json.dumps(result, indent=2), encoding="utf-8")
|
||||
|
||||
|
||||
def copy_goldens(case, backend):
|
||||
result_dir = RESULT_ROOT / f"{safe_case(case['name'])}-{backend}"
|
||||
result_dir.mkdir(parents=True, exist_ok=True)
|
||||
for key, suffix in (("golden", "golden"), ("alternate_golden", "alternate-golden")):
|
||||
value = case.get(key)
|
||||
if not value:
|
||||
continue
|
||||
source = FIXTURES / value
|
||||
if source.exists() and source.stat().st_size > 0:
|
||||
shutil.copyfile(source, result_dir / f"{safe_case(case['name'])}-{backend}-{suffix}.png")
|
||||
|
||||
|
||||
def render_summary():
|
||||
SUMMARY_DIR.mkdir(parents=True, exist_ok=True)
|
||||
command = [
|
||||
"node",
|
||||
str(ROOT / "tools" / "trace_replay" / "render_retrace_summary.mjs"),
|
||||
"--input",
|
||||
str(RESULT_ROOT),
|
||||
"--output-dir",
|
||||
str(SUMMARY_DIR),
|
||||
"--title",
|
||||
"MobileGL Android retrace overview",
|
||||
"--group-label",
|
||||
"Android Device",
|
||||
"--html",
|
||||
SUMMARY_HTML,
|
||||
]
|
||||
subprocess.run(command, cwd=ROOT, check=True)
|
||||
shutil.copyfile(SUMMARY_DIR / SUMMARY_HTML, SUMMARY_DIR / "index.html")
|
||||
|
||||
|
||||
def run_case(case, backend):
|
||||
backend_info = BACKENDS[backend]
|
||||
trace_archive = FIXTURES / case["trace_archive"]
|
||||
golden = FIXTURES / case["golden"]
|
||||
alternate = FIXTURES / case["alternate_golden"] if case.get("alternate_golden") else None
|
||||
if not trace_archive.exists() or is_lfs_pointer(trace_archive):
|
||||
mark_skipped(case, backend, "SKIPPED_LFS_POINTER: trace archive is missing or still an LFS pointer")
|
||||
copy_goldens(case, backend)
|
||||
return 2
|
||||
if not golden.exists() or is_lfs_pointer(golden):
|
||||
mark_skipped(case, backend, "SKIPPED_LFS_POINTER: golden image is missing or still an LFS pointer")
|
||||
return 2
|
||||
if alternate is not None and (not alternate.exists() or is_lfs_pointer(alternate)):
|
||||
alternate = None
|
||||
|
||||
command = [
|
||||
"C:/Program Files/Git/bin/bash.exe",
|
||||
"android-plugin/trace-replay-ci.sh",
|
||||
"--apk-file",
|
||||
bash_path(backend_info["apk"]),
|
||||
"--package",
|
||||
backend_info["package"],
|
||||
"--backend",
|
||||
backend,
|
||||
"--result-root",
|
||||
bash_path(RESULT_ROOT),
|
||||
"--fixture-root",
|
||||
bash_path(FIXTURE_ROOT),
|
||||
"--case",
|
||||
case["name"],
|
||||
"--trace-archive",
|
||||
bash_path(trace_archive),
|
||||
"--trace-file",
|
||||
case["trace_file"],
|
||||
"--golden",
|
||||
bash_path(golden),
|
||||
"--target-call",
|
||||
str(case["target_call"]),
|
||||
"--width",
|
||||
str(case["width"]),
|
||||
"--height",
|
||||
str(case["height"]),
|
||||
"--ssim-threshold",
|
||||
str(case["ssim_threshold"]),
|
||||
"--crop-x",
|
||||
str(case["crop_x"]),
|
||||
"--crop-y",
|
||||
str(case["crop_y"]),
|
||||
"--crop-width",
|
||||
str(case["crop_width"]),
|
||||
"--crop-height",
|
||||
str(case["crop_height"]),
|
||||
"--timeout-seconds",
|
||||
str(case["timeout_seconds"]),
|
||||
]
|
||||
if alternate is not None:
|
||||
command[command.index("--target-call"):command.index("--target-call")] = ["--alternate-golden", bash_path(alternate)]
|
||||
if backend_info["use_pbuffer"]:
|
||||
command.append("--use-pbuffer")
|
||||
env = dict(**__import__("os").environ)
|
||||
env["PYTHON"] = "python"
|
||||
env["MSYS2_ARG_CONV_EXCL"] = "/data/*"
|
||||
if backend_info["use_angle"]:
|
||||
env["MOBILEGL_RETRACE_USE_ANGLE"] = "1"
|
||||
else:
|
||||
env.pop("MOBILEGL_RETRACE_USE_ANGLE", None)
|
||||
result = subprocess.run(command, cwd=ROOT, env=env)
|
||||
copy_goldens(case, backend)
|
||||
return result.returncode
|
||||
|
||||
|
||||
def parse_args():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--case", action="append", dest="cases", help="Case name to run; may be repeated.")
|
||||
parser.add_argument("--backend", action="append", choices=sorted(BACKENDS), help="Backend to run; may be repeated.")
|
||||
parser.add_argument("--all", action="store_true", help="Run every case in the APK workflow matrix.")
|
||||
parser.add_argument("--keep-results", action="store_true", help="Do not clear the previous result root.")
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def main():
|
||||
args = parse_args()
|
||||
selected_backends = args.backend or list(BACKENDS)
|
||||
selected_names = set(args.cases or [])
|
||||
selected_cases = [case_with_defaults(case) for case in CASES if args.all or case["name"] in selected_names]
|
||||
if not selected_cases:
|
||||
print("No cases selected. Use --all or --case NAME.", file=sys.stderr)
|
||||
return 2
|
||||
if not args.keep_results and RESULT_ROOT.exists():
|
||||
shutil.rmtree(RESULT_ROOT)
|
||||
RESULT_ROOT.mkdir(parents=True, exist_ok=True)
|
||||
failures = 0
|
||||
for case in selected_cases:
|
||||
for backend in selected_backends:
|
||||
print(f"=== Android retrace: {case['name']} / {backend} ===", flush=True)
|
||||
rc = run_case(case, backend)
|
||||
try:
|
||||
render_summary()
|
||||
except Exception as error:
|
||||
print(f"failed to render summary: {error}", file=sys.stderr)
|
||||
failures += 1
|
||||
if rc not in (0, 2):
|
||||
failures += 1
|
||||
return 1 if failures else 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user