#!/bin/sh
# Run scrcpy-android tests inside the project-local Docker image.
#
#   ./test          unit tests (JVM only, no KVM)
#   ./test unit     same
#   ./test e2e      single-emulator self-mirror E2E (needs /dev/kvm)
#   ./test all      unit + e2e
#   ./test record   boot emulator, run a Mirror session, inject events,
#                   capture screen recording to ./output.mp4 (needs /dev/kvm)
#   ./test apk      build a signed release APK with a throwaway keystore
#                   (exercises scripts/build-apk end-to-end, no KVM)
#
# The image is built on first run and cached as $IMG.
# /dev/kvm must be readable by the invoking user for `./test e2e` and `record`.

set -eu

ROOT="$(cd "$(dirname "$0")" && pwd)"
# The image tag is a hash of the rig inputs, so editing the Dockerfile
# or the SDK package list automatically invalidates the cached image.
IMG="scrcpy-android-test:$(cat "$ROOT/test-rig/Dockerfile" "$ROOT/test-rig/sdk-packages.txt" | sha256sum | cut -c1-12)"

cmd="${1:-unit}"
case "$cmd" in
    unit|e2e|all|record|apk) ;;
    -h|--help)
        sed -n '2,14p' "$0" >&2
        exit 0 ;;
    *)
        echo "usage: $0 [unit|e2e|all|record|apk]" >&2
        exit 2 ;;
esac

# Cheap supply-chain check: the gradle wrapper jar is a small binary
# we check into the tree; verify its sha before letting it run.
"$ROOT/scripts/check-wrapper"

# Build the image if needed. --network=host so RUN apt/curl can reach
# the outside on hosts where the default docker bridge has no DNS.
if ! docker image inspect "$IMG" >/dev/null 2>&1; then
    echo "test: building $IMG (first run, ~10 min)" >&2
    # Cheap pre-flight: warn the user up-front if the host can't resolve
    # the docker registry, so they don't watch an apt step time out.
    if ! getent hosts registry-1.docker.io >/dev/null 2>&1; then
        echo "test: WARNING - registry-1.docker.io did not resolve via /etc/resolv.conf." >&2
        echo "             Build will likely fail. Fix the host DNS (e.g." >&2
        echo "             append 'nameserver 1.1.1.1' to /etc/resolv.conf) and retry." >&2
    fi
    docker build --network=host -t "$IMG" "$ROOT/test-rig"
fi

# KVM check for tiers that boot the emulator.
needs_kvm=
case "$cmd" in
    e2e|all|record) needs_kvm=1 ;;
esac

kvm_args=
if [ -n "$needs_kvm" ]; then
    if [ ! -e /dev/kvm ]; then
        echo "test: /dev/kvm not present on this host - e2e cannot run." >&2
        exit 3
    fi
    if [ ! -r /dev/kvm ] || [ ! -w /dev/kvm ]; then
        echo "test: /dev/kvm exists but is not rw for uid $(id -u)." >&2
        echo "      one-time fix:" >&2
        echo "          sudo chmod 666 /dev/kvm" >&2
        echo "      or add yourself to the kvm group and re-login:" >&2
        echo "          sudo usermod -aG kvm $(id -un)" >&2
        exit 3
    fi
    # Pass through /dev/kvm's owning gid (numeric - group names from the
    # host don't exist inside the container) so the container user
    # (mapped to host uid:gid) can actually open it.
    kvm_args="--device /dev/kvm --group-add $(stat -c %g /dev/kvm)"
fi

# Forward Ctrl-C cleanly, run as the host user so files in .tools/ stay
# owned by the invoker (avoids root-owned gradle cache on the host).
# --network=host so the gradle wrapper can fetch the distribution and
# maven deps in environments where the docker bridge DNS misbehaves.
exec docker run --rm -i \
    --network=host \
    $kvm_args \
    -u "$(id -u):$(id -g)" \
    -v "$ROOT":/work \
    -w /work \
    -e HOME=/work/.tools/home \
    "$IMG" \
    /work/test-rig/run.sh "$cmd"
