zig-mobile-runner 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +484 -0
- package/CONTRIBUTING.md +42 -0
- package/FEATURES.md +112 -0
- package/LICENSE +21 -0
- package/README.md +255 -0
- package/SECURITY.md +34 -0
- package/build.zig +38 -0
- package/build.zig.zon +7 -0
- package/clients/README.md +144 -0
- package/clients/go/README.md +24 -0
- package/clients/go/examples/fake-session/main.go +93 -0
- package/clients/go/go.mod +3 -0
- package/clients/go/zmr/client.go +432 -0
- package/clients/kotlin/README.md +35 -0
- package/clients/kotlin/build.gradle.kts +35 -0
- package/clients/kotlin/settings.gradle.kts +15 -0
- package/clients/kotlin/src/main/kotlin/dev/zmr/FakeSession.kt +86 -0
- package/clients/kotlin/src/main/kotlin/dev/zmr/ZmrClient.kt +67 -0
- package/clients/python/README.md +29 -0
- package/clients/python/examples/fake_session.py +48 -0
- package/clients/python/pyproject.toml +13 -0
- package/clients/python/zmr_client.py +202 -0
- package/clients/rust/Cargo.lock +107 -0
- package/clients/rust/Cargo.toml +10 -0
- package/clients/rust/README.md +19 -0
- package/clients/rust/examples/fake_session.rs +70 -0
- package/clients/rust/src/lib.rs +461 -0
- package/clients/swift/Package.swift +16 -0
- package/clients/swift/README.md +36 -0
- package/clients/swift/Sources/ZMRClient/ZMRClient.swift +114 -0
- package/clients/swift/Sources/ZMRFakeSession/main.swift +86 -0
- package/clients/typescript/README.md +34 -0
- package/clients/typescript/examples/fake-session.mjs +36 -0
- package/clients/typescript/index.d.ts +144 -0
- package/clients/typescript/index.mjs +192 -0
- package/clients/typescript/package.json +8 -0
- package/docs/adr/0001-agent-native-runner-boundary.md +31 -0
- package/docs/adr/0002-app-local-zmr-contract.md +39 -0
- package/docs/adr/0003-ios-simulator-xctest-shim.md +41 -0
- package/docs/adr/0004-benchmark-claims-and-baseline-collection.md +37 -0
- package/docs/adr/README.md +12 -0
- package/docs/ai-agents.md +156 -0
- package/docs/app-integration.md +316 -0
- package/docs/benchmarking.md +275 -0
- package/docs/client-installation.md +141 -0
- package/docs/clients.md +98 -0
- package/docs/config.md +175 -0
- package/docs/demo.md +259 -0
- package/docs/dsl.md +57 -0
- package/docs/install.md +233 -0
- package/docs/market-positioning.md +70 -0
- package/docs/npm.md +359 -0
- package/docs/protocol-fixtures/README.md +8 -0
- package/docs/protocol-fixtures/core-session.requests.jsonl +8 -0
- package/docs/protocol-fixtures/core-session.responses.jsonl +8 -0
- package/docs/protocol-versioning.md +65 -0
- package/docs/protocol.md +560 -0
- package/docs/publication.md +77 -0
- package/docs/release-audit.md +99 -0
- package/docs/release-candidate.md +111 -0
- package/docs/release-evidence.md +188 -0
- package/docs/release-notes-template.md +58 -0
- package/docs/roadmap.md +334 -0
- package/docs/scenario-authoring.md +88 -0
- package/docs/shipping.md +170 -0
- package/docs/trace-privacy.md +88 -0
- package/docs/troubleshooting.md +256 -0
- package/examples/android-app-auth-probe.json +89 -0
- package/examples/android-app-error-state.json +13 -0
- package/examples/android-app-login-smoke.json +192 -0
- package/examples/android-app-onboarding.json +12 -0
- package/examples/android-app-referral-deep-link.json +12 -0
- package/examples/android-shim-smoke.json +19 -0
- package/examples/demo-failure.json +12 -0
- package/examples/demo-fake.json +14 -0
- package/examples/ios-dev-client-open-link.json +26 -0
- package/examples/ios-dev-client-route-snapshot.json +24 -0
- package/examples/ios-shim-smoke.json +23 -0
- package/examples/ios-smoke.json +9 -0
- package/go.work +3 -0
- package/npm/agents.mjs +183 -0
- package/npm/app-config.mjs +95 -0
- package/npm/build-zmr.mjs +21 -0
- package/npm/commands.mjs +104 -0
- package/npm/generated-files.mjs +50 -0
- package/npm/index.mjs +75 -0
- package/npm/init-app.mjs +80 -0
- package/npm/package-scripts.mjs +72 -0
- package/npm/postinstall.mjs +21 -0
- package/npm/scaffold.mjs +179 -0
- package/npm/scenarios.mjs +93 -0
- package/npm/setup.mjs +69 -0
- package/npm/wizard.mjs +117 -0
- package/npm/zmr.mjs +23 -0
- package/package.json +114 -0
- package/prebuilds/darwin-arm64/zmr +0 -0
- package/prebuilds/darwin-x64/zmr +0 -0
- package/prebuilds/linux-arm64/zmr +0 -0
- package/prebuilds/linux-x64/zmr +0 -0
- package/schemas/README.md +26 -0
- package/schemas/action-result.schema.json +27 -0
- package/schemas/capabilities-output.schema.json +98 -0
- package/schemas/devices-output.schema.json +25 -0
- package/schemas/doctor-output.schema.json +51 -0
- package/schemas/explain-output.schema.json +51 -0
- package/schemas/import-output.schema.json +23 -0
- package/schemas/init-output.schema.json +71 -0
- package/schemas/json-rpc.schema.json +55 -0
- package/schemas/release-manifest.schema.json +43 -0
- package/schemas/release-readiness-output.schema.json +127 -0
- package/schemas/run-output.schema.json +43 -0
- package/schemas/scenario.schema.json +128 -0
- package/schemas/schemas-output.schema.json +26 -0
- package/schemas/semantic-snapshot.schema.json +116 -0
- package/schemas/snapshot.schema.json +60 -0
- package/schemas/trace-event.schema.json +14 -0
- package/schemas/trace-manifest.schema.json +59 -0
- package/schemas/validate-output.schema.json +42 -0
- package/schemas/version-output.schema.json +23 -0
- package/schemas/zmr-config.schema.json +75 -0
- package/scripts/android-emulator.sh +126 -0
- package/scripts/assert-ios-physical-ready.sh +213 -0
- package/scripts/benchmark-command.sh +307 -0
- package/scripts/benchmark.sh +359 -0
- package/scripts/benchmark_gate.py +117 -0
- package/scripts/benchmark_result_row.py +88 -0
- package/scripts/compare-benchmarks.py +288 -0
- package/scripts/create-android-demo-app.sh +342 -0
- package/scripts/create-ios-demo-app.sh +261 -0
- package/scripts/demo-android-real.sh +232 -0
- package/scripts/demo-ios-real.sh +270 -0
- package/scripts/demo.sh +464 -0
- package/scripts/device-matrix.sh +338 -0
- package/scripts/ensure-ios-shim-target.rb +237 -0
- package/scripts/install-android-shim.sh +281 -0
- package/scripts/install-ios-shim.sh +589 -0
- package/scripts/pilot-gate.sh +560 -0
- package/scripts/release-readiness.py +838 -0
- package/scripts/release-readiness.sh +91 -0
- package/scripts/run-android-pilot.sh +561 -0
- package/scripts/run-ios-pilot.sh +509 -0
- package/shims/android/README.md +21 -0
- package/shims/android/ZMRShimInstrumentedTest.java +152 -0
- package/shims/android/protocol.md +18 -0
- package/shims/ios/README.md +50 -0
- package/shims/ios/ZMRShim.swift +110 -0
- package/shims/ios/ZMRShimUITestCase.swift +475 -0
- package/shims/ios/protocol.md +74 -0
- package/skills/zmr-mobile-testing/SKILL.md +127 -0
- package/src/android.zig +344 -0
- package/src/android_device_info.zig +99 -0
- package/src/android_emulator.zig +154 -0
- package/src/android_screen_recording.zig +112 -0
- package/src/android_shell.zig +112 -0
- package/src/bundle.zig +124 -0
- package/src/bundle_redaction.zig +272 -0
- package/src/bundle_tar.zig +123 -0
- package/src/cli_devices.zig +97 -0
- package/src/cli_doctor.zig +114 -0
- package/src/cli_import.zig +70 -0
- package/src/cli_info.zig +39 -0
- package/src/cli_init.zig +72 -0
- package/src/cli_output.zig +467 -0
- package/src/cli_run.zig +259 -0
- package/src/cli_serve.zig +287 -0
- package/src/cli_trace.zig +111 -0
- package/src/cli_validate.zig +41 -0
- package/src/command.zig +211 -0
- package/src/config.zig +305 -0
- package/src/config_diagnostics.zig +212 -0
- package/src/config_paths.zig +49 -0
- package/src/device_registry.zig +37 -0
- package/src/doctor.zig +412 -0
- package/src/doctor_hints.zig +52 -0
- package/src/errors.zig +55 -0
- package/src/fake_device.zig +163 -0
- package/src/health.zig +28 -0
- package/src/importer.zig +343 -0
- package/src/importer_json.zig +100 -0
- package/src/importer_model.zig +103 -0
- package/src/ios.zig +399 -0
- package/src/ios_devices.zig +219 -0
- package/src/ios_lifecycle.zig +72 -0
- package/src/ios_shim.zig +242 -0
- package/src/ios_snapshot.zig +20 -0
- package/src/json_fields.zig +80 -0
- package/src/json_rpc.zig +150 -0
- package/src/json_rpc_methods.zig +318 -0
- package/src/json_rpc_observation.zig +31 -0
- package/src/json_rpc_params.zig +52 -0
- package/src/json_rpc_protocol.zig +110 -0
- package/src/json_rpc_trace.zig +73 -0
- package/src/main.zig +135 -0
- package/src/mcp.zig +234 -0
- package/src/mcp_protocol.zig +64 -0
- package/src/mcp_trace.zig +83 -0
- package/src/report.zig +346 -0
- package/src/report_html.zig +63 -0
- package/src/report_values.zig +27 -0
- package/src/run_options.zig +152 -0
- package/src/runner.zig +280 -0
- package/src/runner_actions.zig +109 -0
- package/src/runner_config.zig +6 -0
- package/src/runner_diagnostics.zig +268 -0
- package/src/runner_events.zig +170 -0
- package/src/runner_native.zig +88 -0
- package/src/runner_waits.zig +300 -0
- package/src/scaffold.zig +472 -0
- package/src/scenario.zig +346 -0
- package/src/scenario_fields.zig +50 -0
- package/src/schema_registry.zig +53 -0
- package/src/selector.zig +84 -0
- package/src/semantic.zig +171 -0
- package/src/trace.zig +315 -0
- package/src/trace_json.zig +340 -0
- package/src/trace_summary.zig +218 -0
- package/src/trace_summary_diagnostic.zig +202 -0
- package/src/types.zig +120 -0
- package/src/uiautomator.zig +164 -0
- package/src/validation.zig +187 -0
- package/src/version.zig +22 -0
- package/viewer/app.js +373 -0
- package/viewer/index.html +126 -0
- package/viewer/parser.js +233 -0
- package/viewer/styles.css +585 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
if [ -z "${ZMR_BASH_BOOTSTRAP:-}" ]; then
|
|
3
|
+
ZMR_BASH_BOOTSTRAP=1
|
|
4
|
+
export ZMR_BASH_BOOTSTRAP
|
|
5
|
+
SCRIPT_DIR="$(cd -P "$(dirname "$0")" && pwd -P)"
|
|
6
|
+
ROOT="$(cd "$SCRIPT_DIR/.." && pwd -P)"
|
|
7
|
+
if [ -z "${TMPDIR:-}" ] || [ ! -w "${TMPDIR:-/nonexistent}" ]; then
|
|
8
|
+
TMPDIR="$ROOT/traces/tmp"
|
|
9
|
+
fi
|
|
10
|
+
mkdir -p "$TMPDIR"
|
|
11
|
+
export TMPDIR
|
|
12
|
+
exec /usr/bin/env bash "$0" "$@"
|
|
13
|
+
fi
|
|
14
|
+
|
|
15
|
+
set -euo pipefail
|
|
16
|
+
|
|
17
|
+
CALLER_CWD="$(pwd -P)"
|
|
18
|
+
# Some sandboxed environments do not allow writing to the default temp directory
|
|
19
|
+
# (/var/folders, /tmp). Use a caller-local TMPDIR so heredocs/mktemp work.
|
|
20
|
+
if [[ -z "${TMPDIR:-}" || ! -w "${TMPDIR:-/nonexistent}" ]]; then
|
|
21
|
+
TMPDIR="$CALLER_CWD/traces/tmp"
|
|
22
|
+
mkdir -p "$TMPDIR"
|
|
23
|
+
export TMPDIR
|
|
24
|
+
fi
|
|
25
|
+
|
|
26
|
+
EVIDENCE_FILES=()
|
|
27
|
+
TARGET="dev-preview"
|
|
28
|
+
JSON=0
|
|
29
|
+
|
|
30
|
+
usage() {
|
|
31
|
+
printf '%s\n' 'Usage:'
|
|
32
|
+
printf '%s\n' ' scripts/release-readiness.sh --evidence <evidence.jsonl> [--evidence <more.jsonl> ...] [--target dev-preview|production|market-claim] [--json]'
|
|
33
|
+
printf '%s\n' ''
|
|
34
|
+
printf '%s\n' 'Reads one or more release/pilot evidence JSONL files and reports whether the'
|
|
35
|
+
printf '%s\n' 'requested release claim is supported by concrete passed evidence.'
|
|
36
|
+
printf '%s\n' ''
|
|
37
|
+
printf '%s\n' 'Targets:'
|
|
38
|
+
printf '%s\n' ' dev-preview Requires local release gate plus public Android and iOS demos.'
|
|
39
|
+
printf '%s\n' ' production Requires dev-preview evidence plus repeated real app/device pilots.'
|
|
40
|
+
printf '%s\n' ' market-claim Requires production evidence plus same-device/app/build benchmark comparison.'
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
die() {
|
|
44
|
+
echo "error: $*" >&2
|
|
45
|
+
exit 2
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
require_value() {
|
|
49
|
+
local flag="$1"
|
|
50
|
+
local value="${2-}"
|
|
51
|
+
if [[ -z "$value" || "$value" == --* ]]; then
|
|
52
|
+
die "$flag requires a value"
|
|
53
|
+
fi
|
|
54
|
+
printf '%s\n' "$value"
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
while [[ $# -gt 0 ]]; do
|
|
58
|
+
case "$1" in
|
|
59
|
+
--evidence)
|
|
60
|
+
EVIDENCE_FILES+=("$(require_value "$1" "${2-}")")
|
|
61
|
+
shift 2
|
|
62
|
+
;;
|
|
63
|
+
--target)
|
|
64
|
+
TARGET="$(require_value "$1" "${2-}")"
|
|
65
|
+
shift 2
|
|
66
|
+
;;
|
|
67
|
+
--json)
|
|
68
|
+
JSON=1
|
|
69
|
+
shift
|
|
70
|
+
;;
|
|
71
|
+
-h|--help)
|
|
72
|
+
usage
|
|
73
|
+
exit 0
|
|
74
|
+
;;
|
|
75
|
+
*)
|
|
76
|
+
die "unknown argument: $1"
|
|
77
|
+
;;
|
|
78
|
+
esac
|
|
79
|
+
done
|
|
80
|
+
|
|
81
|
+
[[ "${#EVIDENCE_FILES[@]}" -gt 0 ]] || die "--evidence is required"
|
|
82
|
+
for evidence_file in "${EVIDENCE_FILES[@]}"; do
|
|
83
|
+
[[ -n "$evidence_file" ]] || die "--evidence requires a path"
|
|
84
|
+
if [[ ! -f "$evidence_file" && "$JSON" -eq 0 ]]; then
|
|
85
|
+
die "evidence file not found: $evidence_file"
|
|
86
|
+
fi
|
|
87
|
+
done
|
|
88
|
+
[[ "$TARGET" == "dev-preview" || "$TARGET" == "production" || "$TARGET" == "market-claim" ]] || die "--target must be dev-preview, production, or market-claim"
|
|
89
|
+
|
|
90
|
+
SCRIPT_DIR="$(cd -P "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"
|
|
91
|
+
python3 "$SCRIPT_DIR/release-readiness.py" "$TARGET" "$JSON" "${EVIDENCE_FILES[@]}"
|
|
@@ -0,0 +1,561 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
5
|
+
CALLER_CWD="$(pwd -P)"
|
|
6
|
+
cd "$ROOT"
|
|
7
|
+
|
|
8
|
+
# Some sandboxed environments do not allow writing to the default temp directory
|
|
9
|
+
# (/var/folders, /tmp). Use a repo-local TMPDIR so adb/mktemp/heredocs work.
|
|
10
|
+
if [[ -z "${TMPDIR:-}" || ! -w "${TMPDIR:-/nonexistent}" ]]; then
|
|
11
|
+
TMPDIR="$ROOT/traces/tmp"
|
|
12
|
+
mkdir -p "$TMPDIR"
|
|
13
|
+
export TMPDIR
|
|
14
|
+
fi
|
|
15
|
+
|
|
16
|
+
APP_ROOT="${APP_ROOT:-}"
|
|
17
|
+
DEVICE="${DEVICE:-emulator-5554}"
|
|
18
|
+
AVD="${AVD:-}"
|
|
19
|
+
TRACE_ROOT="${TRACE_ROOT:-$CALLER_CWD/traces/android-app-pilot-$(date +%Y%m%d-%H%M%S)}"
|
|
20
|
+
ZMR_BIN="${ZMR_BIN:-$(command -v zmr 2>/dev/null || printf '%s' "$ROOT/zig-out/bin/zmr")}"
|
|
21
|
+
ADB="${ADB:-adb}"
|
|
22
|
+
APK="${APK:-}"
|
|
23
|
+
SCENARIO="${SCENARIO:-}"
|
|
24
|
+
APP_ID="${APP_ID:-com.example.mobiletest}"
|
|
25
|
+
RUNS="${RUNS:-1}"
|
|
26
|
+
MIN_PASS_RATE="${MIN_PASS_RATE:-100}"
|
|
27
|
+
MAX_FAILURES="${MAX_FAILURES:-0}"
|
|
28
|
+
MAX_MEAN_MS="${MAX_MEAN_MS:-}"
|
|
29
|
+
MAX_P95_MS="${MAX_P95_MS:-}"
|
|
30
|
+
RESTORE_SNAPSHOT="${RESTORE_SNAPSHOT:-}"
|
|
31
|
+
DRY_RUN=0
|
|
32
|
+
SKIP_EMULATOR=0
|
|
33
|
+
SKIP_METRO=0
|
|
34
|
+
KEEP_RUNNING=0
|
|
35
|
+
RESET_EMULATOR=0
|
|
36
|
+
SCREEN_RECORD=0
|
|
37
|
+
STARTED_EMULATOR=0
|
|
38
|
+
METRO_PID=""
|
|
39
|
+
SCREEN_RECORD_PID=""
|
|
40
|
+
SCREEN_RECORD_REMOTE="/sdcard/zmr-pilot-screenrecord.mp4"
|
|
41
|
+
SCREEN_RECORD_LOCAL=""
|
|
42
|
+
|
|
43
|
+
usage() {
|
|
44
|
+
cat <<'USAGE'
|
|
45
|
+
Usage:
|
|
46
|
+
scripts/run-android-pilot.sh [options]
|
|
47
|
+
|
|
48
|
+
Runs a configurable Android sample-app pilot end to end:
|
|
49
|
+
1. build/validate zmr
|
|
50
|
+
2. boot or use an emulator
|
|
51
|
+
3. install the sample app test APK
|
|
52
|
+
4. optionally start the sample app's Metro environment
|
|
53
|
+
5. run auth and login smoke scenarios
|
|
54
|
+
6. generate reports and normal/redacted .zmrtrace bundles
|
|
55
|
+
|
|
56
|
+
Options:
|
|
57
|
+
--app-root <dir> Sample app repo containing .env.test and the debug APK.
|
|
58
|
+
--app-id <bundle> Application id. Default: com.example.mobiletest.
|
|
59
|
+
--apk <path> APK to install. Defaults to android/app/build/outputs/apk/debug/app-debug.apk.
|
|
60
|
+
--scenario <path> Optional ZMR scenario JSON to run. Defaults to the built-in Sample App flows.
|
|
61
|
+
--device <serial> Android serial. Default: emulator-5554.
|
|
62
|
+
--avd <name> AVD to boot when no device is attached. Defaults to first local AVD.
|
|
63
|
+
--trace-root <dir> Output directory. Default: traces/android-app-pilot-<timestamp>.
|
|
64
|
+
--zmr-bin <path> zmr binary. Default: ZMR_BIN, PATH zmr, then zig-out/bin/zmr.
|
|
65
|
+
--adb <path> adb path. Default: adb.
|
|
66
|
+
--runs <n> Run each flow n times. n=1 writes trace bundles; n>1 writes benchmark reports.
|
|
67
|
+
--min-pass-rate <pct> Repeated-run gate minimum. Default: 100.
|
|
68
|
+
--max-failures <n> Repeated-run gate maximum. Default: 0.
|
|
69
|
+
--max-mean-ms <ms> Optional repeated-run mean duration maximum.
|
|
70
|
+
--max-p95-ms <ms> Optional repeated-run p95 duration maximum.
|
|
71
|
+
--reset-emulator Kill the target emulator before booting/restoring it.
|
|
72
|
+
--restore-snapshot <name>
|
|
73
|
+
Boot the AVD from a named emulator snapshot.
|
|
74
|
+
--screen-record Capture a pilot-level MP4 with adb shell screenrecord.
|
|
75
|
+
--skip-emulator Require/use an already booted device.
|
|
76
|
+
--skip-metro Do not start Metro; assume it is already running.
|
|
77
|
+
--keep-running Leave Metro/emulator running when this script exits.
|
|
78
|
+
--dry-run Print the commands without executing them.
|
|
79
|
+
-h, --help Show this help.
|
|
80
|
+
|
|
81
|
+
Environment:
|
|
82
|
+
APP_ROOT, APP_ID, APK, DEVICE, AVD, TRACE_ROOT, ZMR_BIN, ADB, RUNS,
|
|
83
|
+
RESTORE_SNAPSHOT, MIN_PASS_RATE, MAX_FAILURES, MAX_MEAN_MS, MAX_P95_MS.
|
|
84
|
+
|
|
85
|
+
Notes:
|
|
86
|
+
Metro output is written to <trace-root>/metro.log and may contain app secrets.
|
|
87
|
+
Share the generated *-redacted.zmrtrace bundles, not raw Metro logs.
|
|
88
|
+
USAGE
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
die() {
|
|
92
|
+
echo "error: $*" >&2
|
|
93
|
+
exit 2
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
require_value() {
|
|
97
|
+
local flag="$1"
|
|
98
|
+
local value="${2-}"
|
|
99
|
+
if [[ -z "$value" || "$value" == --* ]]; then
|
|
100
|
+
die "$flag requires a value"
|
|
101
|
+
fi
|
|
102
|
+
printf '%s\n' "$value"
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
resolve_path_from_cwd() {
|
|
106
|
+
local value="$1"
|
|
107
|
+
local absolute dir base probe suffix
|
|
108
|
+
if [[ -z "$value" ]]; then
|
|
109
|
+
printf '\n'
|
|
110
|
+
return 0
|
|
111
|
+
fi
|
|
112
|
+
if [[ "$value" == /* ]]; then
|
|
113
|
+
absolute="$value"
|
|
114
|
+
else
|
|
115
|
+
absolute="$CALLER_CWD/$value"
|
|
116
|
+
fi
|
|
117
|
+
if [[ -d "$absolute" ]]; then
|
|
118
|
+
cd "$absolute" && pwd -P
|
|
119
|
+
return 0
|
|
120
|
+
fi
|
|
121
|
+
if [[ -e "$absolute" ]]; then
|
|
122
|
+
dir="$(dirname "$absolute")"
|
|
123
|
+
base="$(basename "$absolute")"
|
|
124
|
+
printf '%s/%s\n' "$(cd "$dir" && pwd -P)" "$base"
|
|
125
|
+
return 0
|
|
126
|
+
fi
|
|
127
|
+
dir="$(dirname "$absolute")"
|
|
128
|
+
base="$(basename "$absolute")"
|
|
129
|
+
if [[ -d "$dir" ]]; then
|
|
130
|
+
printf '%s/%s\n' "$(cd "$dir" && pwd -P)" "$base"
|
|
131
|
+
return 0
|
|
132
|
+
fi
|
|
133
|
+
probe="$absolute"
|
|
134
|
+
suffix=""
|
|
135
|
+
while [[ "$probe" != "/" && ! -e "$probe" ]]; do
|
|
136
|
+
suffix="/$(basename "$probe")$suffix"
|
|
137
|
+
probe="$(dirname "$probe")"
|
|
138
|
+
done
|
|
139
|
+
if [[ -d "$probe" ]]; then
|
|
140
|
+
printf '%s%s\n' "$(cd "$probe" && pwd -P)" "$suffix"
|
|
141
|
+
return 0
|
|
142
|
+
fi
|
|
143
|
+
while [[ "$absolute" == *"/./"* ]]; do
|
|
144
|
+
absolute="${absolute//\/.\//\/}"
|
|
145
|
+
done
|
|
146
|
+
printf '%s\n' "$absolute"
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
resolve_command_path_from_cwd() {
|
|
150
|
+
local value="$1"
|
|
151
|
+
if [[ -z "$value" || "$value" != */* ]]; then
|
|
152
|
+
printf '%s\n' "$value"
|
|
153
|
+
else
|
|
154
|
+
resolve_path_from_cwd "$value"
|
|
155
|
+
fi
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
quote_cmd() {
|
|
159
|
+
local quoted=()
|
|
160
|
+
local arg
|
|
161
|
+
for arg in "$@"; do
|
|
162
|
+
quoted+=("$(printf '%q' "$arg")")
|
|
163
|
+
done
|
|
164
|
+
printf '%s\n' "${quoted[*]}"
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
run() {
|
|
168
|
+
echo "+ $(quote_cmd "$@")"
|
|
169
|
+
if [[ "$DRY_RUN" -eq 0 ]]; then
|
|
170
|
+
"$@"
|
|
171
|
+
fi
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
capture() {
|
|
175
|
+
if [[ "$DRY_RUN" -eq 1 ]]; then
|
|
176
|
+
echo ""
|
|
177
|
+
else
|
|
178
|
+
"$@"
|
|
179
|
+
fi
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
wait_for_device() {
|
|
183
|
+
echo "+ wait for adb device $DEVICE"
|
|
184
|
+
if [[ "$DRY_RUN" -eq 1 ]]; then
|
|
185
|
+
return
|
|
186
|
+
fi
|
|
187
|
+
for _ in $(seq 1 120); do
|
|
188
|
+
if "$ADB" devices | awk -v serial="$DEVICE" '$1 == serial && $2 == "device" { found = 1 } END { exit found ? 0 : 1 }'; then
|
|
189
|
+
return
|
|
190
|
+
fi
|
|
191
|
+
sleep 2
|
|
192
|
+
done
|
|
193
|
+
die "Android device did not appear: $DEVICE"
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
wait_for_boot() {
|
|
197
|
+
echo "+ wait for Android boot completion on $DEVICE"
|
|
198
|
+
if [[ "$DRY_RUN" -eq 1 ]]; then
|
|
199
|
+
return
|
|
200
|
+
fi
|
|
201
|
+
for _ in $(seq 1 120); do
|
|
202
|
+
booted="$("$ADB" -s "$DEVICE" shell getprop sys.boot_completed 2>/dev/null | tr -d '\r')"
|
|
203
|
+
if [[ "$booted" == "1" ]]; then
|
|
204
|
+
return
|
|
205
|
+
fi
|
|
206
|
+
sleep 2
|
|
207
|
+
done
|
|
208
|
+
die "Android device did not finish booting: $DEVICE"
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
cleanup() {
|
|
212
|
+
if [[ "$DRY_RUN" -eq 1 ]]; then
|
|
213
|
+
return
|
|
214
|
+
fi
|
|
215
|
+
if [[ -n "$SCREEN_RECORD_PID" ]]; then
|
|
216
|
+
kill "$SCREEN_RECORD_PID" >/dev/null 2>&1 || true
|
|
217
|
+
wait "$SCREEN_RECORD_PID" >/dev/null 2>&1 || true
|
|
218
|
+
"$ADB" -s "$DEVICE" pull "$SCREEN_RECORD_REMOTE" "$SCREEN_RECORD_LOCAL" >/dev/null 2>&1 || true
|
|
219
|
+
"$ADB" -s "$DEVICE" shell rm -f "$SCREEN_RECORD_REMOTE" >/dev/null 2>&1 || true
|
|
220
|
+
fi
|
|
221
|
+
if [[ -n "$METRO_PID" ]]; then
|
|
222
|
+
kill "$METRO_PID" >/dev/null 2>&1 || true
|
|
223
|
+
wait "$METRO_PID" >/dev/null 2>&1 || true
|
|
224
|
+
fi
|
|
225
|
+
if [[ "$KEEP_RUNNING" -eq 1 ]]; then
|
|
226
|
+
return
|
|
227
|
+
fi
|
|
228
|
+
if [[ "$STARTED_EMULATOR" -eq 1 ]]; then
|
|
229
|
+
"$ADB" -s "$DEVICE" emu kill >/dev/null 2>&1 || true
|
|
230
|
+
fi
|
|
231
|
+
}
|
|
232
|
+
trap cleanup EXIT
|
|
233
|
+
|
|
234
|
+
start_screen_recording() {
|
|
235
|
+
if [[ "$SCREEN_RECORD" -ne 1 ]]; then
|
|
236
|
+
return 0
|
|
237
|
+
fi
|
|
238
|
+
SCREEN_RECORD_LOCAL="$TRACE_ROOT/screenrecord.mp4"
|
|
239
|
+
run "$ADB" -s "$DEVICE" shell rm -f "$SCREEN_RECORD_REMOTE"
|
|
240
|
+
echo "+ $(quote_cmd "$ADB" -s "$DEVICE" shell screenrecord "$SCREEN_RECORD_REMOTE")"
|
|
241
|
+
if [[ "$DRY_RUN" -eq 0 ]]; then
|
|
242
|
+
"$ADB" -s "$DEVICE" shell screenrecord "$SCREEN_RECORD_REMOTE" > "$TRACE_ROOT/screenrecord.log" 2>&1 &
|
|
243
|
+
SCREEN_RECORD_PID="$!"
|
|
244
|
+
fi
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
stop_screen_recording() {
|
|
248
|
+
if [[ "$SCREEN_RECORD" -ne 1 ]]; then
|
|
249
|
+
return 0
|
|
250
|
+
fi
|
|
251
|
+
if [[ "$DRY_RUN" -eq 1 ]]; then
|
|
252
|
+
echo "+ stop adb screenrecord"
|
|
253
|
+
run "$ADB" -s "$DEVICE" pull "$SCREEN_RECORD_REMOTE" "$TRACE_ROOT/screenrecord.mp4"
|
|
254
|
+
run "$ADB" -s "$DEVICE" shell rm -f "$SCREEN_RECORD_REMOTE"
|
|
255
|
+
return
|
|
256
|
+
fi
|
|
257
|
+
if [[ -n "$SCREEN_RECORD_PID" ]]; then
|
|
258
|
+
kill "$SCREEN_RECORD_PID" >/dev/null 2>&1 || true
|
|
259
|
+
wait "$SCREEN_RECORD_PID" >/dev/null 2>&1 || true
|
|
260
|
+
SCREEN_RECORD_PID=""
|
|
261
|
+
fi
|
|
262
|
+
run "$ADB" -s "$DEVICE" pull "$SCREEN_RECORD_REMOTE" "$SCREEN_RECORD_LOCAL"
|
|
263
|
+
run "$ADB" -s "$DEVICE" shell rm -f "$SCREEN_RECORD_REMOTE"
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
preflight_android_device() {
|
|
267
|
+
if [[ "$DRY_RUN" -eq 1 ]]; then
|
|
268
|
+
return 0
|
|
269
|
+
fi
|
|
270
|
+
if "$ADB" devices | awk -v serial="$DEVICE" '$1 == serial && $2 == "device" { found = 1 } END { exit found ? 0 : 1 }'; then
|
|
271
|
+
return 0
|
|
272
|
+
fi
|
|
273
|
+
echo "error: no Android device found: $DEVICE" >&2
|
|
274
|
+
echo "errorCode: setup.android.no_devices" >&2
|
|
275
|
+
echo "hint: run zmr doctor --json --adb $(printf '%q' "$ADB") and start/connect the requested device." >&2
|
|
276
|
+
"$ZMR_BIN" doctor --json --adb "$ADB" >&2 || true
|
|
277
|
+
exit 2
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
while [[ $# -gt 0 ]]; do
|
|
281
|
+
case "$1" in
|
|
282
|
+
--app-root)
|
|
283
|
+
APP_ROOT="$(require_value "$1" "${2-}")"
|
|
284
|
+
shift 2
|
|
285
|
+
;;
|
|
286
|
+
--app-id)
|
|
287
|
+
APP_ID="$(require_value "$1" "${2-}")"
|
|
288
|
+
shift 2
|
|
289
|
+
;;
|
|
290
|
+
--apk)
|
|
291
|
+
APK="$(require_value "$1" "${2-}")"
|
|
292
|
+
shift 2
|
|
293
|
+
;;
|
|
294
|
+
--scenario)
|
|
295
|
+
SCENARIO="$(require_value "$1" "${2-}")"
|
|
296
|
+
shift 2
|
|
297
|
+
;;
|
|
298
|
+
--device)
|
|
299
|
+
DEVICE="$(require_value "$1" "${2-}")"
|
|
300
|
+
shift 2
|
|
301
|
+
;;
|
|
302
|
+
--avd)
|
|
303
|
+
AVD="$(require_value "$1" "${2-}")"
|
|
304
|
+
shift 2
|
|
305
|
+
;;
|
|
306
|
+
--trace-root)
|
|
307
|
+
TRACE_ROOT="$(require_value "$1" "${2-}")"
|
|
308
|
+
shift 2
|
|
309
|
+
;;
|
|
310
|
+
--zmr-bin)
|
|
311
|
+
ZMR_BIN="$(require_value "$1" "${2-}")"
|
|
312
|
+
shift 2
|
|
313
|
+
;;
|
|
314
|
+
--adb)
|
|
315
|
+
ADB="$(require_value "$1" "${2-}")"
|
|
316
|
+
shift 2
|
|
317
|
+
;;
|
|
318
|
+
--runs)
|
|
319
|
+
RUNS="$(require_value "$1" "${2-}")"
|
|
320
|
+
shift 2
|
|
321
|
+
;;
|
|
322
|
+
--min-pass-rate)
|
|
323
|
+
MIN_PASS_RATE="$(require_value "$1" "${2-}")"
|
|
324
|
+
shift 2
|
|
325
|
+
;;
|
|
326
|
+
--max-failures)
|
|
327
|
+
MAX_FAILURES="$(require_value "$1" "${2-}")"
|
|
328
|
+
shift 2
|
|
329
|
+
;;
|
|
330
|
+
--max-mean-ms)
|
|
331
|
+
MAX_MEAN_MS="$(require_value "$1" "${2-}")"
|
|
332
|
+
shift 2
|
|
333
|
+
;;
|
|
334
|
+
--max-p95-ms)
|
|
335
|
+
MAX_P95_MS="$(require_value "$1" "${2-}")"
|
|
336
|
+
shift 2
|
|
337
|
+
;;
|
|
338
|
+
--reset-emulator)
|
|
339
|
+
RESET_EMULATOR=1
|
|
340
|
+
shift
|
|
341
|
+
;;
|
|
342
|
+
--restore-snapshot)
|
|
343
|
+
RESTORE_SNAPSHOT="$(require_value "$1" "${2-}")"
|
|
344
|
+
shift 2
|
|
345
|
+
;;
|
|
346
|
+
--screen-record)
|
|
347
|
+
SCREEN_RECORD=1
|
|
348
|
+
shift
|
|
349
|
+
;;
|
|
350
|
+
--skip-emulator)
|
|
351
|
+
SKIP_EMULATOR=1
|
|
352
|
+
shift
|
|
353
|
+
;;
|
|
354
|
+
--skip-metro)
|
|
355
|
+
SKIP_METRO=1
|
|
356
|
+
shift
|
|
357
|
+
;;
|
|
358
|
+
--keep-running)
|
|
359
|
+
KEEP_RUNNING=1
|
|
360
|
+
shift
|
|
361
|
+
;;
|
|
362
|
+
--dry-run)
|
|
363
|
+
DRY_RUN=1
|
|
364
|
+
shift
|
|
365
|
+
;;
|
|
366
|
+
-h|--help)
|
|
367
|
+
usage
|
|
368
|
+
exit 0
|
|
369
|
+
;;
|
|
370
|
+
*)
|
|
371
|
+
die "unknown argument: $1"
|
|
372
|
+
;;
|
|
373
|
+
esac
|
|
374
|
+
done
|
|
375
|
+
|
|
376
|
+
[[ -n "$DEVICE" ]] || die "--device cannot be empty"
|
|
377
|
+
[[ "$RUNS" =~ ^[0-9]+$ && "$RUNS" -ge 1 ]] || die "--runs must be a positive integer"
|
|
378
|
+
[[ "$MIN_PASS_RATE" =~ ^[0-9]+([.][0-9]+)?$ ]] || die "--min-pass-rate must be a non-negative number"
|
|
379
|
+
[[ "$MAX_FAILURES" =~ ^[0-9]+$ ]] || die "--max-failures must be a non-negative integer"
|
|
380
|
+
[[ -z "$MAX_MEAN_MS" || "$MAX_MEAN_MS" =~ ^[0-9]+$ ]] || die "--max-mean-ms must be a non-negative integer"
|
|
381
|
+
[[ -z "$MAX_P95_MS" || "$MAX_P95_MS" =~ ^[0-9]+$ ]] || die "--max-p95-ms must be a non-negative integer"
|
|
382
|
+
|
|
383
|
+
APP_ROOT="$(resolve_path_from_cwd "$APP_ROOT")"
|
|
384
|
+
TRACE_ROOT="$(resolve_path_from_cwd "$TRACE_ROOT")"
|
|
385
|
+
ZMR_BIN="$(resolve_command_path_from_cwd "$ZMR_BIN")"
|
|
386
|
+
ADB="$(resolve_command_path_from_cwd "$ADB")"
|
|
387
|
+
if [[ -n "$APK" ]]; then
|
|
388
|
+
APK="$(resolve_path_from_cwd "$APK")"
|
|
389
|
+
fi
|
|
390
|
+
if [[ -n "$SCENARIO" ]]; then
|
|
391
|
+
SCENARIO="$(resolve_path_from_cwd "$SCENARIO")"
|
|
392
|
+
fi
|
|
393
|
+
|
|
394
|
+
[[ -n "$APP_ROOT" ]] || die "--app-root is required"
|
|
395
|
+
[[ -d "$APP_ROOT" ]] || die "app repo not found: $APP_ROOT"
|
|
396
|
+
if [[ "$SKIP_METRO" -eq 0 ]]; then
|
|
397
|
+
[[ -f "$APP_ROOT/.env.test" ]] || die "app test env file not found: $APP_ROOT/.env.test"
|
|
398
|
+
fi
|
|
399
|
+
|
|
400
|
+
if [[ -z "$APK" ]]; then
|
|
401
|
+
APK="$APP_ROOT/android/app/build/outputs/apk/debug/app-debug.apk"
|
|
402
|
+
fi
|
|
403
|
+
[[ -f "$APK" ]] || die "APK not found: $APK"
|
|
404
|
+
|
|
405
|
+
echo "Android pilot output: $TRACE_ROOT"
|
|
406
|
+
echo "App test env: $APP_ROOT/.env.test"
|
|
407
|
+
if [[ "$DRY_RUN" -eq 1 ]]; then
|
|
408
|
+
echo "DRY RUN: commands will be printed but not executed"
|
|
409
|
+
fi
|
|
410
|
+
|
|
411
|
+
run mkdir -p "$TRACE_ROOT" "$(dirname "$ZMR_BIN")"
|
|
412
|
+
|
|
413
|
+
if [[ ! -x "$ZMR_BIN" ]]; then
|
|
414
|
+
target_args=()
|
|
415
|
+
if [[ "$(uname -s)" == "Darwin" && "$(uname -m)" == "arm64" ]]; then
|
|
416
|
+
target_args=(-target aarch64-macos.15.0)
|
|
417
|
+
fi
|
|
418
|
+
run zig build-exe src/main.zig "${target_args[@]}" -O Debug -femit-bin="$ZMR_BIN"
|
|
419
|
+
fi
|
|
420
|
+
|
|
421
|
+
run "$ZMR_BIN" version
|
|
422
|
+
if [[ -n "$SCENARIO" ]]; then
|
|
423
|
+
run "$ZMR_BIN" validate "$SCENARIO"
|
|
424
|
+
else
|
|
425
|
+
run "$ZMR_BIN" validate examples/android-app-auth-probe.json
|
|
426
|
+
run "$ZMR_BIN" validate examples/android-app-login-smoke.json
|
|
427
|
+
fi
|
|
428
|
+
|
|
429
|
+
run_zmr_android_scenario() {
|
|
430
|
+
if [[ "$ADB" == "adb" ]]; then
|
|
431
|
+
run "$ZMR_BIN" run "$@"
|
|
432
|
+
else
|
|
433
|
+
run "$ZMR_BIN" run "$@" --adb "$ADB"
|
|
434
|
+
fi
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
run_android_benchmark() {
|
|
438
|
+
if [[ "$ADB" == "adb" ]]; then
|
|
439
|
+
ZMR_BIN="$ZMR_BIN" run "$ROOT/scripts/benchmark.sh" "$@"
|
|
440
|
+
else
|
|
441
|
+
ZMR_BIN="$ZMR_BIN" run "$ROOT/scripts/benchmark.sh" "$@" --adb "$ADB"
|
|
442
|
+
fi
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
if [[ "$SKIP_EMULATOR" -eq 0 ]]; then
|
|
446
|
+
if [[ "$RESET_EMULATOR" -eq 1 ]]; then
|
|
447
|
+
run "$ADB" -s "$DEVICE" emu kill
|
|
448
|
+
STARTED_EMULATOR=1
|
|
449
|
+
fi
|
|
450
|
+
attached="$(capture "$ADB" devices | awk -v serial="$DEVICE" '$1 == serial && $2 == "device" { print $1 }')"
|
|
451
|
+
if [[ -z "$attached" || "$RESET_EMULATOR" -eq 1 ]]; then
|
|
452
|
+
if [[ -z "$AVD" ]]; then
|
|
453
|
+
AVD="$(find "$HOME/.android/avd" -maxdepth 1 -name '*.ini' -print 2>/dev/null | sed -n '1s#.*/##;s#\.ini$##p')"
|
|
454
|
+
fi
|
|
455
|
+
[[ -n "$AVD" ]] || die "no AVD found; pass --avd or --skip-emulator"
|
|
456
|
+
emulator_bin="${ANDROID_HOME:-$HOME/Library/Android/sdk}/emulator/emulator"
|
|
457
|
+
[[ -x "$emulator_bin" ]] || die "emulator binary not found: $emulator_bin"
|
|
458
|
+
emulator_args=(-avd "$AVD" -no-window -gpu swiftshader_indirect -no-snapshot-save -no-audio -no-boot-anim)
|
|
459
|
+
if [[ -n "$RESTORE_SNAPSHOT" ]]; then
|
|
460
|
+
emulator_args+=(-snapshot "$RESTORE_SNAPSHOT")
|
|
461
|
+
else
|
|
462
|
+
emulator_args+=(-no-snapshot-load)
|
|
463
|
+
fi
|
|
464
|
+
echo "+ $(quote_cmd "$emulator_bin" "${emulator_args[@]}")"
|
|
465
|
+
if [[ "$DRY_RUN" -eq 0 ]]; then
|
|
466
|
+
"$emulator_bin" "${emulator_args[@]}" > "$TRACE_ROOT/emulator.log" 2>&1 &
|
|
467
|
+
STARTED_EMULATOR=1
|
|
468
|
+
fi
|
|
469
|
+
fi
|
|
470
|
+
fi
|
|
471
|
+
|
|
472
|
+
if [[ "$SKIP_EMULATOR" -eq 1 ]]; then
|
|
473
|
+
preflight_android_device
|
|
474
|
+
fi
|
|
475
|
+
wait_for_device
|
|
476
|
+
wait_for_boot
|
|
477
|
+
|
|
478
|
+
run "$ADB" -s "$DEVICE" install -r "$APK"
|
|
479
|
+
run "$ADB" -s "$DEVICE" reverse tcp:8081 tcp:8081
|
|
480
|
+
run "$ADB" -s "$DEVICE" shell settings put global window_animation_scale 0
|
|
481
|
+
run "$ADB" -s "$DEVICE" shell settings put global transition_animation_scale 0
|
|
482
|
+
run "$ADB" -s "$DEVICE" shell settings put global animator_duration_scale 0
|
|
483
|
+
|
|
484
|
+
if [[ "$SKIP_METRO" -eq 0 ]]; then
|
|
485
|
+
command -v bun >/dev/null 2>&1 || die "bun is required to start Metro"
|
|
486
|
+
echo "+ (cd $(printf '%q' "$APP_ROOT") && bun run test:start > $(printf '%q' "$TRACE_ROOT/metro.log") 2>&1 &)"
|
|
487
|
+
if [[ "$DRY_RUN" -eq 0 ]]; then
|
|
488
|
+
(cd "$APP_ROOT" && bun run test:start > "$TRACE_ROOT/metro.log" 2>&1) &
|
|
489
|
+
METRO_PID="$!"
|
|
490
|
+
for _ in $(seq 1 90); do
|
|
491
|
+
if lsof -nP -iTCP:8081 -sTCP:LISTEN >/dev/null 2>&1; then
|
|
492
|
+
break
|
|
493
|
+
fi
|
|
494
|
+
sleep 1
|
|
495
|
+
done
|
|
496
|
+
fi
|
|
497
|
+
else
|
|
498
|
+
echo "Skipping Metro start; assuming app test server is already running"
|
|
499
|
+
fi
|
|
500
|
+
|
|
501
|
+
start_screen_recording
|
|
502
|
+
|
|
503
|
+
if [[ "$RUNS" -eq 1 ]]; then
|
|
504
|
+
if [[ -n "$SCENARIO" ]]; then
|
|
505
|
+
SINGLE_TRACE="$TRACE_ROOT/scenario"
|
|
506
|
+
run rm -rf "$SINGLE_TRACE"
|
|
507
|
+
run_zmr_android_scenario "$SCENARIO" --device "$DEVICE" --app-id "$APP_ID" --trace-dir "$SINGLE_TRACE"
|
|
508
|
+
run "$ZMR_BIN" report "$SINGLE_TRACE" --out "$SINGLE_TRACE/report.html"
|
|
509
|
+
run "$ZMR_BIN" export "$SINGLE_TRACE" --out "$TRACE_ROOT/scenario.zmrtrace"
|
|
510
|
+
run "$ZMR_BIN" export "$SINGLE_TRACE" --out "$TRACE_ROOT/scenario-redacted.zmrtrace" --redact
|
|
511
|
+
else
|
|
512
|
+
AUTH_TRACE="$TRACE_ROOT/auth"
|
|
513
|
+
LOGIN_TRACE="$TRACE_ROOT/login-smoke"
|
|
514
|
+
run rm -rf "$AUTH_TRACE" "$LOGIN_TRACE"
|
|
515
|
+
run_zmr_android_scenario examples/android-app-auth-probe.json --device "$DEVICE" --app-id "$APP_ID" --trace-dir "$AUTH_TRACE"
|
|
516
|
+
run "$ZMR_BIN" report "$AUTH_TRACE" --out "$AUTH_TRACE/report.html"
|
|
517
|
+
run "$ZMR_BIN" export "$AUTH_TRACE" --out "$TRACE_ROOT/auth.zmrtrace"
|
|
518
|
+
run "$ZMR_BIN" export "$AUTH_TRACE" --out "$TRACE_ROOT/auth-redacted.zmrtrace" --redact
|
|
519
|
+
run_zmr_android_scenario examples/android-app-login-smoke.json --device "$DEVICE" --app-id "$APP_ID" --trace-dir "$LOGIN_TRACE"
|
|
520
|
+
run "$ZMR_BIN" report "$LOGIN_TRACE" --out "$LOGIN_TRACE/report.html"
|
|
521
|
+
run "$ZMR_BIN" export "$LOGIN_TRACE" --out "$TRACE_ROOT/login-smoke.zmrtrace"
|
|
522
|
+
run "$ZMR_BIN" export "$LOGIN_TRACE" --out "$TRACE_ROOT/login-smoke-redacted.zmrtrace" --redact
|
|
523
|
+
fi
|
|
524
|
+
else
|
|
525
|
+
benchmark_gate_args=(--min-pass-rate "$MIN_PASS_RATE" --max-failures "$MAX_FAILURES")
|
|
526
|
+
if [[ -n "$MAX_MEAN_MS" ]]; then
|
|
527
|
+
benchmark_gate_args+=(--max-mean-ms "$MAX_MEAN_MS")
|
|
528
|
+
fi
|
|
529
|
+
if [[ -n "$MAX_P95_MS" ]]; then
|
|
530
|
+
benchmark_gate_args+=(--max-p95-ms "$MAX_P95_MS")
|
|
531
|
+
fi
|
|
532
|
+
if [[ -n "$SCENARIO" ]]; then
|
|
533
|
+
run_android_benchmark --zmr "$SCENARIO" --device "$DEVICE" --app-id "$APP_ID" --runs "$RUNS" --trace-root "$TRACE_ROOT/bench-scenario" "${benchmark_gate_args[@]}"
|
|
534
|
+
run "$ZMR_BIN" report "$TRACE_ROOT/bench-scenario" --out "$TRACE_ROOT/bench-scenario/report.html"
|
|
535
|
+
else
|
|
536
|
+
run_android_benchmark --zmr examples/android-app-auth-probe.json --device "$DEVICE" --app-id "$APP_ID" --runs "$RUNS" --trace-root "$TRACE_ROOT/bench-auth" "${benchmark_gate_args[@]}"
|
|
537
|
+
run "$ZMR_BIN" report "$TRACE_ROOT/bench-auth" --out "$TRACE_ROOT/bench-auth/report.html"
|
|
538
|
+
run_android_benchmark --zmr examples/android-app-login-smoke.json --device "$DEVICE" --app-id "$APP_ID" --runs "$RUNS" --trace-root "$TRACE_ROOT/bench-login-smoke" "${benchmark_gate_args[@]}"
|
|
539
|
+
run "$ZMR_BIN" report "$TRACE_ROOT/bench-login-smoke" --out "$TRACE_ROOT/bench-login-smoke/report.html"
|
|
540
|
+
fi
|
|
541
|
+
fi
|
|
542
|
+
|
|
543
|
+
stop_screen_recording
|
|
544
|
+
|
|
545
|
+
cat <<EOF
|
|
546
|
+
|
|
547
|
+
Android pilot complete.
|
|
548
|
+
Output directory: $TRACE_ROOT
|
|
549
|
+
Shareable bundles:
|
|
550
|
+
$TRACE_ROOT/auth-redacted.zmrtrace
|
|
551
|
+
$TRACE_ROOT/login-smoke-redacted.zmrtrace
|
|
552
|
+
Viewer:
|
|
553
|
+
$ROOT/viewer/index.html
|
|
554
|
+
EOF
|
|
555
|
+
|
|
556
|
+
if [[ "$SCREEN_RECORD" -eq 1 ]]; then
|
|
557
|
+
cat <<EOF
|
|
558
|
+
Screen recording:
|
|
559
|
+
$TRACE_ROOT/screenrecord.mp4
|
|
560
|
+
EOF
|
|
561
|
+
fi
|