Skip to content

Commit 4654849

Browse files
committed
Ensure emulator API readiness before running Android UI tests
1 parent cfa363e commit 4654849

File tree

1 file changed

+151
-29
lines changed

1 file changed

+151
-29
lines changed

scripts/build-android-app.sh

Lines changed: 151 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,106 @@ wait_for_package_service() {
497497
return 1
498498
}
499499

500+
wait_for_api_level() {
501+
local serial="$1"
502+
local timeout="${API_LEVEL_TIMEOUT_SECONDS:-600}"
503+
local per_try="${API_LEVEL_PER_TRY_TIMEOUT_SECONDS:-5}"
504+
if ! [[ "$timeout" =~ ^[0-9]+$ ]] || [ "$timeout" -le 0 ]; then
505+
timeout=600
506+
fi
507+
if ! [[ "$per_try" =~ ^[0-9]+$ ]] || [ "$per_try" -le 0 ]; then
508+
per_try=5
509+
fi
510+
511+
local deadline=$((SECONDS + timeout))
512+
local last_log=$SECONDS
513+
local sdk=""
514+
515+
while [ $SECONDS -lt $deadline ]; do
516+
if sdk="$(timeout "$per_try" "$ADB_BIN" -s "$serial" shell getprop ro.build.version.sdk 2>/dev/null | tr -d '\r' | tr -d '\n')"; then
517+
if [[ "$sdk" =~ ^[0-9]+$ ]]; then
518+
ba_log "Device API level is $sdk"
519+
return 0
520+
fi
521+
fi
522+
if [ $((SECONDS - last_log)) -ge 10 ]; then
523+
ba_log "Waiting for ro.build.version.sdk on $serial"
524+
last_log=$SECONDS
525+
fi
526+
sleep 2
527+
done
528+
529+
ba_log "ro.build.version.sdk not available after ${timeout}s" >&2
530+
return 1
531+
}
532+
533+
dump_emulator_diagnostics() {
534+
"$ADB_BIN" -s "$EMULATOR_SERIAL" shell getprop | sed 's/^/[build-android-app] getprop: /' || true
535+
"$ADB_BIN" -s "$EMULATOR_SERIAL" shell logcat -d -t 2000 \
536+
| grep -v -E 'com\\.android\\.bluetooth|BtGd|bluetooth' \
537+
| tail -n 200 | sed 's/^/[build-android-app] logcat: /' || true
538+
}
539+
540+
log_instrumentation_state() {
541+
"$ADB_BIN" -s "$EMULATOR_SERIAL" shell pm path android \
542+
| sed 's/^/[build-android-app] pm path android: /' || true
543+
544+
local instrumentation_list
545+
instrumentation_list="$("$ADB_BIN" -s "$EMULATOR_SERIAL" shell pm list instrumentation 2>/dev/null || true)"
546+
if [ -n "$instrumentation_list" ]; then
547+
printf '%s\n' "$instrumentation_list" | sed 's/^/[build-android-app] instrumentation: /'
548+
else
549+
ba_log "No instrumentation targets reported on $EMULATOR_SERIAL before installation"
550+
fi
551+
552+
local have_test_apk=0
553+
if "$ADB_BIN" -s "$EMULATOR_SERIAL" shell pm path "${PACKAGE_NAME}.test" >/dev/null 2>&1; then
554+
have_test_apk=1
555+
"$ADB_BIN" -s "$EMULATOR_SERIAL" shell pm path "${PACKAGE_NAME}.test" \
556+
| sed 's/^/[build-android-app] test-apk: /'
557+
else
558+
ba_log "Test APK for ${PACKAGE_NAME}.test not yet installed on $EMULATOR_SERIAL"
559+
fi
560+
561+
local package_regex package_list package_matches
562+
package_regex="${PACKAGE_NAME//./\.}"
563+
package_list="$("$ADB_BIN" -s "$EMULATOR_SERIAL" shell pm list packages 2>/dev/null || true)"
564+
if [ -n "$package_list" ]; then
565+
package_matches="$(printf '%s\n' "$package_list" | grep -E "${package_regex}|${package_regex}\.test" || true)"
566+
if [ -n "$package_matches" ]; then
567+
printf '%s\n' "$package_matches" | sed 's/^/[build-android-app] package: /'
568+
else
569+
ba_log "Packages matching $PACKAGE_NAME not yet installed on $EMULATOR_SERIAL"
570+
fi
571+
else
572+
ba_log "Package manager returned no packages on $EMULATOR_SERIAL"
573+
fi
574+
575+
local instrumentation_target instrumentation_line
576+
instrumentation_target=""
577+
if [ -n "$instrumentation_list" ]; then
578+
instrumentation_line="$(printf '%s\n' "$instrumentation_list" | awk -v pkg='${PACKAGE_NAME}.test' '$0 ~ pkg {print; exit}')"
579+
if [ -n "$instrumentation_line" ]; then
580+
instrumentation_target="${instrumentation_line#instrumentation:}"
581+
instrumentation_target="${instrumentation_target%% *}"
582+
else
583+
instrumentation_target="$(printf '%s\n' "$instrumentation_list" | awk -F' ' '/^instrumentation:/{print $1}' | head -n1)"
584+
instrumentation_target="${instrumentation_target#instrumentation:}"
585+
fi
586+
fi
587+
588+
if [ -n "$instrumentation_target" ] && [ "$have_test_apk" -eq 1 ]; then
589+
"$ADB_BIN" -s "$EMULATOR_SERIAL" shell am instrument -w -r \
590+
-e log true \
591+
"$instrumentation_target" \
592+
2>&1 | sed 's/^/[build-android-app] am instrument: /'
593+
elif [ -n "$instrumentation_target" ]; then
594+
ba_log "Instrumentation target $instrumentation_target available but test APK missing; skipping am instrument dry run"
595+
else
596+
ba_log "Skipping am instrument dry run; no instrumentation target detected on $EMULATOR_SERIAL"
597+
fi
598+
}
599+
500600
stop_emulator() {
501601
if [ -n "${EMULATOR_SERIAL:-}" ]; then
502602
"$ADB_BIN" -s "$EMULATOR_SERIAL" emu kill >/dev/null 2>&1 || true
@@ -619,46 +719,68 @@ if [ "$POST_BOOT_GRACE" -gt 0 ]; then
619719
fi
620720

621721
if ! wait_for_package_service "$EMULATOR_SERIAL"; then
622-
"$ADB_BIN" -s "$EMULATOR_SERIAL" shell getprop | sed 's/^/[build-android-app] getprop: /' || true
623-
"$ADB_BIN" -s "$EMULATOR_SERIAL" shell logcat -d -t 2000 \
624-
| grep -v -E 'com\.android\.bluetooth|BtGd|bluetooth' \
625-
| tail -n 200 | sed 's/^/[build-android-app] logcat: /' || true
722+
dump_emulator_diagnostics
626723
stop_emulator
627724
exit 1
628725
fi
629726

630-
"$ADB_BIN" -s "$EMULATOR_SERIAL" shell pm path android \
631-
| sed 's/^/[build-android-app] pm path android: /' || true
632-
INSTRUMENTATION_LIST="$("$ADB_BIN" -s "$EMULATOR_SERIAL" shell pm list instrumentation 2>/dev/null || true)"
633-
if [ -n "$INSTRUMENTATION_LIST" ]; then
634-
printf '%s\n' "$INSTRUMENTATION_LIST" | sed 's/^/[build-android-app] instrumentation: /'
635-
else
636-
ba_log "No instrumentation targets reported on $EMULATOR_SERIAL before installation"
727+
if ! wait_for_api_level "$EMULATOR_SERIAL"; then
728+
dump_emulator_diagnostics
729+
stop_emulator
730+
exit 1
637731
fi
638732

639-
PACKAGE_REGEX="${PACKAGE_NAME//./\\.}"
640-
PACKAGE_LIST="$("$ADB_BIN" -s "$EMULATOR_SERIAL" shell pm list packages 2>/dev/null || true)"
641-
if [ -n "$PACKAGE_LIST" ]; then
642-
PACKAGE_MATCHES="$(printf '%s\n' "$PACKAGE_LIST" | grep -E "${PACKAGE_REGEX}|${PACKAGE_REGEX}\\.test" || true)"
643-
if [ -n "$PACKAGE_MATCHES" ]; then
644-
printf '%s\n' "$PACKAGE_MATCHES" | sed 's/^/[build-android-app] package: /'
645-
else
646-
ba_log "Packages matching $PACKAGE_NAME not yet installed on $EMULATOR_SERIAL"
647-
fi
648-
else
649-
ba_log "Package manager returned no packages on $EMULATOR_SERIAL"
733+
"$ADB_BIN" kill-server >/dev/null 2>&1 || true
734+
"$ADB_BIN" start-server >/dev/null 2>&1 || true
735+
"$ADB_BIN" -s "$EMULATOR_SERIAL" wait-for-device
736+
export ANDROID_SERIAL="$EMULATOR_SERIAL"
737+
738+
INSTALL_TIMEOUT_SECONDS="${INSTALL_TIMEOUT_SECONDS:-600}"
739+
if ! [[ "$INSTALL_TIMEOUT_SECONDS" =~ ^[0-9]+$ ]] || [ "$INSTALL_TIMEOUT_SECONDS" -le 0 ]; then
740+
INSTALL_TIMEOUT_SECONDS=600
650741
fi
651742

652-
INSTRUMENTATION_TARGET="$(printf '%s\n' "$INSTRUMENTATION_LIST" | awk -F' ' '/instrumentation/{print $2}' | head -n1)"
653-
if [ -n "$INSTRUMENTATION_TARGET" ]; then
654-
"$ADB_BIN" -s "$EMULATOR_SERIAL" shell am instrument -w -r \
655-
-e log true \
656-
"$INSTRUMENTATION_TARGET" \
657-
2>&1 | sed 's/^/[build-android-app] am instrument: /'
743+
INSTALL_CMD=(
744+
"./gradlew"
745+
"--no-daemon"
746+
"installDebug"
747+
"installDebugAndroidTest"
748+
)
749+
if command -v timeout >/dev/null 2>&1; then
750+
ba_log "Installing app and androidTest APKs with external timeout of ${INSTALL_TIMEOUT_SECONDS}s"
751+
INSTALL_CMD=("timeout" "$INSTALL_TIMEOUT_SECONDS" "${INSTALL_CMD[@]}")
658752
else
659-
ba_log "Skipping am instrument dry run; no instrumentation target detected on $EMULATOR_SERIAL"
753+
ba_log "timeout command not found; running install tasks without external watchdog"
660754
fi
661755

756+
GRADLE_INSTALL_LOG="$GRADLE_PROJECT_DIR/gradle-ui-install.log"
757+
set +e
758+
(
759+
cd "$GRADLE_PROJECT_DIR"
760+
"${INSTALL_CMD[@]}" | tee "$GRADLE_INSTALL_LOG"
761+
exit "${PIPESTATUS[0]}"
762+
)
763+
INSTALL_EXIT_CODE=$?
764+
set -e
765+
766+
if [ -f "$GRADLE_INSTALL_LOG" ]; then
767+
cp "$GRADLE_INSTALL_LOG" "$FINAL_ARTIFACT_DIR/ui-test-install.log"
768+
ba_log "Gradle install log saved to $FINAL_ARTIFACT_DIR/ui-test-install.log"
769+
fi
770+
771+
if [ "$INSTALL_EXIT_CODE" -ne 0 ]; then
772+
ba_log "Gradle install tasks exited with status $INSTALL_EXIT_CODE"
773+
stop_emulator
774+
exit 1
775+
fi
776+
777+
log_instrumentation_state
778+
779+
"$ADB_BIN" kill-server >/dev/null 2>&1 || true
780+
"$ADB_BIN" start-server >/dev/null 2>&1 || true
781+
"$ADB_BIN" -s "$EMULATOR_SERIAL" wait-for-device
782+
export ANDROID_SERIAL="$EMULATOR_SERIAL"
783+
662784
UI_TEST_TIMEOUT_SECONDS="${UI_TEST_TIMEOUT_SECONDS:-900}"
663785
if ! [[ "$UI_TEST_TIMEOUT_SECONDS" =~ ^[0-9]+$ ]] || [ "$UI_TEST_TIMEOUT_SECONDS" -le 0 ]; then
664786
ba_log "Invalid UI_TEST_TIMEOUT_SECONDS=$UI_TEST_TIMEOUT_SECONDS provided; falling back to 900"

0 commit comments

Comments
 (0)