-
Notifications
You must be signed in to change notification settings - Fork 33
Add enable_android_sdk_checks option for Android emulator testing #215
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 82 commits
d8ce023
b7d0a75
51883a5
427b18b
c082391
1d76ea7
b7e9a5d
1e9bf25
b19a2f9
4312ece
728894a
cb08f99
4d8249c
bad3c64
06d6ff7
3c29f25
988484d
cbf8812
3620be4
97923bd
0c52793
8b7cdf5
b363415
9c38d01
4031eee
560f60a
b09c11b
1ef5eb5
8362509
f0a2e91
c97c292
6932225
88e55ce
dedd2a8
67efdb9
1889eba
5c112a8
8551570
a714374
1c088a2
345a468
c299a2d
8204a10
5b015d8
d0d4b4c
bf04475
b0b4595
b0fc274
6433df2
bbc4a12
4f6703e
707adbd
6cab1f3
e910952
6563fe6
7d58ee6
c705e86
e56b090
25c305b
4a197ee
6841907
4a2a9c7
a86bcba
ca5f01d
1add73b
1ecdca9
ea1eb0a
4411d7e
a0c6393
a5a207b
edb1240
77fd5d6
4f63ef2
fe29bf4
0cc3112
c09530d
2f1c57f
614fb27
5adabf6
4413049
89d7535
c0e37d7
15a740d
5f4d9bf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,140 @@ | ||||||||||
| #!/bin/bash | ||||||||||
| ##===----------------------------------------------------------------------===## | ||||||||||
| ## | ||||||||||
| ## This source file is part of the Swift.org open source project | ||||||||||
| ## | ||||||||||
| ## Copyright (c) 2025 Apple Inc. and the Swift project authors | ||||||||||
| ## Licensed under Apache License v2.0 with Runtime Library Exception | ||||||||||
| ## | ||||||||||
| ## See https://swift.org/LICENSE.txt for license information | ||||||||||
| ## See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors | ||||||||||
| ## | ||||||||||
| ##===----------------------------------------------------------------------===## | ||||||||||
|
|
||||||||||
| set -euo pipefail | ||||||||||
|
|
||||||||||
| log() { printf -- "** %s\n" "$*" >&2; } | ||||||||||
| error() { printf -- "** ERROR: %s\n" "$*" >&2; } | ||||||||||
| fatal() { error "$@"; exit 1; } | ||||||||||
|
|
||||||||||
| ANDROID_PROFILE="Nexus 10" | ||||||||||
| ANDROID_EMULATOR_TIMEOUT=300 | ||||||||||
|
|
||||||||||
| SWIFTPM_HOME="${XDG_CONFIG_HOME}"/swiftpm | ||||||||||
| # e.g., "${SWIFTPM_HOME}"/swift-sdks/swift-DEVELOPMENT-SNAPSHOT-2025-12-11-a_android.artifactbundle/ | ||||||||||
| SWIFT_ANDROID_SDK_HOME=$(find "${SWIFTPM_HOME}"/swift-sdks -maxdepth 1 -name 'swift-*android.artifactbundle' | tail -n 1) | ||||||||||
|
|
||||||||||
| ANDROID_SDK_TRIPLE="x86_64-unknown-linux-android28" | ||||||||||
|
|
||||||||||
| while [[ $# -gt 0 ]]; do | ||||||||||
| case $1 in | ||||||||||
| --android-sdk-triple=*) | ||||||||||
| ANDROID_SDK_TRIPLE="${1#*=}" | ||||||||||
| shift | ||||||||||
| ;; | ||||||||||
| --android-profile=*) | ||||||||||
| ANDROID_PROFILE="${1#*=}" | ||||||||||
| shift | ||||||||||
| ;; | ||||||||||
| --android-emulator-timeout=*) | ||||||||||
| ANDROID_EMULATOR_TIMEOUT="${1#*=}" | ||||||||||
| shift | ||||||||||
| ;; | ||||||||||
| -*) | ||||||||||
| fatal "Unknown option: $1" | ||||||||||
| ;; | ||||||||||
| *) | ||||||||||
| if [[ -z "$SWIFT_VERSION_INPUT" ]]; then | ||||||||||
| SWIFT_VERSION_INPUT="$1" | ||||||||||
| else | ||||||||||
| fatal "Multiple Swift versions specified: $SWIFT_VERSION_INPUT and $1" | ||||||||||
| fi | ||||||||||
| shift | ||||||||||
| ;; | ||||||||||
| esac | ||||||||||
| done | ||||||||||
|
|
||||||||||
| # extract the API level from the end of the triple | ||||||||||
| ANDROID_API="${ANDROID_SDK_TRIPLE/*-unknown-linux-android/}" | ||||||||||
|
|
||||||||||
| # extract the build arch from the beginning of the triple | ||||||||||
| ANDROID_EMULATOR_ARCH="${ANDROID_SDK_TRIPLE/-unknown-linux-android*/}" | ||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If multiple triples are passed in, what does this do, just grab the arch of the first one? If we only support x86_64 right now, may be better to just hard-code this until we support testing on other arches, or it may fail if it attempts those.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It will actually grab the arch of the last one that is passed in (just because of how the parameter is iterated; the last one "wins"). So it happens to work with the default triples that we build against: github-workflows/.github/workflows/swift_package_test.yml Lines 150 to 153 in 20b826e
I had considered just hardwiring "x86_64", but it is possible that aarch64 will work someday once they release a Linux ARM64 emulator (and it currently does work on macOS, which leaves open the possibility of running this on a self-hosted runner). In the (unlikely, methinks) event of someone overriding the build triples to not include x86_64, then this workflow won't currently work at all, since we expect that the package tests will already have been built by install-and-build-with-sdk.sh. If we want to make this less magic, we could add another parameter to android_sdk_checks_emulator_image:
type: string
description: "The emulator system image for testing package with the Swift SDK for Android"
default: "system-images;android-28;default;x86_64" That would allow complete fine-grained control over the exact emulator image that is being used.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Your choice: either add that image setting and add some logic to make sure it matches one of the SDK triples, or simply document in the description that the testing will always be done with the parameters from the last SDK triple specified, so that those who do override the SDK triples won't be surprised by the resulting CI failures. |
||||||||||
|
|
||||||||||
| # x86_64=x86_64, armv7=arm | ||||||||||
| ANDROID_EMULATOR_ARCH_TRIPLE="${ANDROID_EMULATOR_ARCH}" | ||||||||||
|
|
||||||||||
marcprux marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
| EMULATOR_SPEC="system-images;android-${ANDROID_API};default;${ANDROID_EMULATOR_ARCH}" | ||||||||||
|
|
||||||||||
| log "SWIFT_ANDROID_SDK_HOME=${SWIFT_ANDROID_SDK_HOME}" | ||||||||||
|
|
||||||||||
| # install and start an Android emulator | ||||||||||
| log "Listing installed Android SDKs" | ||||||||||
| export PATH="${PATH}:$ANDROID_HOME/emulator:$ANDROID_HOME/tools:$ANDROID_HOME/build-tools/latest:$ANDROID_HOME/platform-tools:$ANDROID_HOME/cmdline-tools/latest/bin" | ||||||||||
| sdkmanager --list_installed | ||||||||||
|
|
||||||||||
| log "Updating Android SDK licenses" | ||||||||||
| yes | sdkmanager --licenses > /dev/null || true | ||||||||||
|
|
||||||||||
| log "Installing Android emulator" | ||||||||||
| sdkmanager --install "emulator" "platform-tools" "platforms;android-${ANDROID_API}" "${EMULATOR_SPEC}" | ||||||||||
|
|
||||||||||
| log "Creating Android emulator" | ||||||||||
| export ANDROID_AVD_HOME=${XDG_CONFIG_HOME:-$HOME}/.android/avd | ||||||||||
| ANDROID_EMULATOR_NAME="swiftemu" | ||||||||||
| avdmanager create avd --force -n "${ANDROID_EMULATOR_NAME}" --package "${EMULATOR_SPEC}" --device "${ANDROID_PROFILE}" | ||||||||||
|
|
||||||||||
| log "Configuring Android emulators" | ||||||||||
| emulator -list-avds | ||||||||||
|
|
||||||||||
| log "Check Hardware Acceleration (KVM)" | ||||||||||
| emulator -accel-check | ||||||||||
|
|
||||||||||
| log "Starting Android emulator" | ||||||||||
| # launch the emulator in the background | ||||||||||
| nohup emulator -no-metrics -partition-size 1024 -memory 4096 -wipe-data -no-window -no-snapshot -noaudio -no-boot-anim -avd "${ANDROID_EMULATOR_NAME}" & | ||||||||||
|
|
||||||||||
| log "Waiting for Android emulator startup" | ||||||||||
| timeout "${ANDROID_EMULATOR_TIMEOUT}" adb wait-for-any-device | ||||||||||
|
|
||||||||||
| log "Prepare Swift test package" | ||||||||||
| # create a staging folder where we copy the test executable | ||||||||||
| # and all the dependent libraries to copy over to the emulator | ||||||||||
| STAGING_DIR="swift-android-test" | ||||||||||
| rm -rf "${STAGING_DIR}" | ||||||||||
| mkdir "${STAGING_DIR}" | ||||||||||
|
|
||||||||||
| BUILD_DIR=.build/"${ANDROID_SDK_TRIPLE}"/debug | ||||||||||
|
|
||||||||||
| find "${BUILD_DIR}" -name '*.xctest' -exec cp -av {} "${STAGING_DIR}" \; | ||||||||||
| find "${BUILD_DIR}" -name '*.resources' -exec cp -av {} "${STAGING_DIR}" \; | ||||||||||
|
|
||||||||||
| # copy over the required library dependencies | ||||||||||
| cp -av "${SWIFT_ANDROID_SDK_HOME}"/swift-android/swift-resources/usr/lib/swift-"${ANDROID_EMULATOR_ARCH_TRIPLE}"/android/*.so "${STAGING_DIR}" | ||||||||||
| cp -av "${SWIFT_ANDROID_SDK_HOME}"/swift-android/ndk-sysroot/usr/lib/"${ANDROID_EMULATOR_ARCH_TRIPLE}"-linux-android/libc++_shared.so "${STAGING_DIR}" | ||||||||||
|
|
||||||||||
| # for the common case of tests referencing | ||||||||||
| # their own files as hardwired paths instead of resources | ||||||||||
| if [[ -d Tests ]]; then | ||||||||||
| cp -a Tests "${STAGING_DIR}" | ||||||||||
| fi | ||||||||||
|
|
||||||||||
| log "Copy Swift test package to emulator" | ||||||||||
|
|
||||||||||
| ANDROID_TMP_FOLDER="/data/local/tmp/${STAGING_DIR}" | ||||||||||
| adb push "${STAGING_DIR}" "${ANDROID_TMP_FOLDER}" | ||||||||||
|
|
||||||||||
| TEST_CMD="./*.xctest" | ||||||||||
| TEST_SHELL="cd ${ANDROID_TMP_FOLDER}" | ||||||||||
| TEST_SHELL="${TEST_SHELL} && ${TEST_CMD} --testing-library xctest" | ||||||||||
|
|
||||||||||
| # Run test cases a second time with the Swift Testing library | ||||||||||
| # We additionally need to handle the special exit code | ||||||||||
| # EXIT_NO_TESTS_FOUND (69 on Android), which can happen | ||||||||||
| # when the tests link to Testing, but no tests are executed | ||||||||||
| # see: https://github.com/swiftlang/swift-package-manager/blob/main/Sources/Commands/SwiftTestCommand.swift#L1571 | ||||||||||
| TEST_SHELL="${TEST_SHELL} && ${TEST_CMD} --testing-library swift-testing && [ \$? -eq 0 ] || [ \$? -eq 69 ]" | ||||||||||
marcprux marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
|
|
||||||||||
| log "Run Swift package tests" | ||||||||||
|
|
||||||||||
| # run the test executable | ||||||||||
| adb shell "${TEST_SHELL}" | ||||||||||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If multiple triples are passed in, what does this do, just grab the API level of the first one?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The last one, actually.