Multi-phase global SUMMARY, warn-filter dimmed context, SUMMARY chrome as meta; FP stage host-agent via francpaysan-stage-user (stagepaysan); monpages GOA + FP stage.
201 lines
7.5 KiB
Bash
Executable file
201 lines
7.5 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# GUI-oriented Android smoke: **withdraw (Abheben)** then **pay**, each with
|
|
# deep-link entry + multi-round uiautomator taps. Not pay-only.
|
|
#
|
|
# 1) taler://withdraw/… + Confirm/Abheben/ToS taps
|
|
# 2) taler://pay… + Pay/Confirm taps
|
|
#
|
|
# See GUI-AUTOMATION-NOTES.md
|
|
#
|
|
set -euo pipefail
|
|
ROOT=$(cd "$(dirname "$0")" && pwd)
|
|
# shellcheck source=lib_android_env.sh
|
|
. "$ROOT/lib_android_env.sh"
|
|
|
|
[ "${AUTO_ANDROID}" = "1" ] || { echo "skipped: AUTO_ANDROID=${AUTO_ANDROID}"; exit 0; }
|
|
if [ "${AUTO_GUI}" != "1" ]; then
|
|
echo "AUTO_GUI=0 → deep-link smoke only"
|
|
exec env AUTO_ANDROID=1 "$ROOT/run-android-pay-smoke.sh"
|
|
fi
|
|
|
|
export OUT_DIR="${OUT_DIR:-$ROOT/out-gui}"
|
|
export GUI_ROUNDS="${GUI_ROUNDS:-10}"
|
|
export GUI_SLEEP="${GUI_SLEEP:-3}"
|
|
|
|
# Install + deliver intents via existing smoke, but skip its weak single-tap
|
|
# by setting GUI_MODE=1 which we implement here more fully.
|
|
# Simpler: do install/URI here by sourcing patterns from pay-smoke via env + python.
|
|
|
|
# Delegate install + URI start to pay-smoke with GUI_AFTER=1 if we patch it;
|
|
# instead run a self-contained flow calling pay-smoke pieces.
|
|
|
|
APK_DIR="${APK_DIR:-$ROOT/apks}"
|
|
APK_URL="${APK_URL:-https://f-droid.org/repo/net.taler.wallet.fdroid_854.apk}"
|
|
APK_NAME="${APK_NAME:-net.taler.wallet.fdroid_854.apk}"
|
|
APK_PATH="${APK_PATH:-}"
|
|
PKG="${PKG:-net.taler.wallet.fdroid}"
|
|
STACK="${STACK:-auto}"
|
|
SERIAL="${SERIAL:-}"
|
|
mkdir -p "$OUT_DIR"
|
|
|
|
command -v adb >/dev/null || { echo "adb missing" >&2; exit 2; }
|
|
|
|
# Headless default: no host window; guest GLES via SwiftShader (uiautomator).
|
|
android_ensure_device || { echo "no adb device (try ./start-android-emulator.sh --wait)" >&2; exit 3; }
|
|
ADB=(adb -s "$SERIAL")
|
|
echo "device: $SERIAL mode: GUI (uiautomator) headless=${EMULATOR_HEADLESS} gpu=${EMULATOR_GPU}"
|
|
|
|
case "$STACK" in
|
|
auto)
|
|
if curl -sfS -m 5 -o /dev/null https://bank.hacktivism.ch/config; then STACK=goa; else STACK=stage; fi
|
|
;;
|
|
esac
|
|
case "$STACK" in
|
|
goa)
|
|
BANK=https://bank.hacktivism.ch
|
|
MERCHANT=https://taler.hacktivism.ch
|
|
WITHDRAW_JSON="$BANK/intro/demo-withdraw.json"
|
|
;;
|
|
stage)
|
|
BANK=https://stage.bank.lefrancpaysan.ch
|
|
MERCHANT=https://stage.monnaie.lefrancpaysan.ch
|
|
WITHDRAW_JSON="$BANK/intro/demo-withdraw.json"
|
|
;;
|
|
*) echo "unknown STACK" >&2; exit 2 ;;
|
|
esac
|
|
echo "stack: $STACK"
|
|
|
|
if [ -n "$APK_PATH" ] && [ -f "$APK_PATH" ]; then
|
|
:
|
|
elif [ -f "$APK_DIR/$APK_NAME" ]; then
|
|
APK_PATH="$APK_DIR/$APK_NAME"
|
|
else
|
|
APK_PATH="$APK_DIR/$APK_NAME"
|
|
mkdir -p "$APK_DIR"
|
|
curl -fL --retry 3 -o "$APK_PATH" "$APK_URL"
|
|
fi
|
|
echo "apk: $APK_PATH pkg: $PKG"
|
|
|
|
"${ADB[@]}" wait-for-device
|
|
"${ADB[@]}" install -r "$APK_PATH"
|
|
"${ADB[@]}" shell settings put global window_animation_scale 0 || true
|
|
"${ADB[@]}" shell settings put global transition_animation_scale 0 || true
|
|
"${ADB[@]}" shell settings put global animator_duration_scale 0 || true
|
|
|
|
: "${DO_WITHDRAW:=1}"
|
|
: "${DO_PAY:=1}"
|
|
: "${SMOKE_STRICT:=0}"
|
|
|
|
WURI=""
|
|
PAY_URI=""
|
|
WITHDRAW_OK=0
|
|
PAY_OK=0
|
|
|
|
"${ADB[@]}" shell am force-stop "$PKG" 2>/dev/null || true
|
|
"${ADB[@]}" logcat -c 2>/dev/null || true
|
|
|
|
if [ "$DO_WITHDRAW" = "1" ]; then
|
|
echo
|
|
echo "======== 1 WITHDRAW (Abheben) ========"
|
|
WURI=$(curl -sfS -m 25 "$WITHDRAW_JSON" | python3 -c 'import json,sys; d=json.load(sys.stdin); print(d.get("taler_withdraw_uri") or d.get("qr_payload") or "")')
|
|
[ -n "$WURI" ] || { echo "no withdraw uri" >&2; exit 4; }
|
|
echo "withdraw: $WURI"
|
|
echo "$WURI" >"$OUT_DIR/last-withdraw.uri"
|
|
"${ADB[@]}" shell am start -a android.intent.action.VIEW -d "$WURI" | tee "$OUT_DIR/start-withdraw.txt"
|
|
sleep 5
|
|
python3 - "$ROOT/lib_ui.py" "$SERIAL" "$OUT_DIR" "$GUI_ROUNDS" "$GUI_SLEEP" <<'PY'
|
|
import json, sys, importlib.util
|
|
from pathlib import Path
|
|
lib_path, serial, out, rounds, sleep_s = (
|
|
Path(sys.argv[1]), sys.argv[2], Path(sys.argv[3]), int(sys.argv[4]), float(sys.argv[5])
|
|
)
|
|
spec = importlib.util.spec_from_file_location("lib_ui", lib_path)
|
|
lib = importlib.util.module_from_spec(spec)
|
|
spec.loader.exec_module(lib)
|
|
st = lib.gui_drive(serial, out / "gui-withdraw", rounds=rounds, sleep_s=sleep_s, phase="wd")
|
|
(out / "gui-withdraw-status.json").write_text(json.dumps(st, indent=2))
|
|
print("gui-withdraw taps:", st.get("taps"))
|
|
print("gui-withdraw anr:", st.get("anr_dismissals"))
|
|
PY
|
|
else
|
|
echo "======== 1 WITHDRAW skipped (DO_WITHDRAW=0) ========"
|
|
fi
|
|
|
|
if [ "$DO_PAY" = "1" ]; then
|
|
echo
|
|
echo "======== 2 PAY (Bezahlen) ========"
|
|
if [ "$STACK" = "stage" ]; then
|
|
if RESP=$(curl -sfS -m 20 -X POST -H 'Content-Type: application/json' -d '{}' \
|
|
"$MERCHANT/instances/fermes-des-collines/templates/panier-legumes" 2>/dev/null); then
|
|
PAY_URI=$(printf '%s' "$RESP" | python3 -c 'import json,sys;d=json.load(sys.stdin);oid=d.get("order_id")or"";tok=d.get("token")or"";
|
|
print("taler://pay/stage.monnaie.lefrancpaysan.ch/instances/fermes-des-collines/%s/?c=%s"%(oid,tok) if oid and tok else "")')
|
|
fi
|
|
else
|
|
PAY_URI="taler://pay-template/taler.hacktivism.ch/instances/goa-shop/paivana"
|
|
fi
|
|
if [ -n "$PAY_URI" ]; then
|
|
echo "pay: $PAY_URI"
|
|
echo "$PAY_URI" >"$OUT_DIR/last-pay.uri"
|
|
"${ADB[@]}" shell am start -a android.intent.action.VIEW -d "$PAY_URI" | tee "$OUT_DIR/start-pay.txt"
|
|
sleep 5
|
|
python3 - "$ROOT/lib_ui.py" "$SERIAL" "$OUT_DIR" "$GUI_ROUNDS" "$GUI_SLEEP" <<'PY'
|
|
import json, sys, importlib.util
|
|
from pathlib import Path
|
|
lib_path, serial, out, rounds, sleep_s = (
|
|
Path(sys.argv[1]), sys.argv[2], Path(sys.argv[3]), int(sys.argv[4]), float(sys.argv[5])
|
|
)
|
|
spec = importlib.util.spec_from_file_location("lib_ui", lib_path)
|
|
lib = importlib.util.module_from_spec(spec)
|
|
spec.loader.exec_module(lib)
|
|
st = lib.gui_drive(serial, out / "gui-pay", rounds=rounds, sleep_s=sleep_s, phase="pay")
|
|
(out / "gui-pay-status.json").write_text(json.dumps(st, indent=2))
|
|
print("gui-pay taps:", st.get("taps"))
|
|
print("gui-pay anr:", st.get("anr_dismissals"))
|
|
PY
|
|
else
|
|
echo "pay: (no URI)"
|
|
fi
|
|
else
|
|
echo "======== 2 PAY skipped (DO_PAY=0) ========"
|
|
fi
|
|
|
|
"${ADB[@]}" logcat -d -t 500 >"$OUT_DIR/logcat.txt" || true
|
|
grep -iE 'taler-wallet|prepareBank|acceptWithdrawal|confirmWithdrawal|preparePay|confirmPay|Error|success|withdraw|pay' \
|
|
"$OUT_DIR/logcat.txt" | tail -100 >"$OUT_DIR/logcat-taler.txt" || true
|
|
|
|
if [ "$DO_WITHDRAW" = "1" ] && grep -qE 'prepareBankIntegratedWithdrawal|acceptWithdrawal|confirmWithdrawal' \
|
|
"$OUT_DIR/logcat.txt" 2>/dev/null; then
|
|
WITHDRAW_OK=1
|
|
fi
|
|
if [ "$DO_PAY" = "1" ] && [ -n "$PAY_URI" ] && \
|
|
grep -qiE 'preparePay|confirmPay|preparePurchase|checkPay|pay-template|PayForTemplate' \
|
|
"$OUT_DIR/logcat.txt" 2>/dev/null; then
|
|
PAY_OK=1
|
|
fi
|
|
|
|
rc=0
|
|
echo
|
|
echo "=== GUI smoke summary ($STACK) — withdraw + pay ==="
|
|
echo "package: $PKG DO_WITHDRAW=$DO_WITHDRAW DO_PAY=$DO_PAY STRICT=$SMOKE_STRICT"
|
|
if [ "$DO_WITHDRAW" = "1" ]; then
|
|
echo "withdraw URI: delivered → $OUT_DIR/gui-withdraw-status.json"
|
|
echo "withdraw wallet-core: $([ "$WITHDRAW_OK" = 1 ] && echo YES || echo NO)"
|
|
if [ "$SMOKE_STRICT" = "1" ] && [ "$WITHDRAW_OK" != "1" ]; then
|
|
echo "FAIL: strict withdraw missing"; rc=11
|
|
fi
|
|
fi
|
|
if [ "$DO_PAY" = "1" ]; then
|
|
echo "pay URI: ${PAY_URI:-none} → $OUT_DIR/gui-pay-status.json"
|
|
echo "pay wallet-core: $([ "$PAY_OK" = 1 ] && echo YES || echo NO)"
|
|
if [ "$SMOKE_STRICT" = "1" ] && [ "$PAY_OK" != "1" ]; then
|
|
echo "FAIL: strict pay missing"; [ "$rc" -eq 0 ] && rc=13
|
|
fi
|
|
fi
|
|
if grep -qiE "isn't responding|not responding" "$OUT_DIR/logcat.txt" 2>/dev/null \
|
|
|| grep -rqiE "isn't responding" "$OUT_DIR/gui-withdraw" "$OUT_DIR/gui-pay" 2>/dev/null; then
|
|
echo "FAIL: ANR"; rc=10
|
|
fi
|
|
echo "artifacts: $OUT_DIR/"
|
|
ls -la "$OUT_DIR" | sed 's/^/ /'
|
|
echo "Documented shortcuts → GUI-AUTOMATION-NOTES.md"
|
|
exit "$rc"
|