docs/ had 26 developer documents flat beside the manual, and the two audiences are very differently sized: most readers want the manual and the gesture reference, a few want the register, the designs and the measurements. The manual and gestures.md stay at the top; everything for someone changing the code moves to docs/dev/, and the two documents that name their own successors — the v0.1 milestone and the UI-refinement plan — go to docs/dev/archive/ rather than being deleted, since both are still cited. docs/README.md is the index, users first. Every reference follows: code comments, Cargo manifests, the workflows, the pre-commit hook, the bench and traceability tools (which locate the repo root by docs/dev/requirements.md now), packaging, the Docker READMEs, CLAUDE.md, CONTRIBUTING.md and the README. The matrix links one level deeper and is regenerated. Links out of the moved documents into the tree gain a level; a link checker over every Markdown file finds none broken.
79 lines
2.7 KiB
Bash
Executable File
79 lines
2.7 KiB
Bash
Executable File
#!/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/dev/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"
|