Run the face tests on the tablet, where the NEON kernel actually runs
The similarity scan picks its dot product per machine, and the NEON one is the kernel that ships to the phone and the tablet — and the one a desktop cargo test never executes. A wrong lane index or a mishandled tail there is a silent wrong answer on exactly the devices nobody runs the suite on, which is a poor place for the only untested code path. dr-face carries no weights and touches no display, so its tests are a plain ARM64 binary that runs under adb shell with nothing installed. The script builds it against the SDK's newest NDK, pushes it, runs it and cleans up. It checks for the device first, so a tablet that is not plugged in costs a second rather than the two minutes it takes to compile for it. Not wired into CI, which has no device attached. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Executable
+78
@@ -0,0 +1,78 @@
|
||||
#!/usr/bin/env bash
|
||||
# Run dr-face's test suite on a connected Android device.
|
||||
#
|
||||
# ./tools/face-tests-on-device.sh [extra cargo test args…]
|
||||
#
|
||||
# ## Why this exists
|
||||
#
|
||||
# `dr-face`'s similarity scan picks its dot product per machine (docs/faces.md
|
||||
# §9): AVX2 where the CPU has it, **NEON on aarch64**, and a portable loop
|
||||
# otherwise. The NEON kernel is the one that runs on the phone and the tablet,
|
||||
# and it is the one a desktop `cargo test` never executes — a wrong lane index
|
||||
# or a mishandled tail there would be a silent wrong answer on exactly the
|
||||
# devices nobody runs the test suite on.
|
||||
#
|
||||
# `the_fastest_kernel_agrees_with_the_portable_one` is written to catch that,
|
||||
# and this is how it gets to run on the hardware it is about. Everything else
|
||||
# in the suite comes along for free: `dr-face` carries no weights and touches
|
||||
# no display, so its tests are a plain ARM64 binary that runs under `adb
|
||||
# shell` with nothing installed.
|
||||
#
|
||||
# Not part of CI, which has no device attached. Run it when the kernels change.
|
||||
set -euo pipefail
|
||||
|
||||
TARGET=aarch64-linux-android
|
||||
API=26
|
||||
DEST=/data/local/tmp/dr_face_tests
|
||||
|
||||
ndk="${ANDROID_NDK_HOME:-}"
|
||||
if [[ -z "$ndk" ]]; then
|
||||
# The newest NDK the SDK has, which is what the app is built with.
|
||||
ndk=$(find "${ANDROID_HOME:-$HOME/Android/Sdk}/ndk" -maxdepth 1 -mindepth 1 -type d 2>/dev/null |
|
||||
sort -V | tail -1)
|
||||
fi
|
||||
[[ -n "$ndk" && -d "$ndk" ]] || {
|
||||
echo "no NDK found — set ANDROID_NDK_HOME" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
clang="$ndk/toolchains/llvm/prebuilt/linux-x86_64/bin/$TARGET$API-clang"
|
||||
[[ -x "$clang" ]] || {
|
||||
echo "no $TARGET$API-clang in $ndk" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
rustup target list --installed | grep -qx "$TARGET" || rustup target add "$TARGET"
|
||||
|
||||
# Told to the device before the build, so a missing tablet costs seconds rather
|
||||
# than the two minutes it takes to compile for it.
|
||||
adb devices | grep -qw device || {
|
||||
echo "no device attached — plug the tablet in and enable USB debugging" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
echo "building dr-face tests for $TARGET…"
|
||||
binary=$(
|
||||
CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER="$clang" \
|
||||
CC_aarch64_linux_android="$clang" \
|
||||
cargo test -p dr-face --lib --release --target "$TARGET" --no-run --message-format=json "$@" |
|
||||
python3 -c '
|
||||
import json, sys
|
||||
for line in sys.stdin:
|
||||
m = json.loads(line)
|
||||
if m.get("profile", {}).get("test") and m.get("executable"):
|
||||
print(m["executable"])
|
||||
' | tail -1
|
||||
)
|
||||
[[ -n "$binary" ]] || {
|
||||
echo "cargo produced no test binary" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
echo "pushing $(basename "$binary")…"
|
||||
adb push "$binary" "$DEST" >/dev/null
|
||||
adb shell chmod 755 "$DEST"
|
||||
# `--test-threads` left alone: the scan spawns its own workers and the point is
|
||||
# to exercise them the way the app will.
|
||||
adb shell "$DEST" --color never
|
||||
adb shell rm -f "$DEST"
|
||||
Reference in New Issue
Block a user