diff --git a/.github/workflows/lints.yml b/.github/workflows/lints.yml index eec548fe..9defa932 100644 --- a/.github/workflows/lints.yml +++ b/.github/workflows/lints.yml @@ -18,7 +18,7 @@ jobs: steps: - uses: actions/checkout@v3 - run: pip3 install flake8 mypy - - run: shellcheck **/*.sh + - run: shellcheck **/*.sh bin/verify_duplicate_crates bin/adb-run-test - run: python3 -m flake8 . # Only include typed Python scripts here. - run: python3 -m mypy bin/fetch_archive.py --python-version 3.8 --strict diff --git a/TESTING.md b/TESTING.md new file mode 100644 index 00000000..bd1c90bd --- /dev/null +++ b/TESTING.md @@ -0,0 +1,63 @@ +For the most part, libsignal is tested using each language's usual testing infrastructure, as described in the main [README.md](./README.md): + +```shell +# Rust +% cargo test --workspace --all-features + +# Java / Android +% ./gradlew client:test server:test android:connectedAndroidTest + +# Node +% yarn build && yarn tsc && yarn test + +# Swift +% ./build_ffi.sh --generate-ffi && swift test +``` + +However, sometimes there are some more interesting test configurations; those are documented here. + + +# Running cross-compiling Rust tests with custom runners + +Rust allows running tests with cross-compiled targets, but normally that only works if your system supports executing the cross-compiled binary (like Intel targets on ARM64 macOS or Windows, or 32-bit targets on 64-bit Linux or Windows). However, by overriding the "runner" setting for a particular target, we can run cross-compiled tests as well. + +## Running Rust tests on Android Devices (including the emulator) + +1. Connect your device, or start an emulator and let it finish booting. + +2. Make sure `adb` is in your path, or set `ADB` to the path to `adb` (it's usually in `$ANDROID_SDK_ROOT/platform-tools/adb`). + +3. Set the following environment variables, filling in `path/to/ndk` and `YOUR_HOST_HERE`: + + ```shell + ANDROID_NDK_HOME=path/to/ndk + CARGO_PROFILE_TEST_STRIP=debuginfo # make the "push" step take less time + CARGO_PROFILE_BENCH_STRIP=debuginfo # same for benchmarks + CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER=path/to/ndk/toolchains/llvm/prebuilt/YOUR_HOST_HERE/bin/ aarch64-linux-android21-clang + CARGO_TARGET_AARCH64_LINUX_ANDROID_RUNNER=bin/adb-run-test # in the repo root + ``` + + (If working with a different target architecture, don't forget to change the environment variables above. You may need to set additional environment variables depending on what you're building; see [`build_jni.sh`][java/build_jni.sh] for the full set that libsignal-jni uses.) + +4. Finally, run `cargo test --target aarch64-linux-android -p PACKAGE`. + +When running against an actual device, the "push" step in [`adb-run-test`][bin/adb-run-test] can be a bit flaky. Turning on the developer option "Stay awake" in the system settings seems to help. + +You may need to push additional resources if the test expects to find them relative to the working directory, which you can `adb push` as well. (If you're writing the test, prefer `include_bytes!` instead to avoid this.) + + +## Running Rust tests in the iOS Simulator + +1. Start a simulator and let it finish booting. + +2. Set the following environment variable: + + ```shell + CARGO_TARGET_AARCH64_APPLE_IOS_SIM_RUNNER='xcrun simctl spawn booted' + ``` + + (if working on an Intel Mac, don't forget to change the environment variables above to match the Intel simulator target) + +3. Finally, run `cargo test --target aarch64-apple-ios-sim -p PACKAGE`. + +If the test has resources found relatively, you’ll have to hack them in by loading them into the simulator’s root, which is located at `~/Developer/CoreSimulator/Devices/YOUR_SIMULATOR_UUID/data`. (If you're writing the test, prefer `include_bytes!` instead to avoid this.) diff --git a/bin/adb-run-test b/bin/adb-run-test new file mode 100755 index 00000000..4e005997 --- /dev/null +++ b/bin/adb-run-test @@ -0,0 +1,20 @@ +#!/bin/sh + +# +# Copyright 2023 Signal Messenger, LLC. +# SPDX-License-Identifier: AGPL-3.0-only +# + +set -e + +ADB=${ADB:-adb} + +executable="$1" +shift +basename=$(basename "$executable") + +# We have to use /data/local/tmp on modern Android systems; +# other locations don't allow executables or don't allow non-root adb access by default. + +"$ADB" push -z any "$executable" "/data/local/tmp/$basename" +"$ADB" shell "cd /data/local/tmp/ && chmod 744 $basename && ./$basename" "$@"