aboutsummaryrefslogtreecommitdiff
path: root/test-rig/e2e.sh
diff options
context:
space:
mode:
Diffstat (limited to 'test-rig/e2e.sh')
-rwxr-xr-xtest-rig/e2e.sh172
1 files changed, 172 insertions, 0 deletions
diff --git a/test-rig/e2e.sh b/test-rig/e2e.sh
new file mode 100755
index 0000000..ae2a1a8
--- /dev/null
+++ b/test-rig/e2e.sh
@@ -0,0 +1,172 @@
+#!/bin/sh
+# Single-emulator self-mirror E2E.
+#
+# Boot an AOSP API-35 emulator, root it, install the app, let it
+# generate its keypair, copy that pubkey into /data/misc/adb/adb_keys
+# so the app can connect to its own host's adbd over TCP, launch
+# Mirror against 127.0.0.1:5555, wait for the first video frame in
+# logcat, screencap, assert the frame is non-uniform.
+#
+# Runs inside the test image; orchestrated by ../test.
+
+set -eu
+
+ROOT=/work
+# Debug applicationId (note the .debug suffix). Activity classes live in
+# the invalid.lena.scrcpy namespace, which carries no suffix.
+PKG=invalid.lena.scrcpy.debug
+AVD=scrcpy-test
+SERIAL=emulator-5554
+APK=$ROOT/app/build/outputs/apk/debug/app-debug.apk
+TMPDIR=$ROOT/.tools/e2e
+mkdir -p "$TMPDIR"
+
+log() { printf 'e2e: %s\n' "$*" >&2; }
+
+# ---- 0. server jar ----
+[ -f "$ROOT/app/src/main/assets/scrcpy-server.jar" ] || "$ROOT/scripts/update-server"
+
+# ---- 1. build APK ----
+log 'gradle :app:assembleDebug'
+"$ROOT/gradlew" --no-daemon -q :app:assembleDebug
+
+# ---- 2. AVD + boot ----
+if ! avdmanager list avd | grep -q "Name: $AVD$"; then
+ log "creating avd $AVD"
+ echo no | avdmanager create avd -n "$AVD" -k 'system-images;android-35;default;x86_64' -d pixel >/dev/null
+fi
+
+# Clean stale lock files from a previously aborted run; otherwise the
+# emulator refuses to start ("Running multiple emulators with the same AVD").
+AVD_DIR="$ANDROID_AVD_HOME/$AVD.avd"
+rm -f "$AVD_DIR"/multiinstance.lock "$AVD_DIR"/hardware-qemu.ini.lock 2>/dev/null || true
+rm -rf "$HOME/.android/avd/running" 2>/dev/null || true
+
+if ! pgrep -f "emulator.*-avd $AVD" >/dev/null; then
+ log 'booting emulator (no window, no snapshot)'
+ emulator -avd "$AVD" -no-window -no-audio -no-snapshot -gpu swiftshader_indirect \
+ -no-boot-anim -accel on >"$TMPDIR/emulator.log" 2>&1 &
+fi
+
+log 'wait-for-device'
+adb -s "$SERIAL" wait-for-device
+log 'wait for boot'
+until [ "$(adb -s "$SERIAL" shell getprop sys.boot_completed | tr -d '\r')" = 1 ]; do
+ sleep 2
+done
+
+# ---- 3. root (emulator adbd already listens on TCP 5555) ----
+log 'adb root'
+adb -s "$SERIAL" root
+adb -s "$SERIAL" wait-for-device
+
+# ---- 4. install ----
+log "install $APK"
+adb -s "$SERIAL" install -r "$APK" >/dev/null
+
+# ---- 5. let the app generate its keypair ----
+log "launching Main once so Adb.java writes filesDir/adbkey"
+adb -s "$SERIAL" shell am start -W -n "$PKG/invalid.lena.scrcpy.Main" >/dev/null
+# Adb.java writes the keypair inside its constructor, before setContentView
+sleep 1
+
+# ---- 6. extract pubkey and authorise ----
+log 'reading filesDir/adbkey via run-as'
+adb -s "$SERIAL" shell "run-as $PKG cat files/adbkey" > "$TMPDIR/adbkey.der"
+if [ ! -s "$TMPDIR/adbkey.der" ]; then
+ log 'adbkey was empty - did Adb.java run?'
+ adb -s "$SERIAL" logcat -d -t 200 -s scrcpy-android >&2 || true
+ exit 1
+fi
+
+log 'computing android pubkey blob'
+java "$ROOT/test-rig/Keygen.java" "$TMPDIR/adbkey.der" > "$TMPDIR/adb_keys.line"
+
+log 'appending to /data/misc/adb/adb_keys'
+adb -s "$SERIAL" push "$TMPDIR/adb_keys.line" /sdcard/adb_keys.line >/dev/null
+adb -s "$SERIAL" shell "cat /sdcard/adb_keys.line >> /data/misc/adb/adb_keys \
+ && chown system:shell /data/misc/adb/adb_keys \
+ && chmod 640 /data/misc/adb/adb_keys \
+ && rm /sdcard/adb_keys.line"
+
+# adbd rereads /data/misc/adb/adb_keys on every AUTH challenge,
+# so no daemon restart is necessary. Restarting it would put the
+# host's adb client into 'offline' state and force a reconnect dance.
+
+# ---- 7. trigger Mirror ----
+log 'starting Mirror -> 127.0.0.1:5555'
+adb -s "$SERIAL" logcat -c
+adb -s "$SERIAL" shell am start -n "$PKG/invalid.lena.scrcpy.Mirror" \
+ --es host 127.0.0.1 --ei port 5555 >/dev/null
+
+# ---- 8. wait for first frame, fail on session give-up ----
+# Server's openAbstract budget (Server.OPEN_DEADLINE_MS) must stay
+# shorter than this deadline; otherwise our retries finish before
+# we've given the wire a chance.
+deadline=$(( $(date +%s) + ${E2E_DEADLINE:-60} ))
+ok=
+while [ "$(date +%s)" -lt "$deadline" ]; do
+ line=$(adb -s "$SERIAL" logcat -d -s scrcpy-android | tail -200)
+ if printf '%s' "$line" | grep -q 'video frame n=1'; then
+ ok=1; break
+ fi
+ if printf '%s' "$line" | grep -q 'session: gave up'; then
+ log 'session gave up; logcat:'
+ printf '%s\n' "$line" | tail -50 >&2
+ exit 1
+ fi
+ sleep 1
+done
+if [ -z "$ok" ]; then
+ log 'timed out waiting for video frame n=1'
+ log "full app log: $TMPDIR/logcat.scrcpy"
+ adb -s "$SERIAL" logcat -d -s scrcpy-android > "$TMPDIR/logcat.scrcpy" 2>&1 || true
+ log "full system log: $TMPDIR/logcat.full"
+ adb -s "$SERIAL" logcat -d > "$TMPDIR/logcat.full" 2>&1 || true
+ log 'last 80 scrcpy-android lines:'
+ tail -80 "$TMPDIR/logcat.scrcpy" >&2 || true
+ exit 1
+fi
+log 'video frame n=1 - proceeding to screencap'
+
+# Give the decoder a moment to actually render to the surface.
+sleep 1
+
+# ---- 9. screencap + pixhash ----
+adb -s "$SERIAL" exec-out screencap -p > "$TMPDIR/shot.png"
+log "screencap $(wc -c <"$TMPDIR/shot.png") bytes"
+java "$ROOT/test-rig/Pixhash.java" "$TMPDIR/shot.png" --min 5
+
+# ---- 9b. mid-session disconnect -> auto-reconnect ----
+# Kill the scrcpy server on the target out from under the app. The video
+# socket dies; Session.run() must detect it, rerun the bring-up ladder,
+# and a fresh VideoStream must log 'video frame n=1' again. Clear logcat
+# first so the only frame we can match is the post-reconnect one.
+log 'forcing a mid-session disconnect (pkill scrcpy server on target)'
+adb -s "$SERIAL" logcat -c
+adb -s "$SERIAL" shell 'pkill -f com.genymobile.scrcpy.Server' || true
+
+rdeadline=$(( $(date +%s) + ${E2E_RECONNECT_DEADLINE:-60} ))
+relink=
+while [ "$(date +%s)" -lt "$rdeadline" ]; do
+ if adb -s "$SERIAL" logcat -d -s scrcpy-android | grep -q 'video frame n=1'; then
+ relink=1; break
+ fi
+ sleep 1
+done
+if [ -z "$relink" ]; then
+ log 'timed out waiting for auto-reconnect (no fresh video frame n=1)'
+ adb -s "$SERIAL" logcat -d -s scrcpy-android > "$TMPDIR/logcat.reconnect" 2>&1 || true
+ log "full app log: $TMPDIR/logcat.reconnect"
+ tail -80 "$TMPDIR/logcat.reconnect" >&2 || true
+ exit 1
+fi
+log 'auto-reconnect ok - fresh video frame n=1 after link loss'
+
+# ---- 10. cleanup ----
+log "full app log: $TMPDIR/logcat.scrcpy"
+adb -s "$SERIAL" logcat -d -s scrcpy-android > "$TMPDIR/logcat.scrcpy" 2>&1 || true
+log 'adb emu kill'
+adb -s "$SERIAL" emu kill || true
+
+log 'e2e: pass'