koopa-admin-log/scripts/taler-monitoring/android-test/run-android-pay-smoke.sh
Hernâni Marques b1c8e5ddb2
monitoring: build latest taler-android then same adb pay smoke
Add run-android-build-and-smoke.sh (assembleFdroidDebug from
taler-android master) and wire APK_PATH/PKG into the existing smoke.
2026-07-17 20:59:31 +02:00

204 lines
7.5 KiB
Bash
Executable file
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env bash
# Android wallet smoke: install APK (published F-Droid **or** from-source), open
# withdraw/pay URIs via adb.
#
# No root required if:
# - adb is available (package android-tools-adb / platform-tools)
# - a device or emulator is connected (`adb devices` shows "device")
# - optional user-local SDK under $HOME/Android/Sdk (emulator)
#
# Usage:
# ./android-test/run-android-pay-smoke.sh # published F-Droid APK
# STACK=goa ./android-test/run-android-pay-smoke.sh
# STACK=stage ./android-test/run-android-pay-smoke.sh
# # from-source (built first):
# ./android-test/run-android-build-and-smoke.sh
# APK_PATH=/path/to.apk PKG=net.taler.wallet.fdroid.debug ./run-android-pay-smoke.sh
#
# Published APK (default): F-Droid Taler Wallet 1.6.1 (854)
# https://f-droid.org/packages/net.taler.wallet.fdroid/
#
set -euo pipefail
ROOT=$(cd "$(dirname "$0")" && pwd)
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}"
# Optional override: full path to an already-built APK (from-source)
APK_PATH="${APK_PATH:-}"
PKG="${PKG:-net.taler.wallet.fdroid}"
STACK="${STACK:-auto}" # auto | goa | stage
SERIAL="${SERIAL:-}"
OUT_DIR="${OUT_DIR:-$ROOT/out}"
mkdir -p "$APK_DIR" "$OUT_DIR"
if ! command -v adb >/dev/null 2>&1; then
if [ -x "$HOME/Android/Sdk/platform-tools/adb" ]; then
export PATH="$HOME/Android/Sdk/platform-tools:$PATH"
else
echo "adb missing — install android-tools-adb or user SDK platform-tools" >&2
exit 2
fi
fi
if [ -z "$SERIAL" ]; then
SERIAL=$(adb devices | awk '/\tdevice$/{print $1; exit}')
fi
if [ -z "$SERIAL" ]; then
cat >&2 <<'EOF'
No adb device. Options (no root for user-local emulator if /dev/kvm is usable):
1) Plug phone with USB debugging
2) Start AVD: $HOME/Android/Sdk/emulator/emulator -avd TalerWallet34 -no-window
3) Then re-run this script
EOF
exit 3
fi
ADB=(adb -s "$SERIAL")
echo "device: $SERIAL"
# Resolve stack endpoints
case "$STACK" in
auto)
if curl -sfS -m 5 -o /dev/null https://bank.hacktivism.ch/config 2>/dev/null; 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"
PAY_HINT="paivana template / goa-shop"
;;
stage)
BANK=https://stage.bank.lefrancpaysan.ch
MERCHANT=https://stage.monnaie.lefrancpaysan.ch
WITHDRAW_JSON="$BANK/intro/demo-withdraw.json"
PAY_HINT="farmer shop templates"
;;
*) echo "unknown STACK=$STACK" >&2; exit 2 ;;
esac
echo "stack: $STACK bank: $BANK"
# APK: explicit path, or download published F-Droid into APK_DIR
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"
echo "downloading published wallet APK…"
curl -fL --retry 3 -o "$APK_PATH" "$APK_URL"
fi
echo "apk: $APK_PATH ($(wc -c <"$APK_PATH") bytes)"
echo "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
# Withdraw URI from live mint
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 "")')
if [ -z "$WURI" ]; then
echo "FAIL: no taler_withdraw_uri from $WITHDRAW_JSON" >&2
exit 4
fi
echo "withdraw: $WURI"
echo "$WURI" >"$OUT_DIR/last-withdraw.uri"
"${ADB[@]}" shell am force-stop "$PKG" 2>/dev/null || true
"${ADB[@]}" logcat -c 2>/dev/null || true
"${ADB[@]}" shell am start -a android.intent.action.VIEW -d "$WURI" 2>&1 | tee "$OUT_DIR/start-withdraw.txt"
sleep 12
"${ADB[@]}" exec-out screencap -p >"$OUT_DIR/01-after-withdraw-uri.png" || true
"${ADB[@]}" shell uiautomator dump /sdcard/ui.xml 2>/dev/null || true
"${ADB[@]}" pull /sdcard/ui.xml "$OUT_DIR/01-ui.xml" 2>/dev/null || true
# Best-effort: tap common confirm labels
python3 - "$SERIAL" "$OUT_DIR/01-ui.xml" <<'PY' || true
import re, subprocess, sys
serial, path = sys.argv[1], sys.argv[2]
try:
xml = open(path, errors="replace").read()
except FileNotFoundError:
raise SystemExit(0)
labels = [
"Confirm", "Withdraw", "Accept", "Continue", "OK",
"I accept", "Agree", "Bestätigen", "Abheben", "Akzeptieren",
]
for label in labels:
for pat in (
r'text="%s"[^>]*bounds="\[(\d+),(\d+)\]\[(\d+),(\d+)\]"' % re.escape(label),
r'bounds="\[(\d+),(\d+)\]\[(\d+),(\d+)\]"[^>]*text="%s"' % re.escape(label),
):
for m in re.finditer(pat, xml):
x1, y1, x2, y2 = map(int, m.groups())
x, y = (x1 + x2) // 2, (y1 + y2) // 2
print(f"tap {label} @ {x},{y}")
subprocess.run(["adb", "-s", serial, "shell", "input", "tap", str(x), str(y)], check=False)
PY
sleep 8
"${ADB[@]}" exec-out screencap -p >"$OUT_DIR/02-after-confirm-tap.png" || true
# Optional public pay template (stage fixed product / GOA shop if amount known)
# Stage: open monnaies shop is browser-side; deep link pay after template POST if available.
PAY_URI=""
if [ "$STACK" = "stage" ]; then
# fixed template panier-legumes → taler://pay/…
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 ""
if oid and tok:
print("taler://pay/stage.monnaie.lefrancpaysan.ch/instances/fermes-des-collines/%s/?c=%s"%(oid,tok))
' 2>/dev/null || true)
fi
elif [ "$STACK" = "goa" ]; then
# Paivana pay-template deep link (wallet prepares order)
PAY_URI="taler://pay-template/taler.hacktivism.ch/instances/goa-shop/paivana"
fi
if [ -n "$PAY_URI" ]; then
echo "pay: $PAY_URI ($PAY_HINT)"
echo "$PAY_URI" >"$OUT_DIR/last-pay.uri"
"${ADB[@]}" shell am start -a android.intent.action.VIEW -d "$PAY_URI" 2>&1 | tee "$OUT_DIR/start-pay.txt"
sleep 12
"${ADB[@]}" exec-out screencap -p >"$OUT_DIR/03-after-pay-uri.png" || true
else
echo "pay: (skipped — no public template order)"
fi
# Evidence from logcat
"${ADB[@]}" logcat -d -t 300 >"$OUT_DIR/logcat.txt" || true
grep -iE 'taler-wallet|prepareBank|preparePay|confirm|error|Error|success' "$OUT_DIR/logcat.txt" \
| tail -80 >"$OUT_DIR/logcat-taler.txt" || true
echo
echo "=== summary ==="
echo "package installed: $PKG"
echo "withdraw intent delivered: $WURI"
if grep -q 'prepareBankIntegratedWithdrawal' "$OUT_DIR/logcat.txt" 2>/dev/null; then
echo "wallet-core: prepareBankIntegratedWithdrawal seen (wallet accepted withdraw URI)"
else
echo "wallet-core: prepareBankIntegratedWithdrawal NOT seen (UI may still show onboarding/ANR on small RAM)"
fi
if [ -n "$PAY_URI" ]; then
if grep -qiE 'preparePay|confirmPay|pay-template|preparePurchase' "$OUT_DIR/logcat.txt" 2>/dev/null; then
echo "wallet-core: pay path activity seen"
else
echo "wallet-core: pay path not confirmed in logcat (check $OUT_DIR/03-after-pay-uri.png)"
fi
fi
echo "artifacts: $OUT_DIR/"
ls -la "$OUT_DIR" | sed 's/^/ /'
echo
echo "NOTE: Full unattended UI payment needs a responsive device/emulator (≥68GiB host RAM recommended)."
echo "This smoke proves: published APK install + deep-link into wallet-core on stack=$STACK."