168 lines
6.1 KiB
Bash
Executable File
168 lines
6.1 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Smoke test on the headless Google TV emulator.
|
|
#
|
|
# Builds the debug APK, seeds the demo playlist as its source, installs it
|
|
# and walks from the channel list into the player with the D-pad. Fails on
|
|
# anything the unit tests cannot see: a crash on startup, a crash while
|
|
# navigating, an ANR, or a channel list that stayed empty. 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 <path> # 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"
|
|
DEMO_PORT="${CASTARR_DEMO_PORT:-8099}"
|
|
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 <path>] [--stop]" >&2; exit 2 ;;
|
|
esac
|
|
done
|
|
|
|
mkdir -p "$RUNS/screenshots"
|
|
LOG="$RUNS/smoke.log"
|
|
: > "$LOG"
|
|
# The player retries the fake demo stream for as long as it is on screen, so
|
|
# without this the request log grows by a few hundred KB per run.
|
|
: > "$RUNS/http.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 "Demo-Quelle bereitstellen"
|
|
python3 "$ROOT/tests/demo/make-demo-data.py" >>"$LOG" 2>&1 || fail "Demo-Daten fehlgeschlagen"
|
|
# The emulator reaches the host at 10.0.2.2, which is the address baked into
|
|
# the demo playlist.
|
|
# A leftover server from an earlier run happily answers on this port while
|
|
# serving a directory that no longer exists — every request a 404, and the
|
|
# wait below would spin forever.
|
|
if ss -ltn "sport = :$DEMO_PORT" 2>/dev/null | grep -q LISTEN; then
|
|
fail "Port $DEMO_PORT ist belegt: $(ss -ltnp "sport = :$DEMO_PORT" 2>/dev/null | tail -1)"
|
|
fi
|
|
# 10.0.2.2 inside the emulator is the host loopback, so binding there is enough.
|
|
(cd "$ROOT/tests/demo" && exec python3 -m http.server "$DEMO_PORT" --bind 127.0.0.1) \
|
|
>>"$RUNS/http.log" 2>&1 &
|
|
DEMO_PID=$!
|
|
trap 'kill "$DEMO_PID" 2>/dev/null || true' EXIT
|
|
for _ in $(seq 1 50); do
|
|
curl -sf "http://127.0.0.1:$DEMO_PORT/playlist.m3u" -o /dev/null && break
|
|
sleep 0.2
|
|
done
|
|
curl -sf "http://127.0.0.1:$DEMO_PORT/playlist.m3u" -o /dev/null ||
|
|
fail "Demo-Server antwortet nicht auf Port $DEMO_PORT"
|
|
|
|
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"
|
|
|
|
# Onboarding runs on a phone (ADR-0007), which a test has no way to be, so
|
|
# the source is seeded straight into the preferences the first run reads.
|
|
# Only a debug build allows this, which is the build under test.
|
|
"$ADB" -s "$SERIAL" shell run-as "$PKG" sh -c "'mkdir -p shared_prefs && cat > shared_prefs/source.xml'" <<XML || fail "Quelle konnte nicht gesetzt werden"
|
|
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
|
|
<map>
|
|
<string name="m3u_url">http://10.0.2.2:$DEMO_PORT/playlist.m3u</string>
|
|
<string name="epg_url">http://10.0.2.2:$DEMO_PORT/epg.xml</string>
|
|
</map>
|
|
XML
|
|
|
|
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
|
|
|
|
# Reaching the channel list is the point: it is the screen the demo source
|
|
# feeds, and a blank one means the playlist never arrived.
|
|
step "Senderliste prüfen"
|
|
DUMP="$RUNS/ui-dump.xml"
|
|
"$ADB" -s "$SERIAL" shell uiautomator dump /sdcard/ui.xml >>"$LOG" 2>&1 || true
|
|
"$ADB" -s "$SERIAL" pull /sdcard/ui.xml "$DUMP" >>"$LOG" 2>&1 || true
|
|
if grep -q "Blau TV HD" "$DUMP" 2>/dev/null; then
|
|
echo " Sender aus der Demo-Playlist sichtbar"
|
|
else
|
|
fail "Senderliste zeigt die Demo-Playlist nicht — Dump in $DUMP"
|
|
fi
|
|
|
|
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 "Wiedereintritt"
|
|
"$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 <<EOF
|
|
|
|
OK — kein Absturz, App läuft.
|
|
Screenshots: $RUNS/screenshots/smoke-start.png, smoke-nav.png
|
|
Log: $LOG
|
|
|
|
Abgedeckt: Start mit gesetzter Quelle, Senderliste aus der Demo-Playlist,
|
|
D-Pad bis in den Player, Wiedereintritt. Nicht abgedeckt: echte Wiedergabe
|
|
(die Demo-Streams sind Attrappen), Onboarding am Handy, Kopplung und alles,
|
|
was ein Dispatcharr-Backend braucht.
|
|
EOF
|