#!/data/data/com.termux/files/usr/bin/bash # Runs the headless GDScript gameplay tests from Termux, via the Godot # 4.7.1 Linux arm64 build installed inside the proot-distro Ubuntu container. # # bash tests/run_tests.sh # everything # bash tests/run_tests.sh formation # only tests matching a substring # JOBS=1 bash tests/run_tests.sh # serial, for debugging a hang # VERBOSE=1 bash tests/run_tests.sh # print passing tests' output too # IN_PLACE=1 bash tests/run_tests.sh # run from the project dir itself # # Three things make this fast, in descending order of how much they matter # (measured, not guessed - see tests/_profile_startup.gd): # # 1. It runs from a COPY on Termux's own filesystem, not from the project # directory. The project lives under ~/storage/shared, which is Android's # FUSE bridge; read through proot on top of that, `load("res://Main.tscn")` # alone took 8.5s per test, against ~2s from a native path. Nearly every # test loads Main.tscn, and none of that time is gameplay. The copy is # ~1.4s for the whole suite and its .godot import cache is kept between # runs. # 2. Tests run JOBS at a time. Each is its own Godot process - they call # quit() and stamp on the GameState autoload, so they cannot share one - # which makes the suite a pile of independent, single-core-bound jobs on # an 8-core phone. # 3. The whole run happens in ONE `proot-distro login`. Entering the # container costs ~0.5s, which used to be paid once per test. # # Output is buffered per test and printed only for failures; six interleaved # logs are unreadable. set -uo pipefail PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" # Leave headroom: Godot is memory-hungry and this is a phone, not a build # server. Override with JOBS= if you know better. JOBS="${JOBS:-6}" VERBOSE="${VERBOSE:-0}" IN_PLACE="${IN_PLACE:-0}" WORK_DIR="${WORK_DIR:-$HOME/.cache/spaceship-tests}" filter="${1:-}" tests=() for path in "$PROJECT_DIR"/tests/test_*.gd; do name="$(basename "$path")" if [[ -z "$filter" || "$name" == *"$filter"* ]]; then tests+=("$name") fi done if (( ${#tests[@]} == 0 )); then echo "no tests match '$filter'" exit 2 fi start=$(date +%s) run_dir="$PROJECT_DIR" if [[ "$IN_PLACE" != "1" ]]; then run_dir="$WORK_DIR" mkdir -p "$run_dir" # Clear last run's sources but keep .godot, so imports stay warm. Without # the clear, a test deleted from the project would live on in the copy and # keep being run. find "$run_dir" -mindepth 1 -maxdepth 1 ! -name '.godot' -exec rm -rf {} + # android/ and builds/ are export artefacts no test touches, and the .apk # is 30MB of nothing useful here. tar -C "$PROJECT_DIR" \ --exclude=./.godot --exclude=./android --exclude=./builds --exclude='*.apk' \ -cf - . 2>/dev/null | tar -C "$run_dir" -xf - fi proot-distro login ubuntu -- bash "$run_dir/tests/_run_inside.sh" \ "$run_dir" "$JOBS" "$VERBOSE" "${tests[@]}" status=$? echo "in $(( $(date +%s) - start ))s with JOBS=$JOBS" exit $status