diff --git a/.github/workflows/device-tests-ios.yml b/.github/workflows/device-tests-ios.yml index f916748374..7ebe9774ed 100644 --- a/.github/workflows/device-tests-ios.yml +++ b/.github/workflows/device-tests-ios.yml @@ -75,14 +75,7 @@ jobs: run: pwsh ./scripts/device-test.ps1 ios -Build - name: Run Tests - id: first-test-run - continue-on-error: true - timeout-minutes: 40 - run: pwsh scripts/device-test.ps1 ios -Run -Verbose - - - name: Retry Tests (if previous failed to run) - if: steps.first-test-run.outcome == 'failure' - timeout-minutes: 40 + timeout-minutes: 60 run: pwsh scripts/device-test.ps1 ios -Run -Verbose - name: Run Integration Tests diff --git a/scripts/device-test-utils.ps1 b/scripts/device-test-utils.ps1 index 4a492592df..546a2d2e47 100644 --- a/scripts/device-test-utils.ps1 +++ b/scripts/device-test-utils.ps1 @@ -1,3 +1,37 @@ +function Reset-IosSimulator { + [CmdletBinding()] + param( + [Parameter(Mandatory)] + [PSCustomObject]$SimInfo + ) + + $udid = $SimInfo.Udid + + Write-Host "Hard-resetting simulator $($SimInfo.Name) [$udid]..." + + # Shut down & delete the old device + xcrun simctl shutdown $udid 2>&1 | Out-Null + xcrun simctl delete $udid 2>&1 | Out-Null + + # Restart the CoreSimulator service to clear any daemon-level state left + # over from a simulator crash (this is what makes a fresh runner "work"). + Write-Host "Restarting CoreSimulator service..." + sudo launchctl kickstart -kp system/com.apple.CoreSimulator.CoreSimulatorService 2>&1 | Out-Null + Start-Sleep -Seconds 5 # give the daemon time to re-initialise + + # Create a brand-new simulator with the same device type & runtime + $newUdid = (& xcrun simctl create $SimInfo.Name $SimInfo.DeviceType $SimInfo.Runtime).Trim() + Write-Host "Created new simulator $($SimInfo.Name) [$newUdid]" + + # Boot and wait + xcrun simctl boot $newUdid 2>&1 | Out-Null + xcrun simctl bootstatus $newUdid -b + + # Return updated info + $SimInfo.Udid = $newUdid + return $newUdid +} + function Install-XHarness { if (!(Get-Command xharness -ErrorAction SilentlyContinue)) @@ -120,5 +154,10 @@ function Get-IosSimulatorUdid { } Write-Verbose ("Selected simulator: {0} ({1}) [{2}]" -f $selected.Device.name, $selected.Device.deviceTypeIdentifier, $selected.Device.udid) - return $selected.Device.udid + return [PSCustomObject]@{ + Udid = $selected.Device.udid + Name = $selected.Device.name + DeviceType = $selected.Device.deviceTypeIdentifier + Runtime = $runtimeKey + } } diff --git a/scripts/device-test.ps1 b/scripts/device-test.ps1 index af539978a9..14401d5646 100644 --- a/scripts/device-test.ps1 +++ b/scripts/device-test.ps1 @@ -29,6 +29,7 @@ try $Tfm = 'net10.0' } $arch = (!$IsWindows -and $(uname -m) -eq 'arm64') ? 'arm64' : 'x64' + $udid = $null if ($Platform -eq 'android') { $Tfm += '-android' @@ -64,8 +65,11 @@ try $udid = Get-IosSimulatorUdid -Verbose if ($udid) { + $simInfo = $udid # Get-IosSimulatorUdid now returns an object + $udid = $simInfo.Udid $arguments += @('--device', $udid) } else { + $simInfo = $null Write-Host "No suitable simulator found; proceeding without a specific --device" } } @@ -84,13 +88,59 @@ try { Install-XHarness Remove-Item -Recurse -Force test_output -ErrorAction SilentlyContinue + + if ($Platform -eq 'ios' -and $udid) + { + Write-Host "Ensuring simulator is booted and ready..." + if ($CI) + { + # On CI, do a full reset to guarantee a clean simulator + $udid = Reset-IosSimulator -SimInfo $simInfo + # Update arguments with new UDID + for ($i = 0; $i -lt $arguments.Count; $i++) { + if ($arguments[$i] -eq '--device' -and ($i + 1) -lt $arguments.Count) { + $arguments[$i + 1] = $udid + break + } + } + } + else + { + xcrun simctl boot $udid 2>&1 | Out-Null # no-op if already booted + xcrun simctl bootstatus $udid -b # block until fully operational + } + } + try { if ($VerbosePreference) { $arguments += '-v' } - xharness $group test $arguments --output-directory=test_output + + $maxAttempts = 3 + for ($attempt = 1; $attempt -le $maxAttempts; $attempt++) + { + if ($attempt -gt 1) + { + Write-Host "Retrying xharness (attempt $attempt of $maxAttempts)..." + Remove-Item -Recurse -Force test_output -ErrorAction SilentlyContinue + if ($Platform -eq 'ios' -and $simInfo) + { + $udid = Reset-IosSimulator -SimInfo $simInfo + # Update arguments with new UDID + for ($i = 0; $i -lt $arguments.Count; $i++) { + if ($arguments[$i] -eq '--device' -and ($i + 1) -lt $arguments.Count) { + $arguments[$i + 1] = $udid + break + } + } + } + } + xharness $group test $arguments --output-directory=test_output + if ($LASTEXITCODE -eq 0) { break } + } + if ($LASTEXITCODE -ne 0) { $testResultsXml = './test_output/TestResults.xml'