From 502b6a2d1e0ec4adb499067bd22154f73d3d29b6 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Fri, 27 Feb 2026 10:02:29 +0100 Subject: [PATCH 1/5] ci: run iOS device tests on arm64 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit System.Reflection.Emit is blocked on arm64 simulators due to W^X — this is what NSubstitute/Castle.DynamicProxy needs: https://learn.microsoft.com/en-us/dotnet/maui/macios/interpreter The Mono interpreter bypasses this by interpreting emitted IL instead of generating native code. Sentry.Maui.Device.TestApp.csproj already has true for Release, and the build already passes EnableAot=false. So the two workarounds are redundant — either x64 via Rosetta OR the interpreter alone should suffice. Switching to iossimulator-arm64 should work with the current build settings. Co-Authored-By: Claude Opus 4.6 --- scripts/device-test.ps1 | 2 -- .../SentryHttpMessageHandlerBuilderFilterTests.cs | 8 ++++---- .../Sentry.Maui.Device.TestApp.csproj | 4 ++-- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/scripts/device-test.ps1 b/scripts/device-test.ps1 index dc896e2280..60a2c82644 100644 --- a/scripts/device-test.ps1 +++ b/scripts/device-test.ps1 @@ -52,8 +52,6 @@ try { $Tfm += '-ios' $group = 'apple' - # Always use x64 on iOS, since arm64 doesn't support JIT, which is required for tests using NSubstitute - $arch = 'x64' $buildDir = "test/Sentry.Maui.Device.TestApp/bin/Release/$Tfm/iossimulator-$arch" $envValue = $CI ? 'true' : 'false' $arguments = @( diff --git a/test/Sentry.Extensions.Logging.Tests/SentryHttpMessageHandlerBuilderFilterTests.cs b/test/Sentry.Extensions.Logging.Tests/SentryHttpMessageHandlerBuilderFilterTests.cs index ee3e59fff6..49349a8b5a 100644 --- a/test/Sentry.Extensions.Logging.Tests/SentryHttpMessageHandlerBuilderFilterTests.cs +++ b/test/Sentry.Extensions.Logging.Tests/SentryHttpMessageHandlerBuilderFilterTests.cs @@ -7,8 +7,8 @@ public class SentryHttpMessageHandlerBuilderFilterTests [SkippableFact] public void Configure_HandlerEnabled_ShouldAddSentryHttpMessageHandler() { -#if __ANDROID__ - Skip.If(true, "Can't create proxies for classes without parameterless constructors on Android"); +#if __MOBILE__ + Skip.If(true, "Can't create proxies for classes without parameterless constructors on mobile"); #endif // Arrange @@ -31,8 +31,8 @@ public void Configure_HandlerEnabled_ShouldAddSentryHttpMessageHandler() [SkippableFact] public void Configure_HandlerDisabled_ShouldNotAddSentryHttpMessageHandler() { -#if __ANDROID__ - Skip.If(true, "Can't create proxies for classes without parameterless constructors on Android"); +#if __MOBILE__ + Skip.If(true, "Can't create proxies for classes without parameterless constructors on mobile"); #endif // Arrange diff --git a/test/Sentry.Maui.Device.TestApp/Sentry.Maui.Device.TestApp.csproj b/test/Sentry.Maui.Device.TestApp/Sentry.Maui.Device.TestApp.csproj index 602e09d06b..64d296477a 100644 --- a/test/Sentry.Maui.Device.TestApp/Sentry.Maui.Device.TestApp.csproj +++ b/test/Sentry.Maui.Device.TestApp/Sentry.Maui.Device.TestApp.csproj @@ -65,8 +65,8 @@ android-arm64 android-x64 - - iossimulator-x64 + iossimulator-arm64 + iossimulator-x64 maccatalyst-arm64 maccatalyst-x64 From 2fb862afed3fdc16c718a32501ae5e689a0c5a9f Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Fri, 27 Feb 2026 14:27:52 +0100 Subject: [PATCH 2/5] ci: pre-disable simulator watchdogs before boot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit mlaunch (inside xharness) checks if simulator watchdogs are disabled before launching an app. If they aren't, it shuts down the simulator, writes plist files, then reboots — this sequence is flaky on CI, often leaving the simulator stuck in a Shutdown state with: "Unable to lookup in current state: Shutdown" Root cause was found by decompiling mlaunch with ilspycmd (it ships as a compiled DLL in the xharness NuGet). It checks two plists under the simulator's data directory: ~/Library/Developer/CoreSimulator/Devices/$UDID/data/Library/Preferences/ - com.apple.springboard.plist - com.apple.frontboard.plist All 6 FBLaunchWatchdog* keys must be >= 100, otherwise mlaunch shuts down the sim to write them and reboots — which races on CI. Fix: pre-write both plists with the 6 keys set to 100 before booting the simulator ourselves. mlaunch then sees watchdogs already disabled and the sim already booted, skipping its entire shutdown/reboot dance. Co-Authored-By: Claude Opus 4.6 --- scripts/device-test-utils.ps1 | 43 +++++++++++++++++++++++++++++++++++ scripts/device-test.ps1 | 3 +++ 2 files changed, 46 insertions(+) diff --git a/scripts/device-test-utils.ps1 b/scripts/device-test-utils.ps1 index 455e85e4e8..a8d70df0b2 100644 --- a/scripts/device-test-utils.ps1 +++ b/scripts/device-test-utils.ps1 @@ -26,6 +26,49 @@ function Get-AndroidEmulatorId } } +# mlaunch (inside xharness) checks if simulator watchdogs are disabled before +# launching an app. If not, it shuts down the sim, writes plist files, then +# reboots via Simulator.app — but simctl still sees it as Shutdown, so the +# launch fails. The CI log sequence: +# +# dbug: Xamarin.Hosting: Simulator watchdogs are not disabled for 'iPhone 17 (...)' +# dbug: Xamarin.Hosting: Shutting down simulator... +# dbug: Xamarin.Hosting: Successfully disabled simulator watchdogs for 'iPhone 17 (...)' +# dbug: Xamarin.Hosting: Launching simulator application 'com.apple.iphonesimulator' +# dbug: Xamarin.Hosting: Ready notification 'com.apple.iphonesimulator.ready' received from the simulator. +# dbug: Unable to lookup in current state: Shutdown +# dbug: error HE0042: Could not launch the app '...' on the device '...': simctl returned exit code 149 +# dbug: Process mlaunch exited with 1 +# +# By pre-writing the watchdog plists before booting, mlaunch sees watchdogs +# already disabled and skips its shutdown/reboot dance entirely. +function Disable-IosSimulatorWatchdogs { + param( + [Parameter(Mandatory)] + [string]$Udid + ) + $prefsPath = "$HOME/Library/Developer/CoreSimulator/Devices/$Udid/data/Library/Preferences" + New-Item -ItemType Directory -Force -Path $prefsPath | Out-Null + $keys = @( + 'FBLaunchWatchdogScale', + 'FBLaunchWatchdogFirstPartyScale', + 'FBLaunchWatchdogResumeScale', + 'FBLaunchWatchdogScaleOverride', + 'FBLaunchWatchdogFirstPartyScaleOverride', + 'FBLaunchWatchdogResumeScaleOverride' + ) + foreach ($plist in @('com.apple.springboard.plist', 'com.apple.frontboard.plist')) { + $plistPath = "$prefsPath/$plist" + if (-not (Test-Path $plistPath)) { + /usr/bin/plutil -create xml1 $plistPath + } + foreach ($key in $keys) { + /usr/libexec/PlistBuddy -c "Delete :$key" $plistPath 2>&1 | Out-Null + /usr/libexec/PlistBuddy -c "Add :$key real 100" $plistPath + } + } +} + function Get-IosSimulatorUdid { [CmdletBinding()] param( diff --git a/scripts/device-test.ps1 b/scripts/device-test.ps1 index 60a2c82644..90760833a3 100644 --- a/scripts/device-test.ps1 +++ b/scripts/device-test.ps1 @@ -64,6 +64,9 @@ try $udid = Get-IosSimulatorUdid -Verbose if ($udid) { + if ($CI -and $Run) { + Disable-IosSimulatorWatchdogs -Udid $udid + } $arguments += @('--device', $udid) } else { Write-Host "No suitable simulator found; proceeding without a specific --device" From d10ed1557a8445f3a8c18412e21dd9a9f1f54140 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Fri, 27 Feb 2026 14:27:59 +0100 Subject: [PATCH 3/5] debug: enable verbose output for iOS device tests Co-Authored-By: Claude Opus 4.6 --- .github/workflows/device-tests-ios.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/device-tests-ios.yml b/.github/workflows/device-tests-ios.yml index c4f191a8a6..c966f658ca 100644 --- a/.github/workflows/device-tests-ios.yml +++ b/.github/workflows/device-tests-ios.yml @@ -78,12 +78,12 @@ jobs: id: first-test-run continue-on-error: true timeout-minutes: 40 - run: pwsh scripts/device-test.ps1 ios -Run + 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 - run: pwsh scripts/device-test.ps1 ios -Run + run: pwsh scripts/device-test.ps1 ios -Run -Verbose - name: Run Integration Tests id: first-integration-test-run From dbff261ae33980b8c9b1a012d318bf87c6888227 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Sat, 28 Feb 2026 10:51:08 +0100 Subject: [PATCH 4/5] Revert "ci: pre-disable simulator watchdogs before boot" This reverts commit 2fb862afed3fdc16c718a32501ae5e689a0c5a9f. --- scripts/device-test-utils.ps1 | 43 ----------------------------------- scripts/device-test.ps1 | 3 --- 2 files changed, 46 deletions(-) diff --git a/scripts/device-test-utils.ps1 b/scripts/device-test-utils.ps1 index a8d70df0b2..455e85e4e8 100644 --- a/scripts/device-test-utils.ps1 +++ b/scripts/device-test-utils.ps1 @@ -26,49 +26,6 @@ function Get-AndroidEmulatorId } } -# mlaunch (inside xharness) checks if simulator watchdogs are disabled before -# launching an app. If not, it shuts down the sim, writes plist files, then -# reboots via Simulator.app — but simctl still sees it as Shutdown, so the -# launch fails. The CI log sequence: -# -# dbug: Xamarin.Hosting: Simulator watchdogs are not disabled for 'iPhone 17 (...)' -# dbug: Xamarin.Hosting: Shutting down simulator... -# dbug: Xamarin.Hosting: Successfully disabled simulator watchdogs for 'iPhone 17 (...)' -# dbug: Xamarin.Hosting: Launching simulator application 'com.apple.iphonesimulator' -# dbug: Xamarin.Hosting: Ready notification 'com.apple.iphonesimulator.ready' received from the simulator. -# dbug: Unable to lookup in current state: Shutdown -# dbug: error HE0042: Could not launch the app '...' on the device '...': simctl returned exit code 149 -# dbug: Process mlaunch exited with 1 -# -# By pre-writing the watchdog plists before booting, mlaunch sees watchdogs -# already disabled and skips its shutdown/reboot dance entirely. -function Disable-IosSimulatorWatchdogs { - param( - [Parameter(Mandatory)] - [string]$Udid - ) - $prefsPath = "$HOME/Library/Developer/CoreSimulator/Devices/$Udid/data/Library/Preferences" - New-Item -ItemType Directory -Force -Path $prefsPath | Out-Null - $keys = @( - 'FBLaunchWatchdogScale', - 'FBLaunchWatchdogFirstPartyScale', - 'FBLaunchWatchdogResumeScale', - 'FBLaunchWatchdogScaleOverride', - 'FBLaunchWatchdogFirstPartyScaleOverride', - 'FBLaunchWatchdogResumeScaleOverride' - ) - foreach ($plist in @('com.apple.springboard.plist', 'com.apple.frontboard.plist')) { - $plistPath = "$prefsPath/$plist" - if (-not (Test-Path $plistPath)) { - /usr/bin/plutil -create xml1 $plistPath - } - foreach ($key in $keys) { - /usr/libexec/PlistBuddy -c "Delete :$key" $plistPath 2>&1 | Out-Null - /usr/libexec/PlistBuddy -c "Add :$key real 100" $plistPath - } - } -} - function Get-IosSimulatorUdid { [CmdletBinding()] param( diff --git a/scripts/device-test.ps1 b/scripts/device-test.ps1 index 90760833a3..60a2c82644 100644 --- a/scripts/device-test.ps1 +++ b/scripts/device-test.ps1 @@ -64,9 +64,6 @@ try $udid = Get-IosSimulatorUdid -Verbose if ($udid) { - if ($CI -and $Run) { - Disable-IosSimulatorWatchdogs -Udid $udid - } $arguments += @('--device', $udid) } else { Write-Host "No suitable simulator found; proceeding without a specific --device" From a55c17774e39e182ddda91e33a68b4e95b8934ba Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Sat, 28 Feb 2026 10:51:37 +0100 Subject: [PATCH 5/5] Try xharness 11.0.0-prerelease.26117.1 --- scripts/device-test-utils.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/device-test-utils.ps1 b/scripts/device-test-utils.ps1 index 455e85e4e8..4a492592df 100644 --- a/scripts/device-test-utils.ps1 +++ b/scripts/device-test-utils.ps1 @@ -4,7 +4,7 @@ function Install-XHarness { $CI = Test-Path env:CI Push-Location ($CI ? $env:RUNNER_TEMP : $IsWindows ? $env:TMP : $IsMacos ? $env:TMPDIR : '/tmp') - dotnet tool install Microsoft.DotNet.XHarness.CLI --global --version '10.0.0-prerelease.25466.1' ` + dotnet tool install Microsoft.DotNet.XHarness.CLI --global --version '11.0.0-prerelease.26117.1' ` --add-source https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json Pop-Location }