Files
simplex-chat/apps/multiplatform/scripts/uitest.sh
T
Narasimha-sc 69b3cc4f0e ui tests: about 300 more tests across all areas, server control, relays, remote desktop, CI workflow
- Tests for connection plans, prepared chats, edit/delete/selection, forwarding, drafts, group preferences and admission, group lifecycle, compose, live messages, item info, reports and moderation, privacy and SimpleX Lock, chat data and database, address and contact preferences, profiles, contact info, unread and search, files and reactions, group info and events, chat shell and statuses, joining, support and business chats, settings and appearance, network and servers, channels, remote desktop, Android intents and notifications.
- Harness: server stop/start, smp2/xftp2, SOCKS stub, CLI chat relays, CLI remote host/controller, chat scroll and drag helpers, file chooser answers, clipboard in popups.
- ui-tests workflow (manual dispatch only) running both suites on GitHub runners.
- App findings recorded in plan section 15.5 (items 7-23), each covered by a test marked @KnownAppIssue.
2026-10-22 19:45:11 +00:00

111 lines
5.2 KiB
Bash
Executable File

#!/bin/sh
# Usage: scripts/uitest.sh [gradle args] e.g. --tests '*ChatListMenuTest', -PuiForks=2, -PuiForkEvery=N
# scripts/uitest.sh --prepare-only only the CLI, test servers, peer template and build/uitest/env.properties (for uitest-android.sh)
# Env: UITEST_CLI and UITEST_SERVERS, absolute paths of a prebuilt CLI and uitest-servers (cabal -f uitest), skip the cabal build.
# Runs the desktop UI tests (common/src/uiTestShared + desktopTest/.../ui) in a private network namespace with local servers.
# Needs cabal/GHC for the CLI peers and test servers, and the desktop native libs (./gradlew :desktop:cmakeBuildAndCopy).
# Results: common/build/reports/tests/desktopUiTest/pass1; run directories (failure screenshots) in build/uitest/run-*.
set -eu
self=$(readlink -f "$0")
cd "$(dirname "$self")/.."
home="$PWD/.gradle/uitest-home"
kotlin_in_process="-Pkotlin.compiler.execution.strategy=in-process"
if [ "${1:-}" = "--inside" ]; then
shift
run="$1"; shift
[ "$$" -eq 1 ] || { echo "uitest: --inside runs only as PID 1 of the runner's PID namespace" >&2; exit 1; }
trap 'kill -TERM -1 2>/dev/null; exit 143' TERM
SIMPLEX_UITEST_RUNNER=1 ./gradlew -g "$home" --offline --no-daemon "$kotlin_in_process" :common:desktopUiTest -PuiRunDir="$run" -PuiPass=1 "$@"
exit $?
fi
prepare_only=
if [ "${1:-}" = "--prepare-only" ]; then
shift
[ "$#" -eq 0 ] || { echo "uitest: --prepare-only takes no other arguments" >&2; exit 1; }
prepare_only=1
fi
avail_mb=$(awk '/^MemAvailable:/ {print int($2 / 1024)}' /proc/meminfo)
[ "$avail_mb" -ge 3000 ] || { echo "uitest: only $avail_mb MB available, need 3000; free memory first" >&2; exit 1; }
mkdir -p build/uitest
exec 9>build/uitest/runner.lock
flock -n 9 || { echo "another uitest run holds build/uitest/runner.lock" >&2; exit 1; }
run="$PWD/build/uitest/run-$(date +%Y%m%d-%H%M%S)"
mkdir -p "$run/jvmtmp" "$run/cache"
ls -1dt build/uitest/run-* 2>/dev/null | tail -n +7 | xargs -r rm -rf
repo=$(cd ../.. && pwd)
if [ -n "${UITEST_CLI:-}${UITEST_SERVERS:-}" ]; then
for exe in "${UITEST_CLI:-}" "${UITEST_SERVERS:-}"; do
case "$exe" in /*) [ -x "$exe" ] ;; *) false ;; esac || { echo "uitest: UITEST_CLI and UITEST_SERVERS must both be absolute paths of executables" >&2; exit 1; }
done
cli=$UITEST_CLI
servers=$UITEST_SERVERS
else
(cd "$repo" && cabal build -O0 -f uitest --builddir=dist-uitest exe:simplex-chat exe:uitest-servers | tail -n 1)
cli=$(cd "$repo" && cabal list-bin -O0 -f uitest --builddir=dist-uitest exe:simplex-chat | tail -n 1)
servers=$(cd "$repo" && cabal list-bin -O0 -f uitest --builddir=dist-uitest exe:uitest-servers | tail -n 1)
fi
peer_template() {
t="$run/peer-template.tmp"
mkdir -p "$t/tmp"
(cd "$repo" && HOME="$t" TMPDIR="$t/tmp" "$cli" -d "$t/simplex_v1" --maintenance -e /v -t 0 >"$t/out.txt" 2>&1) || true
if [ -f "$t/simplex_v1_chat.db" ] && grep -q "no active user in maintenance mode" "$t/out.txt"; then
rm -rf "$t/tmp" "$t/out.txt" && mv "$t" "$run/peer-template"
else
echo "peer template not created; peers create their databases on first start" >&2
fi
}
peer_template &
template_pid=$!
lib=common/src/commonMain/cpp/desktop/libs/linux-x86_64/libapp-lib.so
cat > build/uitest/env.properties <<ENV
libAppLib=$PWD/$lib
runDir=$run
repoRoot=$repo
cli=$cli
servers=$servers
ENV
if [ -n "$prepare_only" ]; then
wait "$template_pid"
echo "uitest: prepared $run and build/uitest/env.properties"
exit 0
fi
[ -d common/src/commonMain/cpp/desktop/libs/linux-x86_64 ] || { echo "uitest: native libs missing in common/src/commonMain/cpp/desktop/libs/linux-x86_64; build the desktop app once (./gradlew :desktop:cmakeBuildAndCopy)" >&2; exit 1; }
prepare_key=$({
find . -path ./build -prune -o -path ./.gradle -prune -o -path '*/build' -prune -o \( -name '*.gradle.kts' -o -name gradle.properties -o -name '*.versions.toml' \) -type f -print
find common/src/commonMain/cpp -path '*/libs' -prune -o -type f -print
} | LC_ALL=C sort | xargs sha256sum | sha256sum; ls -l --time-style=full-iso common/src/commonMain/cpp/desktop/libs/linux-x86_64 | grep -v libapp-lib.so)
prepare_key=$(printf '%s' "$prepare_key" | sha256sum | cut -d' ' -f1)
if [ "$prepare_key" = "$(cat build/uitest/prepare.key 2>/dev/null)" ] && [ -f "$lib" ]; then
echo "uitest: build files and native libs unchanged, skipping the outside Gradle step"
else
rm -f build/uitest/prepare.key
./gradlew -g "$home" --no-daemon "$kotlin_in_process" :desktop:cmakeBuildAndCopy :common:desktopTestClasses :common:uitestPrepare
./gradlew -g "$home" --stop >/dev/null 2>&1 || true
echo "$prepare_key" > build/uitest/prepare.key
fi
wait "$template_pid"
case " $* " in
*" -PuiForks="*) ;;
*)
forks=$(( (avail_mb - 2500) / 1000 ))
[ "$forks" -ge 1 ] || forks=1
[ "$forks" -le 4 ] || forks=4
echo "uitest: $avail_mb MB available, running $forks test JVMs in parallel (override with -PuiForks=N)"
set -- "$@" -PuiForks=$forks ;;
esac
inside_pid=
trap '[ -z "$inside_pid" ] || kill -KILL "$inside_pid"' INT TERM
unshare -rn --pid --fork --kill-child --mount-proc sh -c '
ip link set lo up && ip link set lo multicast on && ip route add 224.0.0.0/4 dev lo src 127.0.0.1 &&
exec "$0" --inside "$@"' "$self" "$run" "$@" &
inside_pid=$!
wait "$inside_pid"