#!/usr/bin/env bash # VPN crash simulation lab — device (adb) and/or BE upload verification. # # Modes: # MODE=device — trigger VpnCrashSimulator in :vpn via adb (debug APK) # MODE=upload — POST synthetic vpn-process crash JSON to BE upload API # MODE=both — device then verify BE (default when adb device present) # # Env: # COUNT=70 # BASE=https://apps.f0xx.org/app/androidcast_project/crashes # RUN_ID=YYYYMMDD_HHMMSS (batch tag for Issues search) # PACKAGE=com.foxx.androidcast set -euo pipefail ROOT="$(cd "$(dirname "$0")/.." && pwd)" COUNT="${COUNT:-70}" BASE="${BASE:-https://apps.f0xx.org/app/androidcast_project/crashes}" UPLOAD_URL="$BASE/api/upload.php" PACKAGE="${PACKAGE:-com.foxx.androidcast}" RUN_ID="${RUN_ID:-$(date -u +%Y%m%d_%H%M%S)}" MODE="${MODE:-auto}" JAR="${JAR:-/tmp/ac_vpn_crash_cookies.txt}" DELAY_MS="${DELAY_MS:-80}" VERIFY_LOGIN="${VERIFY_LOGIN:-1}" log() { printf '[vpn-crash-sim] %s\n' "$*"; } has_device() { adb devices 2>/dev/null | awk 'NR>1 && $2=="device" { found=1 } END { exit !found }' } simulate_device() { local n="$1" local i seq log "device: triggering $n VPN-process crash recordings via $PACKAGE" for ((i = 1; i <= n; i++)); do seq="$i" adb shell am start-service \ -n "$PACKAGE/com.foxx.androidcast.vpn.AndroidCastVpnService" \ -a com.foxx.androidcast.vpn.SIMULATE_CRASH \ --ei sim_seq "$seq" >/dev/null 2>&1 \ || adb shell am startservice \ -n "$PACKAGE/com.foxx.androidcast.vpn.AndroidCastVpnService" \ -a com.foxx.androidcast.vpn.SIMULATE_CRASH \ --ei sim_seq "$seq" >/dev/null 2>&1 \ || true if [[ "$DELAY_MS" -gt 0 ]]; then sleep "$(awk "BEGIN { print $DELAY_MS / 1000 }")" fi if (( i % 10 == 0 )); then log " device progress $i/$n" fi done log "device: done — waiting for crash watcher upload sweep" sleep 15 } upload_one() { local seq="$1" local report_id="vpn_sim_${RUN_ID}_$(printf '%03d' "$seq")" local ms ms="$(date +%s)000" local fp fp="$(printf 'vpn_sim_%s_%03d' "$RUN_ID" "$seq" | sha256sum | awk '{print $1}')" local body body="$(cat </dev/null || echo 0)" log "verify: BE reports matching q=$q → $cnt (expected up to $COUNT)" if [[ "$cnt" -lt 1 ]]; then log "verify: WARN — Issues API returned 0 (login cookie may be invalid in automation)" log "verify: open $BASE/?view=reports&q=$q in browser when logged in" return 1 fi echo "$json" | python3 -c " import json,sys d=json.load(sys.stdin) for it in (d.get('items') or [])[:3]: p=it.get('payload') or {} j=p.get('java') or {} print(' sample:', it.get('report_id'), 'process=', p.get('process'), 'frames=', len(j.get('stack_frames') or [])) " 2>/dev/null || true } if [[ "$MODE" == "auto" ]]; then if has_device; then MODE=both else MODE=upload log "no adb device — using upload-only mode" fi fi case "$MODE" in device) simulate_device "$COUNT" ;; upload) simulate_upload "$COUNT" verify_be || true ;; both) simulate_device "$COUNT" QUERY="${QUERY:-VpnCrashSimulation}" verify_be || true ;; *) echo "unknown MODE=$MODE (device|upload|both)" >&2 exit 1 ;; esac log "complete run_id=$RUN_ID — Issues: $BASE/?view=reports&q=$RUN_ID"