Closer/qa/entrypoint_smoke.sh

101 lines
5.0 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters

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
# qa/entrypoint_smoke.sh — Cold-start / entry-point launch-integrity smoke.
#
# WHY THIS EXISTS: a whole bug class makes the app "open and immediately close" on a REAL notification
# cold-start (e.g. the splash-exit `provider.iconView` NPE — the OS hands over a splash with no icon on
# the notification/PendingIntent launch path). It breaks EVERY notification at once (shared cold-start
# path) yet is invisible to `adb am start` (different launch path) and to the normal launcher icon.
# The only reliable catch is a real push, delivered to a genuinely killed app (`am kill`, NOT
# `am force-stop` — force-stopped apps are excluded from FCM), tapped from the shade.
#
# For each entry the app must: OPEN, STAY UP (process alive, 0 FATAL), and land OFF the launcher.
# Emulator FCM-to-killed-app is flaky (FcmRetry); undeliverable cases are reported BLOCKED, not FAIL —
# only an actual open-and-close / crash is a FAIL.
#
# Usage: qa/entrypoint_smoke.sh <serial> [recipient_uid]
# qa/entrypoint_smoke.sh emulator-5556 imDjjOTTQvXGGjyUhUc5JSeHWkU2
# Env overrides: PKG, SA_JSON, COUPLE_ID.
# Runtime: ~37 min (flaky emulator FCM adds retries). Run in the background and read the matrix.
# Exit 0 only if zero FAIL (BLOCK = undeliverable push, environmental — rerun, not an app bug).
set -u
SERIAL="${1:-emulator-5554}"
RUID="${2:-}"
PKG="${PKG:-closer.app}"
HERE="$(cd "$(dirname "$0")" && pwd)"
export NODE_PATH="${NODE_PATH:-$HERE/../functions/node_modules}"
PASS=0; FAIL=0; BLOCKED=0
adbs() { adb -s "$SERIAL" "$@"; }
alive() { adbs shell pidof "$PKG" 2>/dev/null | tr -d '\r'; }
crashed() { adbs logcat -d -t 1500 2>/dev/null | grep -E "FATAL EXCEPTION|getIconView|Force finishing.*$PKG" | grep -v AppsFilter | head -3; }
on_launcher() { adbs shell dumpsys activity activities 2>/dev/null | grep -m1 "ResumedActivity" | grep -qi "launcher"; }
ok() { echo " PASS $1"; PASS=$((PASS+1)); }
bad() { echo " FAIL $1 [$2]"; FAIL=$((FAIL+1)); }
blkd() { echo " BLOCK $1 [$2]"; BLOCKED=$((BLOCKED+1)); }
verify() { # <label> — the real check: app opened and STAYED (no crash/close)
local c a; c="$(crashed)"; a="$(alive)"
if [ -n "$a" ] && [ -z "$c" ] && ! on_launcher; then ok "$1"
else bad "$1" "alive='${a:-none}' crash='${c:-none}' onLauncher=$(on_launcher && echo yes || echo no)"; fi
}
settle_fcm() { adbs shell monkey -p "$PKG" -c android.intent.category.LAUNCHER 1 >/dev/null 2>&1; sleep 15; adbs shell input keyevent KEYCODE_HOME >/dev/null 2>&1; sleep 1; }
# find the QA-SMOKE:<type> notification in the shade; echoes "x y" if present
find_notif() { # <type>
adbs shell cmd statusbar expand-notifications >/dev/null 2>&1; sleep 2
adbs shell uiautomator dump /sdcard/sm.xml >/dev/null 2>&1
adbs pull /sdcard/sm.xml "/tmp/sm_${SERIAL}.xml" >/dev/null 2>&1
python3 - "/tmp/sm_${SERIAL}.xml" "$1" <<'PY'
import re,sys
xml=open(sys.argv[1],encoding="utf-8",errors="ignore").read(); want="QA-SMOKE:"+sys.argv[2]
for n in re.findall(r'<node[^>]*>',xml):
t=re.search(r'text="([^"]*)"',n)
if t and want in t.group(1):
b=re.search(r'bounds="\[(\d+),(\d+)\]\[(\d+),(\d+)\]"',n)
if b: print((int(b.group(1))+int(b.group(3)))//2,(int(b.group(2))+int(b.group(4)))//2); break
PY
}
echo "== entrypoint smoke :: $SERIAL =="
settle_fcm # clear 'stopped' flag, register token, give FCM time to connect
# 1) Launcher icon cold-start.
adbs shell am kill "$PKG" >/dev/null 2>&1; sleep 2
adbs logcat -c 2>/dev/null
adbs shell monkey -p "$PKG" -c android.intent.category.LAUNCHER 1 >/dev/null 2>&1
sleep 6
verify "launcher cold-start"
# 2) Notification cold-starts (real push -> killed app -> tap).
if [ -n "$RUID" ]; then
for CASE in \
"partner_started_game|game_type=this_or_that" \
"partner_completed_part|game_type=this_or_that" \
"partner_finished_game|game_type=wheel" \
"chat_message|conversation_id=main" \
"partner_answered|" ; do
TYPE="${CASE%%|*}"; EXTRAS="${CASE#*|}"
XY=""; ATTEMPT=0
while [ -z "$XY" ] && [ "$ATTEMPT" -lt 2 ]; do
ATTEMPT=$((ATTEMPT+1))
[ "$ATTEMPT" -eq 2 ] && settle_fcm # 2nd try: relaunch to kick the FCM transport
adbs shell am kill "$PKG" >/dev/null 2>&1; sleep 2
adbs logcat -c 2>/dev/null
OUT="$(node "$HERE/qa_push.js" "$RUID" "$TYPE" $EXTRAS 2>&1)"
if ! echo "$OUT" | grep -q "^SENT"; then bad "notif:$TYPE (send)" "$OUT"; break; fi
# poll for delivery up to ~24s
for _ in 1 2 3 4 5 6; do sleep 4; XY="$(find_notif "$TYPE")"; [ -n "$XY" ] && break; adbs shell cmd statusbar collapse >/dev/null 2>&1; done
done
if echo "${OUT:-}" | grep -q "^SENT" && [ -z "$XY" ]; then blkd "notif:$TYPE" "not delivered (flaky emulator FCM); rerun"; continue; fi
[ -z "$XY" ] && continue
adbs shell input tap $XY >/dev/null 2>&1
sleep 8
verify "notif:$TYPE tap -> opens & stays"
done
else
echo " (notification cases skipped — pass a recipient_uid to run them)"
fi
echo "== result: ${PASS} passed, ${FAIL} failed, ${BLOCKED} blocked =="
[ "$FAIL" -eq 0 ]