Skip to content

Commit b14f558

Browse files
committed
No idea
1 parent eb41b8c commit b14f558

File tree

1 file changed

+85
-69
lines changed

1 file changed

+85
-69
lines changed

scripts/run-ios-ui-tests.sh

Lines changed: 85 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,48 @@ set -euo pipefail
44

55
ri_log() { echo "[run-ios-ui-tests] $1"; }
66

7+
# --- begin: global cleanup/watchdog helpers ---
8+
VIDEO_PID=""
9+
SYSLOG_PID=""
10+
SIM_UDID_CREATED=""
11+
12+
cleanup() {
13+
# Stop recorders
14+
[ -n "$VIDEO_PID" ] && kill "$VIDEO_PID" >/dev/null 2>&1 || true
15+
[ -n "$SYSLOG_PID" ] && kill "$SYSLOG_PID" >/dev/null 2>&1 || true
16+
# Shutdown and delete the temp simulator we created (if any)
17+
if [ -n "$SIM_UDID_CREATED" ]; then
18+
xcrun simctl shutdown "$SIM_UDID_CREATED" >/dev/null 2>&1 || true
19+
xcrun simctl delete "$SIM_UDID_CREATED" >/dev/null 2>&1 || true
20+
fi
21+
}
22+
trap cleanup EXIT
23+
24+
run_with_timeout() {
25+
# run_with_timeout <seconds> <cmd...>
26+
local t="$1"; shift
27+
local log="${ARTIFACTS_DIR:-.}/xcodebuild-live.log"
28+
( "$@" 2>&1 | tee -a "$log" ) & # background xcodebuild
29+
local child=$!
30+
local waited=0
31+
while kill -0 "$child" >/dev/null 2>&1; do
32+
sleep 5
33+
waited=$((waited+5))
34+
# heartbeat so CI doesn’t think we're idle
35+
if (( waited % 60 == 0 )); then echo "[run-ios-ui-tests] heartbeat: ${waited}s"; fi
36+
if (( waited >= t )); then
37+
echo "[run-ios-ui-tests] WATCHDOG: Killing long-running process (>${t}s)"
38+
kill -TERM "$child" >/dev/null 2>&1 || true
39+
sleep 2
40+
kill -KILL "$child" >/dev/null 2>&1 || true
41+
wait "$child" || true
42+
return 124
43+
fi
44+
done
45+
wait "$child"
46+
}
47+
# --- end: global cleanup/watchdog helpers ---
48+
749
ensure_dir() { mkdir -p "$1" 2>/dev/null || true; }
850

