Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
186 changes: 152 additions & 34 deletions scripts/run-ios-ui-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,33 @@ if ! command -v xcrun >/dev/null 2>&1; then
exit 3
fi

HOST_ARCH="$(uname -m)"
ARM64_AVAILABLE=0
if [ "$HOST_ARCH" = "x86_64" ]; then
ARM64_AVAILABLE="$(sysctl -n hw.optional.arm64 2>/dev/null || echo 0)"
fi
declare -a XCODE_ARCH_PREFIX=()
if [ "$HOST_ARCH" = "x86_64" ] && [ "$ARM64_AVAILABLE" = "1" ]; then
ri_log "Detected Rosetta shell; running Xcode tools under arm64"
XCODE_ARCH_PREFIX=(arch -arm64)
fi

xcodebuild_cmd() {
if [ ${#XCODE_ARCH_PREFIX[@]} -gt 0 ]; then
"${XCODE_ARCH_PREFIX[@]}" xcodebuild "$@"
else
xcodebuild "$@"
fi
}

xcrun_cmd() {
if [ ${#XCODE_ARCH_PREFIX[@]} -gt 0 ]; then
"${XCODE_ARCH_PREFIX[@]}" xcrun "$@"
else
xcrun "$@"
fi
}

JAVA17_BIN="$JAVA17_HOME/bin/java"

cn1ss_setup "$JAVA17_BIN" "$CN1SS_HELPER_SOURCE_DIR"
Expand Down Expand Up @@ -168,7 +195,7 @@ normalize_destination() {
auto_select_destination() {
local show_dest rc=0 best_line="" best_key="" line payload platform id name os priority key part value
set +e
show_dest="$(xcodebuild -workspace "$WORKSPACE_PATH" -scheme "$SCHEME" -sdk iphonesimulator -showdestinations 2>/dev/null)"
show_dest="$(xcodebuild_cmd -workspace "$WORKSPACE_PATH" -scheme "$SCHEME" -sdk iphonesimulator -showdestinations 2>/dev/null)"
rc=$?
set -e

Expand Down Expand Up @@ -237,6 +264,34 @@ auto_select_destination() {
return $rc
}

auto_select_destination_retry() {
local attempt=1
local selected=""
while [ "$attempt" -le 3 ]; do
selected="$(auto_select_destination || true)"
if [ -n "$selected" ]; then
printf '%s\n' "$selected"
return 0
fi
ri_log "Auto-select attempt $attempt did not return a destination; retrying" >&2
sleep 5
attempt=$((attempt + 1))
done
return 1
}

destination_visible_to_xcodebuild() {
local destination="$1"
local id=""
id="$(printf '%s\n' "$destination" | sed -n 's/.*id=\([^,]*\).*/\1/p' | tr -d '\r[:space:]')"
[ -z "$id" ] && return 1
set +e
xcodebuild_cmd -workspace "$WORKSPACE_PATH" -scheme "$SCHEME" -sdk iphonesimulator -showdestinations 2>/dev/null | grep -q "$id"
local rc=$?
set -e
return $rc
}

fallback_sim_destination() {
if ! command -v xcrun >/dev/null 2>&1; then
return
Expand Down Expand Up @@ -304,7 +359,7 @@ fallback_sim_destination() {
[ -n "$current_version" ] && best_line="$best_line,OS=$current_version"
best_line="$best_line,name=$name"
fi
done < <(xcrun simctl list devices 2>/dev/null)
done < <(xcrun_cmd simctl list devices 2>/dev/null)

if [ -n "$best_line" ]; then
printf '%s\n' "$best_line"
Expand All @@ -315,7 +370,7 @@ fallback_sim_destination() {

SIM_DESTINATION="${IOS_SIM_DESTINATION:-}"
if [ -z "$SIM_DESTINATION" ]; then
SELECTED_DESTINATION="$(auto_select_destination || true)"
SELECTED_DESTINATION="$(auto_select_destination_retry || true)"
if [ -n "${SELECTED_DESTINATION:-}" ]; then
SIM_DESTINATION="$SELECTED_DESTINATION"
ri_log "Auto-selected simulator destination '$SIM_DESTINATION'"
Expand All @@ -335,17 +390,36 @@ if [ -z "$SIM_DESTINATION" ]; then
fi

SIM_DESTINATION="$(normalize_destination "$SIM_DESTINATION")"
BUILD_DESTINATION="$SIM_DESTINATION"

# Extract UDID and prefer id-only destination to avoid OS/SDK mismatches
# Extract UDID and prefer platform+id destination for xcodebuild stability
SIM_UDID="$(printf '%s\n' "$SIM_DESTINATION" | sed -n 's/.*id=\([^,]*\).*/\1/p' | tr -d '\r[:space:]')"
if [ -n "$SIM_UDID" ]; then
ri_log "Booting simulator $SIM_UDID"
BOOT_START=$(date +%s)
xcrun simctl boot "$SIM_UDID" >/dev/null 2>&1 || true
xcrun simctl bootstatus "$SIM_UDID" -b
xcrun_cmd simctl boot "$SIM_UDID" >/dev/null 2>&1 || true
xcrun_cmd simctl bootstatus "$SIM_UDID" -b
BOOT_END=$(date +%s)
echo "Simulator Boot : $(( (BOOT_END - BOOT_START) * 1000 )) ms" >> "$ARTIFACTS_DIR/ios-test-stats.txt"
SIM_DESTINATION="id=$SIM_UDID"
SIM_DESTINATION="platform=iOS Simulator,id=$SIM_UDID"
BUILD_DESTINATION="$SIM_DESTINATION"
fi
if ! destination_visible_to_xcodebuild "$SIM_DESTINATION"; then
ri_log "Selected simulator destination not visible to xcodebuild; attempting re-selection"
SELECTED_DESTINATION="$(auto_select_destination_retry || true)"
if [ -n "${SELECTED_DESTINATION:-}" ]; then
SIM_DESTINATION="$(normalize_destination "$SELECTED_DESTINATION")"
SIM_UDID="$(printf '%s\n' "$SIM_DESTINATION" | sed -n 's/.*id=\([^,]*\).*/\1/p' | tr -d '\r[:space:]')"
if [ -n "$SIM_UDID" ]; then
SIM_DESTINATION="platform=iOS Simulator,id=$SIM_UDID"
fi
BUILD_DESTINATION="$SIM_DESTINATION"
ri_log "Re-selected simulator destination '$SIM_DESTINATION'"
else
ri_log "Auto-selection still did not return a destination; continuing with '$SIM_DESTINATION'"
BUILD_DESTINATION=""
ri_log "Using default simulator destination for build"
fi
fi
ri_log "Running DeviceRunner on destination '$SIM_DESTINATION'"

Expand All @@ -355,23 +429,67 @@ BUILD_LOG="$ARTIFACTS_DIR/xcodebuild-build.log"

ri_log "Building simulator app with xcodebuild"
COMPILE_START=$(date +%s)
if ! xcodebuild \
-workspace "$WORKSPACE_PATH" \
-scheme "$SCHEME" \
-sdk iphonesimulator \
-configuration Debug \
-destination "$SIM_DESTINATION" \
-destination-timeout 120 \
-derivedDataPath "$DERIVED_DATA_DIR" \
build | tee "$BUILD_LOG"; then
ri_log "STAGE:XCODE_BUILD_FAILED -> See $BUILD_LOG"
exit 10
build_with_destination() {
local dest="$1"
local args=(
-workspace "$WORKSPACE_PATH"
-scheme "$SCHEME"
-sdk iphonesimulator
-configuration Debug
-derivedDataPath "$DERIVED_DATA_DIR"
build
)
if [ -n "$dest" ]; then
args=(
-workspace "$WORKSPACE_PATH"
-scheme "$SCHEME"
-sdk iphonesimulator
-configuration Debug
-destination "$dest"
-destination-timeout 120
-derivedDataPath "$DERIVED_DATA_DIR"
build
)
fi
xcodebuild_cmd "${args[@]}" | tee "$BUILD_LOG"
}

if ! build_with_destination "$BUILD_DESTINATION"; then
if grep -q "Unable to find a destination matching the provided destination specifier" "$BUILD_LOG"; then
ri_log "xcodebuild could not find destination; retrying after re-selection"
SELECTED_DESTINATION="$(auto_select_destination_retry || true)"
if [ -n "${SELECTED_DESTINATION:-}" ]; then
SIM_DESTINATION="$(normalize_destination "$SELECTED_DESTINATION")"
SIM_UDID="$(printf '%s\n' "$SIM_DESTINATION" | sed -n 's/.*id=\([^,]*\).*/\1/p' | tr -d '\r[:space:]')"
if [ -n "$SIM_UDID" ]; then
SIM_DESTINATION="platform=iOS Simulator,id=$SIM_UDID"
fi
BUILD_DESTINATION="$SIM_DESTINATION"
ri_log "Retrying xcodebuild with destination '$BUILD_DESTINATION'"
if ! build_with_destination "$BUILD_DESTINATION"; then
ri_log "Retrying xcodebuild with default simulator destination"
if ! build_with_destination ""; then
ri_log "STAGE:XCODE_BUILD_FAILED -> See $BUILD_LOG"
exit 10
fi
fi
else
ri_log "Retrying xcodebuild with default simulator destination"
if ! build_with_destination ""; then
ri_log "STAGE:XCODE_BUILD_FAILED -> See $BUILD_LOG"
exit 10
fi
fi
else
ri_log "STAGE:XCODE_BUILD_FAILED -> See $BUILD_LOG"
exit 10
fi
fi
COMPILE_END=$(date +%s)
COMPILATION_TIME=$((COMPILE_END - COMPILE_START))
ri_log "Compilation time: ${COMPILATION_TIME}s"

BUILD_SETTINGS="$(xcodebuild -workspace "$WORKSPACE_PATH" -scheme "$SCHEME" -sdk iphonesimulator -configuration Debug -showBuildSettings 2>/dev/null || true)"
BUILD_SETTINGS="$(xcodebuild_cmd -workspace "$WORKSPACE_PATH" -scheme "$SCHEME" -sdk iphonesimulator -configuration Debug -showBuildSettings 2>/dev/null || true)"
TARGET_BUILD_DIR="$(printf '%s\n' "$BUILD_SETTINGS" | awk -F' = ' '/ TARGET_BUILD_DIR /{print $2; exit}')"
WRAPPER_NAME="$(printf '%s\n' "$BUILD_SETTINGS" | awk -F' = ' '/ WRAPPER_NAME /{print $2; exit}')"
if [ -z "$WRAPPER_NAME" ]; then
Expand Down Expand Up @@ -436,21 +554,21 @@ APP_PROCESS_NAME="${WRAPPER_NAME%.app}"
resolved_id="$(trim_whitespace "$id_part")"
break
fi
done < <(xcrun simctl list devices 2>/dev/null)
done < <(xcrun_cmd simctl list devices 2>/dev/null)
SIM_DEVICE_ID="$resolved_id"
fi
fi

if [ -n "$SIM_DEVICE_ID" ]; then
ri_log "Booting simulator $SIM_DEVICE_ID"
BOOT_START=$(date +%s)
xcrun simctl boot "$SIM_DEVICE_ID" >/dev/null 2>&1 || true
xcrun simctl bootstatus "$SIM_DEVICE_ID" -b
xcrun_cmd simctl boot "$SIM_DEVICE_ID" >/dev/null 2>&1 || true
xcrun_cmd simctl bootstatus "$SIM_DEVICE_ID" -b
BOOT_END=$(date +%s)
echo "Simulator Boot (Run) : $(( (BOOT_END - BOOT_START) * 1000 )) ms" >> "$ARTIFACTS_DIR/ios-test-stats.txt"
else
ri_log "Warning: simulator UDID not resolved; relying on default booted device"
xcrun simctl bootstatus booted -b || true
xcrun_cmd simctl bootstatus booted -b || true
fi

LOG_STREAM_PID=0
Expand All @@ -460,22 +578,22 @@ APP_PROCESS_NAME="${WRAPPER_NAME%.app}"
wait "$LOG_STREAM_PID" 2>/dev/null || true
fi
if [ -n "$SIM_DEVICE_ID" ] && [ -n "$BUNDLE_IDENTIFIER" ]; then
xcrun simctl terminate "$SIM_DEVICE_ID" "$BUNDLE_IDENTIFIER" >/dev/null 2>&1 || true
xcrun_cmd simctl terminate "$SIM_DEVICE_ID" "$BUNDLE_IDENTIFIER" >/dev/null 2>&1 || true
fi
}
trap cleanup EXIT

ri_log "Streaming simulator logs to $TEST_LOG"
if [ -n "$SIM_DEVICE_ID" ]; then
xcrun simctl terminate "$SIM_DEVICE_ID" "$BUNDLE_IDENTIFIER" >/dev/null 2>&1 || true
xcrun simctl uninstall "$SIM_DEVICE_ID" "$BUNDLE_IDENTIFIER" >/dev/null 2>&1 || true
xcrun_cmd simctl terminate "$SIM_DEVICE_ID" "$BUNDLE_IDENTIFIER" >/dev/null 2>&1 || true
xcrun_cmd simctl uninstall "$SIM_DEVICE_ID" "$BUNDLE_IDENTIFIER" >/dev/null 2>&1 || true

xcrun simctl spawn "$SIM_DEVICE_ID" \
xcrun_cmd simctl spawn "$SIM_DEVICE_ID" \
log stream --style json --level debug \
--predicate 'eventMessage CONTAINS "CN1SS"' \
> "$TEST_LOG" 2>&1 &
else
xcrun simctl spawn booted log stream --style compact --level debug --predicate 'composedMessage CONTAINS "CN1SS"' > "$TEST_LOG" 2>&1 &
xcrun_cmd simctl spawn booted log stream --style compact --level debug --predicate 'composedMessage CONTAINS "CN1SS"' > "$TEST_LOG" 2>&1 &
fi
LOG_STREAM_PID=$!
sleep 2
Expand All @@ -487,7 +605,7 @@ APP_PROCESS_NAME="${WRAPPER_NAME%.app}"
local attempt=1
while true; do
local output
if output="$(xcrun simctl launch "$target" "$BUNDLE_IDENTIFIER" 2>&1)"; then
if output="$(xcrun_cmd simctl launch "$target" "$BUNDLE_IDENTIFIER" 2>&1)"; then
printf '%s\n' "$output" >> "$LAUNCH_LOG"
return 0
fi
Expand All @@ -496,7 +614,7 @@ APP_PROCESS_NAME="${WRAPPER_NAME%.app}"
return 1
fi
ri_log "simctl launch failed (attempt $attempt), retrying"
xcrun simctl bootstatus "$target" -b >/dev/null 2>&1 || true
xcrun_cmd simctl bootstatus "$target" -b >/dev/null 2>&1 || true
sleep 5
attempt=$((attempt + 1))
done
Expand All @@ -505,7 +623,7 @@ APP_PROCESS_NAME="${WRAPPER_NAME%.app}"
ri_log "Installing simulator app bundle"
INSTALL_START=$(date +%s)
if [ -n "$SIM_DEVICE_ID" ]; then
if ! xcrun simctl install "$SIM_DEVICE_ID" "$APP_BUNDLE_PATH"; then
if ! xcrun_cmd simctl install "$SIM_DEVICE_ID" "$APP_BUNDLE_PATH"; then
ri_log "FATAL: simctl install failed"
exit 11
fi
Expand All @@ -518,7 +636,7 @@ APP_PROCESS_NAME="${WRAPPER_NAME%.app}"
fi
LAUNCH_END=$(date +%s)
else
if ! xcrun simctl install booted "$APP_BUNDLE_PATH"; then
if ! xcrun_cmd simctl install booted "$APP_BUNDLE_PATH"; then
ri_log "FATAL: simctl install failed"
exit 11
fi
Expand Down Expand Up @@ -560,13 +678,13 @@ wait "$LOG_STREAM_PID" 2>/dev/null || true
LOG_STREAM_PID=0

FALLBACK_LOG="$ARTIFACTS_DIR/device-runner-fallback.log"
xcrun simctl spawn "$SIM_DEVICE_ID" \
xcrun_cmd simctl spawn "$SIM_DEVICE_ID" \
log show --style syslog --last 30m \
--predicate 'eventMessage CONTAINS "CN1SS"' \
> "$FALLBACK_LOG" 2>/dev/null || true

if [ -n "$SIM_DEVICE_ID" ]; then
xcrun simctl terminate "$SIM_DEVICE_ID" "$BUNDLE_IDENTIFIER" >/dev/null 2>&1 || true
xcrun_cmd simctl terminate "$SIM_DEVICE_ID" "$BUNDLE_IDENTIFIER" >/dev/null 2>&1 || true
fi

declare -a CN1SS_SOURCES=("SIMLOG:$TEST_LOG")
Expand Down
Loading