#!/usr/bin/env bash # Smoke test on the headless Google TV emulator. # # Builds the debug APK, installs it, walks the first screen with the D-pad # and fails on anything the unit tests cannot see: a crash on startup, a # crash while navigating, an ANR. The 0.11.0 startup crash and the rail # crash on "Verein hinzufügen" would both have been caught here. # # tests/smoke.sh # build, run, leave the emulator up # tests/smoke.sh --apk # skip the build, test this APK # tests/smoke.sh --stop # stop the emulator when done set -euo pipefail ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" HELPERS="$ROOT/tests/helpers" RUNS="$ROOT/tests/runs" SERIAL="${CASTARR_SERIAL:-emulator-5554}" ADB="${ANDROID_SDK_ROOT:-$HOME/Android/Sdk}/platform-tools/adb" PKG="dev.castarr.tv" ACTIVITY="$PKG/.MainActivity" APK="" STOP_AFTER=0 while [ $# -gt 0 ]; do case "$1" in --apk) APK="$2"; shift 2 ;; --stop) STOP_AFTER=1; shift ;; *) echo "usage: $0 [--apk ] [--stop]" >&2; exit 2 ;; esac done mkdir -p "$RUNS/screenshots" LOG="$RUNS/smoke.log" : > "$LOG" step() { printf '\n== %s\n' "$1" | tee -a "$LOG"; } fail() { printf '\nFAIL: %s\n' "$1" | tee -a "$LOG" >&2; exit 1; } if [ -z "$APK" ]; then step "Debug-APK bauen" # shellcheck source=tests/helpers/jdk.sh . "$HELPERS/jdk.sh" (cd "$ROOT" && ./gradlew assembleDebug --no-daemon -q) >>"$LOG" 2>&1 || fail "Build fehlgeschlagen, siehe $LOG" APK="$ROOT/app/build/outputs/apk/debug/app-debug.apk" fi [ -f "$APK" ] || fail "APK nicht gefunden: $APK" step "Emulator starten" "$HELPERS/emulator.sh" start | tee -a "$LOG" step "Installieren" # A debug build over a signed release needs the old one gone first. "$ADB" -s "$SERIAL" uninstall "$PKG" >/dev/null 2>&1 || true "$ADB" -s "$SERIAL" install -r "$APK" >>"$LOG" 2>&1 || fail "Installation fehlgeschlagen" step "Starten" "$ADB" -s "$SERIAL" logcat -c "$ADB" -s "$SERIAL" shell am start -W -n "$ACTIVITY" >>"$LOG" 2>&1 || fail "am start fehlgeschlagen" # The first frame is not the point — the crash usually lands a moment later, # when state loads. sleep 6 running() { [ -n "$("$ADB" -s "$SERIAL" shell pidof "$PKG" | tr -d '\r')" ]; } crashed() { "$ADB" -s "$SERIAL" logcat -d -b crash,main 2>/dev/null | grep -E "FATAL EXCEPTION|ANR in $PKG|Process $PKG .* has died" | head -20 } check() { local where="$1" trace trace="$(crashed || true)" if [ -n "$trace" ]; then printf '%s\n' "$trace" >>"$LOG" printf '%s\n' "$trace" | head -5 fail "Absturz $where — vollständig in $LOG" fi running || fail "Prozess weg $where (kein Stacktrace im Log)" } check "beim Start" "$HELPERS/emulator.sh" shot smoke-start >/dev/null step "D-Pad-Navigation" # Down/right walks the rail and opens whatever has focus; back returns. for key in DPAD_DOWN DPAD_RIGHT DPAD_RIGHT DPAD_DOWN DPAD_CENTER BACK DPAD_UP; do "$ADB" -s "$SERIAL" shell input keyevent "$key" sleep 1 done sleep 2 check "bei der Navigation" "$HELPERS/emulator.sh" shot smoke-nav >/dev/null step "Einstellungen öffnen" "$ADB" -s "$SERIAL" shell am start -n "$ACTIVITY" >/dev/null 2>&1 sleep 2 check "nach dem Wiedereintritt" if [ "$STOP_AFTER" = 1 ]; then step "Emulator stoppen" "$HELPERS/emulator.sh" stop | tee -a "$LOG" fi cat <