951
if [ $# -lt 1 ]; then
@@ -123,72 +165,30 @@ SDKROOT_OS="${SDKROOT#iphonesimulator}"
123165
DESIRED_OS_MAJOR="${SDKROOT_OS%%.*}"
124166
DESIRED_OS_MINOR="${SDKROOT_OS#*.}"; [ "$DESIRED_OS_MINOR" = "$SDKROOT_OS" ] && DESIRED_OS_MINOR=""
125167

126-
auto_select_destination() {
127-
# 1) Try xcodebuild -showdestinations, but skip placeholder ids
128-
if command -v xcodebuild >/dev/null 2>&1; then
129-
sel="$(
130-
xcodebuild -workspace "$WORKSPACE_PATH" -scheme "$SCHEME" -showdestinations 2>/dev/null |
131-
awk -v wantMajor="${DESIRED_OS_MAJOR:-}" -v wantMinor="${DESIRED_OS_MINOR:-}" '
132-
function is_uuid(s) { return match(s, /^[0-9A-Fa-f-]{8}-[0-9A-Fa-f-]{4}-[0-9A-Fa-f-]{4}-[0-9A-Fa-f-]{4}-[0-9A-Fa-f-]{12}$/) }
133-
/platform:iOS Simulator/ && /name:/ && /id:/ {
134-
os=""; name=""; id="";
135-
for (i=1;i<=NF;i++) {
136-
if ($i ~ /^OS:/) { sub(/^OS:/,"",$i); os=$i }
137-
if ($i ~ /^name:/) { sub(/^name:/,"",$i); name=$i }
138-
if ($i ~ /^id:/) { sub(/^id:/,"",$i); id=$i }
139-
}
140-
if (!is_uuid(id)) next; # skip placeholders
141-
gsub(/[^0-9.]/,"",os) # keep 18.5 form if present
142-
pri=(name ~ /iPhone/)?2:((name ~ /iPad/)?1:0)
143-
# preference score: major-match first, then minor proximity if same major
144-
split(os, p, "."); major=p[1]; minor=p[2]
145-
major_ok = (wantMajor=="" || major==wantMajor) ? 1 : 0
146-
minor_pen = (wantMinor=="" || major!=wantMajor) ? 999 : (minor=="" ? 500 : (minor<wantMinor ? wantMinor-minor : minor-wantMinor))
147-
printf("%d|%d|%03d|%s|%s\n", pri, major_ok, minor_pen, name, id)
148-
}
149-
' | sort -t'|' -k2,2nr -k1,1nr -k3,3n | head -n1 | awk -F'|' '{print "platform=iOS Simulator,id="$5}'
150-
)"
151-
[ -n "$sel" ] && { echo "$sel"; return; }
152-
fi
153-
154-
# 2) Fallback: simctl list devices available (plain text)
155-
if command -v xcrun >/dev/null 2>&1; then
156-
sel="$(
157-
xcrun simctl list devices available 2>/dev/null |
158-
awk -v wantMajor="${DESIRED_OS_MAJOR:-}" -v wantMinor="${DESIRED_OS_MINOR:-}" '
159-
# Example: "iPhone 16e (18.5) [UDID] (Available)"
160-
/\[/ && /\)/ {
161-
line=$0
162-
name=line; sub(/ *\(.*/,"",name); sub(/^ +/,"",name)
163-
os=""; if (match(line, /\(([0-9.]+)\)/, a)) os=a[1]
164-
udid=""; if (match(line, /\[([0-9A-Fa-f-]+)\]/, b)) udid=b[1]
165-
if (udid=="") next
166-
pri=(name ~ /iPhone/)?2:((name ~ /iPad/)?1:0)
167-
split(os, p, "."); major=p[1]; minor=p[2]
168-
major_ok = (wantMajor=="" || major==wantMajor) ? 1 : 0
169-
minor_pen = (wantMinor=="" || major!=wantMajor) ? 999 : (minor=="" ? 500 : (minor<wantMinor ? wantMinor-minor : minor-wantMinor))
170-
printf("%d|%d|%03d|%s|%s\n", pri, major_ok, minor_pen, name, udid)
171-
}
172-
' | sort -t'|' -k2,2nr -k1,1nr -k3,3n | head -n1 | awk -F'|' '{print "platform=iOS Simulator,id="$5}'
173-
)"
174-
[ -n "$sel" ] && { echo "$sel"; return; }
175-
fi
176-
}
177-
178-
SIM_DESTINATION="${IOS_SIM_DESTINATION:-}"
179-
if [ -z "$SIM_DESTINATION" ]; then
180-
SELECTED_DESTINATION="$(auto_select_destination || true)"
181-
if [ -n "${SELECTED_DESTINATION:-}" ]; then
182-
SIM_DESTINATION="$SELECTED_DESTINATION"
183-
ri_log "Auto-selected simulator destination '$SIM_DESTINATION'"
184-
else
185-
ri_log "Simulator auto-selection did not return a destination"
186-
fi
168+
# Determine an iOS 18 runtime and create a throwaway iPhone 16 device
169+
RUNTIME_ID="$(xcrun simctl list runtimes | awk '/iOS 18\./ && $0 ~ /Available/ {print $NF; exit}')"
170+
if [ -z "$RUNTIME_ID" ]; then
171+
ri_log "FATAL: No iOS 18.x simulator runtime available"
172+
exit 3
173+
fi
174+
DEVICE_TYPE="com.apple.CoreSimulator.SimDeviceType.iPhone-16"
175+
SIM_NAME="CN1 UI Test iPhone"
176+
SIM_UDID="$(xcrun simctl create "$SIM_NAME" "$DEVICE_TYPE" "$RUNTIME_ID" 2>/dev/null || true)"
177+
if [ -z "$SIM_UDID" ]; then
178+
ri_log "FATAL: Failed to create simulator ($DEVICE_TYPE, $RUNTIME_ID)"
179+
exit 3
187180
fi
188-
if [ -z "$SIM_DESTINATION" ]; then
189-
SIM_DESTINATION="platform=iOS Simulator,name=iPhone 16,OS=latest"
190-
ri_log "Falling back to default simulator destination '$SIM_DESTINATION'"
181+
SIM_UDID_CREATED="$SIM_UDID"
182+
ri_log "Created simulator $SIM_NAME ($SIM_UDID) with runtime $RUNTIME_ID"
183+
184+
# Boot it and wait until it's ready
185+
xcrun simctl boot "$SIM_UDID" >/dev/null 2>&1 || true
186+
if ! xcrun simctl bootstatus "$SIM_UDID" -b -t 180; then
187+
ri_log "FATAL: Simulator never reached booted state"
188+
exit 4
191189
fi
190+
ri_log "Simulator booted: $SIM_UDID"
191+
SIM_DESTINATION="id=$SIM_UDID"
192192

