Android CI with Unit Testing (#295)

* Add android CI scripts

* Android Test Driver: Busybox compatibility
main
Hugo Melder 2 years ago committed by GitHub
parent 2855d17714
commit b35505ff59
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,61 @@
#!/bin/sh
# This script is run on the emulator to run the tests
# Get list of all binaries in pwd for later iteration (only include binaries)
BINARIES=$(find . -maxdepth 1 -type f ! -name "*.so" ! -name "android_test_driver.sh")
TOTAL=0
PASS=0
SKIP=0
FAIL=0
# Run each binary, measure time and return value (PASS or FAIL). Print stdout and stderr only after a failure
for BINARY in $BINARIES; do
TOTAL=$((TOTAL + 1))
START_TIME=$(date +%s)
START_TIME_MS=$((START_TIME * 1000 + $(date +%N) / 1000000))
OUTPUT=$("$BINARY" 2>&1)
EXIT_CODE=$?
END_TIME=$(date +%s)
END_TIME_MS=$((END_TIME * 1000 + $(date +%N) / 1000000))
ELAPSED_TIME=$((END_TIME_MS - START_TIME_MS))
BINARY_NAME=$(basename "$BINARY")
if [ $EXIT_CODE -eq 0 ]; then
PASS=$((PASS + 1))
echo "PASSED ($EXIT_CODE): $BINARY_NAME (${ELAPSED_TIME}ms)"
elif [ $EXIT_CODE -eq 77 ]; then
SKIP=$((SKIP + 1))
echo "SKIPPED: $BINARY_NAME"
else
FAIL=$((FAIL + 1))
echo "FAILED ($EXIT_CODE): $BINARY_NAME (${ELAPSED_TIME}ms)"
if [ -z "$OUTPUT" ]; then
echo "No output written to stdout."
else
echo "Output:"
echo "$OUTPUT"
fi
fi
done
if [ $TOTAL -eq 0 ]; then
echo "No tests found. Exiting."
exit 1
fi
PERCENTAGE=$(((PASS + SKIP) * 100 / TOTAL))
echo "$PERCENTAGE% Passed. Total: $TOTAL, Passed: $PASS, Skipped: $SKIP, Failed: $FAIL"
echo "Finished running tests. Exiting."
# Exit with corresponding return value
if [ $FAIL -eq 0 ]; then
exit 0
else
exit 1
fi

@ -0,0 +1,63 @@
#!/bin/sh
main () {
# first argument is the build directory
local BUILD_DIR=$1
# second argument is the android ndk sysroot
local ANDROID_NDK_SYSROOT=$2
# third argument is the target triple
# e.g. arm-linux-androideabi, aarch64-linux-android, x86_64-linux-android
local TARGET_TRIPLE=$3
if [ ! -d "$BUILD_DIR" ]
then
echo "Build directory argument not found"
exit 1
fi
if [ ! -d "$ANDROID_NDK_SYSROOT" ]
then
echo "Android NDK sysroot argument not found"
exit 1
fi
if [ -z "$TARGET_TRIPLE" ]
then
echo "Target triple argument not found"
exit 1
fi
# We need to run the emulator with root permissions
# This is needed to run the tests
adb root
local TEMP_DIR=$(mktemp -d)
# Copy libobjc.so and test binaries to temporary directory
cp $BUILD_DIR/libobjc.so* $TEMP_DIR
cp $BUILD_DIR/Test/* $TEMP_DIR
for file in $TEMP_DIR/*; do
# Check if file is a binary
if ! file $file | grep -q "ELF"
then
rm $file
continue
fi
# Set runtime path to ORIGIN
patchelf --set-rpath '$ORIGIN' $file
done
# Copy libc++_shared.so (required by libobjc2)
cp $ANDROID_NDK_SYSROOT/usr/lib/$TARGET_TRIPLE/libc++_shared.so $TEMP_DIR
adb shell rm -rf /data/local/tmp/libobjc2_tests
adb push $TEMP_DIR /data/local/tmp/libobjc2_tests
# Copy android_test_driver.sh to device
adb push $BUILD_DIR/../.github/scripts/android_test_driver.sh /data/local/tmp/libobjc2_tests
# Run the tests
adb shell "cd /data/local/tmp/libobjc2_tests && sh android_test_driver.sh"
}
main "$@"

@ -259,6 +259,79 @@ jobs:
name: ${{ matrix.msystem }}-${{ matrix.build-type }} name: ${{ matrix.msystem }}-${{ matrix.build-type }}
path: dist/ path: dist/
android:
strategy:
matrix:
# Build each combination of OS and release/debug variants
os: [ ubuntu-20.04 ]
build-type: [ Release, Debug ]
arch:
- name: x86_64
triple: x86_64-linux-android
api-level: [ 26 ]
# Don't abort runners if a single one fails
fail-fast: false
runs-on: ${{ matrix.os }}
name: Android ${{ matrix.build-type }} ${{ matrix.arch.name }} API-${{ matrix.api-level }}
steps:
- uses: actions/checkout@v4
- name: Install Dependencies
run: |
sudo apt-get update -y
sudo apt-get install patchelf ninja-build -y
- uses: nttld/setup-ndk@v1
id: setup-ndk
with:
ndk-version: r26d
- name: Configure CMake
env:
ANDROID_NDK_HOME: ${{ steps.setup-ndk.outputs.ndk-path }}
run: |
export TOOLCHAIN=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64
export CCPREFIX=$TOOLCHAIN/bin/${{ matrix.arch.triple }}${{ matrix.api-level }}
export CC="$CCPREFIX-clang"
export CXX="$CCPREFIX-clang++"
export OBJC="$CCPREFIX-clang"
export OBJCXX="$CCPREFIX-clang++"
export AS="$CCPREFIX-clang"
export LD="$TOOLCHAIN/bin/ld.lld"
export AR="$TOOLCHAIN/bin/llvm-ar"
export RANLIB="$TOOLCHAIN/bin/llvm-ranlib"
export STRIP="$TOOLCHAIN/bin/llvm-strip"
export NM="$TOOLCHAIN/bin/llvm-nm"
export OBJDUMP="$TOOLCHAIN/bin/llvm-objdump"
export LDFLAGS="-fuse-ld=lld"
export LIBS="-lc++_shared"
cmake -B ${{github.workspace}}/build \
-DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK_HOME/build/cmake/android.toolchain.cmake \
-DANDROID_ABI=${{ matrix.arch.name }} \
-DANDROID_NDK=$ANDROID_NDK_HOME \
-DANDROID_STL=c++_shared \
-DCMAKE_FIND_USE_CMAKE_PATH=false \
-DCMAKE_C_COMPILER=$CC \
-DCMAKE_CXX_COMPILER=$CXX \
-DCMAKE_ASM_COMPILER=$AS \
-DCMAKE_BUILD_TYPE=${{matrix.build-type}} \
-DTESTS=ON \
-DANDROID_PLATFORM=android-${{ matrix.api-level }} \
-G Ninja
- name: Build
working-directory: ${{github.workspace}}/build
run: |
NINJA_STATUS="%p [%f:%s/%t] %o/s, %es" ninja -v
- name: Test
uses: reactivecircus/android-emulator-runner@v2
env:
ANDROID_NDK_HOME: ${{ steps.setup-ndk.outputs.ndk-path }}
with:
api-level: ${{ matrix.api-level }}
target: default
arch: ${{ matrix.arch.name }}
script: |
${{github.workspace}}/.github/scripts/android_test_main.sh ${{github.workspace}}/build ${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/sysroot ${{ matrix.arch.triple }}
# Fake check that can be used as a branch-protection rule. # Fake check that can be used as a branch-protection rule.
all-checks: all-checks:
needs: [ubuntu, windows, qemu-crossbuild] needs: [ubuntu, windows, qemu-crossbuild]

Loading…
Cancel
Save