#!/usr/bin/env bash # Host-only regression tests. The fake adb rejects every non-read-only command. set -euo pipefail root=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd) tmp=$(mktemp -d) trap 'rm -rf -- "$tmp"' EXIT mkdir "$tmp/bin" export ADB_LOG="$tmp/adb.log" FAKE_MODE=ok cat > "$tmp/bin/adb" <<'FAKE' #!/usr/bin/env bash set -euo pipefail printf '%s\n' "$*" >> "$ADB_LOG" [[ "$*" == version ]] && { echo 'fake adb (test fixture, not device evidence)'; exit; } [[ "$1" == -s && "$2" == '192.0.2.1:5555' ]] || exit 90 shift 2 case "$*" in get-state) case "$FAKE_MODE" in absent|unauthorized) echo "$FAKE_MODE" >&2; exit 1 ;; offline) echo offline ;; *) echo device ;; esac ;; 'shell getprop') [[ "$FAKE_MODE" != disconnect ]] || exit 1 [[ "$FAKE_MODE" != emptyprops ]] || exit 0 printf '%s\r\n' '[ro.build.fingerprint]: [FAKE/TEST/ONLY]' '[ro.build.version.sdk]: [34]' '[ro.product.cpu.abilist]: [armeabi-v7a]' ;; 'shell pm list packages --user 0'|'shell pm list packages -e --user 0') [[ "$FAKE_MODE" != empty ]] || exit 0 [[ "$FAKE_MODE" != pmerror ]] || { echo 'Error: user unavailable'; exit; } [[ "$FAKE_MODE" != malicious ]] || { echo 'package:evil;touch /tmp/no'; exit; } printf 'package:%s\r\n' android com.google.android.apps.tv.launcherx com.google.android.katniss com.google.android.gms com.android.vending if [[ "$*" == 'shell pm list packages --user 0' ]]; then [[ "$FAKE_MODE" == nodisabled ]] || echo 'package:com.google.android.videos' fi ;; 'shell pm list packages -d --user 0') [[ "$FAKE_MODE" != inconsistent && "$FAKE_MODE" != nodisabled ]] || exit 0 echo 'package:com.google.android.videos' [[ "$FAKE_MODE" != overlap ]] || echo 'package:com.google.android.katniss' ;; *) echo 'FORBIDDEN adb command' >&2; exit 99 ;; esac FAKE chmod +x "$tmp/bin/adb" export PATH="$tmp/bin:$PATH" script="$root/scripts/device-inventory.sh" expect_failure() { if bash "$script" "$@" > "$tmp/stdout" 2> "$tmp/stderr"; then echo "Expected failure: $*" >&2; exit 1 fi } expect_failure expect_failure --serial 192.0.2.1:5555 expect_failure --output-dir "$tmp/missing-serial" expect_failure --serial 'bad;serial' --output-dir "$tmp/bad" expect_failure --serial 192.0.2.1:5555 --serial other --output-dir "$tmp/bad" expect_failure --serial 192.0.2.1:5555 --output-dir "$tmp/bad" --unknown [[ ! -e "$ADB_LOG" ]] # Argument errors must never invoke adb. for mode in absent unauthorized offline disconnect emptyprops empty pmerror malicious inconsistent overlap; do export FAKE_MODE=$mode expect_failure --serial 192.0.2.1:5555 --output-dir "$tmp/$mode" [[ ! -e "$tmp/$mode/rollback.txt" && ! -e "$tmp/$mode/COMPLETE.txt" ]] case "$mode" in absent|unauthorized|offline) [[ ! -e "$tmp/$mode" ]] ;; *) [[ -f "$tmp/$mode/INCOMPLETE.txt" ]] ;; esac done export FAKE_MODE=ok out="$tmp/valid capture" bash "$script" --serial 192.0.2.1:5555 --output-dir "$out" [[ -f "$out/COMPLETE.txt" && ! -e "$out/INCOMPLETE.txt" ]] [[ ! -x "$out/rollback.txt" ]] grep -Fxq 'adb -s 192.0.2.1:5555 shell pm enable --user 0 com.google.android.apps.tv.launcherx' "$out/rollback.txt" grep -Fxq 'adb -s 192.0.2.1:5555 shell cmd package install-existing --user 0 com.google.android.katniss' "$out/rollback.txt" [[ $(grep -c '^adb ' "$out/rollback.txt") == 3 ]] # Disabled, absent, and protected packages must have no recovery commands. ! grep -Eq '^adb .* (com.google.android.videos|com.google.android.tungsten.setupwraith|com.google.android.gms|com.android.vending)$' "$out/rollback.txt" ! grep -Eq 'disable-user|uninstall|install-existing|pm enable|reboot| install ' "$ADB_LOG" cp "$out/rollback.txt" "$tmp/expected" expect_failure --serial 192.0.2.1:5555 --output-dir "$out" cmp "$tmp/expected" "$out/rollback.txt" ln -s "$out" "$tmp/link" expect_failure --serial 192.0.2.1:5555 --output-dir "$tmp/link" export FAKE_MODE=nodisabled bash "$script" --serial 192.0.2.1:5555 --output-dir "$tmp/no-disabled" [[ -f "$tmp/no-disabled/COMPLETE.txt" && ! -s "$tmp/no-disabled/packages-disabled.txt" ]] echo 'PASS: inventory safety and recovery-plan tests (fake adb only)'