193193
ri_log "Running UI tests on destination '$SIM_DESTINATION'"
194194

@@ -263,17 +263,25 @@ if [ -n "$AUT_APP" ] && [ -d "$AUT_APP" ]; then
263263
if [ -n "$SIM_UDID" ]; then
264264
xcrun simctl bootstatus "$SIM_UDID" -b || xcrun simctl boot "$SIM_UDID"
265265
xcrun simctl install "$SIM_UDID" "$AUT_APP" || true
266+
if [ -n "$AUT_BUNDLE_ID" ]; then
267+
ri_log "Warm-launching $AUT_BUNDLE_ID"
268+
xcrun simctl terminate "$SIM_UDID" "$AUT_BUNDLE_ID" >/dev/null 2>&1 || true
269+
xcrun simctl launch "$SIM_UDID" "$AUT_BUNDLE_ID" --args -AppleLocale en_US -AppleLanguages "(en)" || true
270+
xcrun simctl io "$SIM_UDID" screenshot "$ARTIFACTS_DIR/pre-xctest.png" || true
271+
fi
266272

267-
# Now that a device is definitely booted, start syslog and video
273+
# Start syslog capture for this simulator
268274
SIM_SYSLOG="$ARTIFACTS_DIR/simulator-syslog.txt"
269275
ri_log "Capturing simulator syslog at $SIM_SYSLOG"
270-
(xcrun simctl spawn "$SIM_UDID" log stream --style syslog --level debug \
271-
|| xcrun simctl spawn "$SIM_UDID" log stream --style compact) > "$SIM_SYSLOG" 2>&1 &
276+
( xcrun simctl spawn "$SIM_UDID" log stream --style syslog --level debug \
277+
|| xcrun simctl spawn "$SIM_UDID" log stream --style compact ) > "$SIM_SYSLOG" 2>&1 &
272278
SYSLOG_PID=$!
273279

280+
# Start video recording
274281
RUN_VIDEO="$ARTIFACTS_DIR/run.mp4"
275282
ri_log "Recording simulator video to $RUN_VIDEO"
276283
( xcrun simctl io "$SIM_UDID" recordVideo "$RUN_VIDEO" & echo $! > "$SCREENSHOT_TMP_DIR/video.pid" ) || true
284+
VIDEO_PID="$(cat "$SCREENSHOT_TMP_DIR/video.pid" 2>/dev/null || true)"
277285

278286
if [ -n "$AUT_BUNDLE_ID" ] && [ -n "$SIM_UDID" ]; then
279287
ri_log "Warm-launching $AUT_BUNDLE_ID"
@@ -302,8 +310,9 @@ XCODE_TEST_FILTERS=(
302310
-skip-testing:HelloCodenameOneTests
303311
)
304312

313+
ri_log "STAGE:TEST -> xcodebuild test-without-building (destination=$SIM_DESTINATION)"
305314
set -o pipefail
306-
if ! xcodebuild \
315+
if ! run_with_timeout 1500 xcodebuild \
307316
-workspace "$WORKSPACE_PATH" \
308317
-scheme "$SCHEME" \
309318
-sdk iphonesimulator \
@@ -314,10 +323,17 @@ if ! xcodebuild \
314323
"${XCODE_TEST_FILTERS[@]}" \
315324
CODE_SIGNING_ALLOWED=NO CODE_SIGNING_REQUIRED=NO \
316325
GENERATE_INFOPLIST_FILE=YES \
326+
-maximum-test-execution-time-allowance 1200 \
317327
test-without-building | tee "$TEST_LOG"; then
318-
ri_log "STAGE:XCODE_TEST_FAILED -> See $TEST_LOG"
328+
rc=$?
329+
if [ "$rc" = "124" ]; then
330+
ri_log "STAGE:WATCHDOG_TRIGGERED -> Killed stalled xcodebuild"
331+
else
332+
ri_log "STAGE:XCODE_TEST_FAILED -> See $TEST_LOG"
333+
fi
319334
exit 10
320335
fi
336+
set +o pipefail
321337

322338
# --- Begin: Stop video + final screenshots ---
323339
if [ -f "$SCREENSHOT_TMP_DIR/video.pid" ]; then

0 commit comments

Comments
 (0)