diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 5e2ae792111b..85b1789deae2 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -24,7 +24,7 @@ "rollForward": false }, "microsoft.dotnet.xharness.cli": { - "version": "10.0.0-prerelease.25575.2", + "version": "11.0.0-prerelease.25603.1", "commands": [ "xharness" ], diff --git a/src/TestUtils/src/Microsoft.Maui.IntegrationTests/Apple/Simulator.cs b/src/TestUtils/src/Microsoft.Maui.IntegrationTests/Apple/Simulator.cs index 64288dd8f7d0..30abd07e0a31 100644 --- a/src/TestUtils/src/Microsoft.Maui.IntegrationTests/Apple/Simulator.cs +++ b/src/TestUtils/src/Microsoft.Maui.IntegrationTests/Apple/Simulator.cs @@ -19,7 +19,34 @@ public string GetUDID() public bool Launch() { ToolRunner.Run(XCRunTool, $"simctl boot {GetUDID()}", out int exitCode, timeoutInSeconds: 30); - return exitCode == 0; + if (exitCode != 0) + return false; + + // Wait for the simulator to be fully booted before returning + // The boot command can return before the simulator is ready to accept app launches + return WaitForSimulatorReady(timeoutInSeconds: 60); + } + + bool WaitForSimulatorReady(int timeoutInSeconds = 60) + { + var udid = GetUDID(); + var startTime = DateTime.UtcNow; + var timeout = TimeSpan.FromSeconds(timeoutInSeconds); + + while (DateTime.UtcNow - startTime < timeout) + { + var output = ToolRunner.Run(XCRunTool, $"simctl bootstatus {udid}", out int exitCode, timeoutInSeconds: 10); + if (exitCode == 0) + return true; + + // Print diagnostic output to help troubleshoot boot issues + TestContext.WriteLine($"Simulator not ready yet: {output}"); + + // Wait a bit before checking again + System.Threading.Thread.Sleep(2000); + } + + return false; } public bool Shutdown() diff --git a/src/TestUtils/src/Microsoft.Maui.IntegrationTests/AppleTemplateTests.cs b/src/TestUtils/src/Microsoft.Maui.IntegrationTests/AppleTemplateTests.cs index a5b5dd44a3d7..cb9a6370397d 100644 --- a/src/TestUtils/src/Microsoft.Maui.IntegrationTests/AppleTemplateTests.cs +++ b/src/TestUtils/src/Microsoft.Maui.IntegrationTests/AppleTemplateTests.cs @@ -51,7 +51,6 @@ public void RunOniOS(string id, string config, string framework, string runtimeI buildProps.Add("PublishAot=true"); buildProps.Add("PublishAotUsingRuntimePack=true"); // TODO: This parameter will become obsolete https://github.com/dotnet/runtime/issues/87060 buildProps.Add("_IsPublishing=true"); // using dotnet build with -p:_IsPublishing=true enables targeting simulators - buildProps.Add($"RuntimeIdentifier={runtimeIdentifier}"); buildProps.Add("IlcTreatWarningsAsErrors=false"); // TODO: Remove this once all warnings are fixed https://github.com/dotnet/maui/issues/19397 } @@ -61,12 +60,13 @@ public void RunOniOS(string id, string config, string framework, string runtimeI buildProps.Add("TrimmerSingleWarn=false"); // Disable trimmer warnings for iOS full trimming builds due to ObjCRuntime issues } - Assert.IsTrue(DotnetInternal.Build(projectFile, config, framework: $"{framework}-ios", properties: buildProps), + Assert.IsTrue(DotnetInternal.Build(projectFile, config, framework: $"{framework}-ios", properties: buildProps, runtimeIdentifier: runtimeIdentifier), $"Project {Path.GetFileName(projectFile)} failed to build. Check test output/attachments for errors."); var appFile = Path.Combine(projectDir, "bin", config, $"{framework}-ios", runtimeIdentifier, $"{Path.GetFileName(projectDir)}.app"); - Assert.IsTrue(XHarness.RunAppleForTimeout(appFile, Path.Combine(projectDir, "xh-results"), TestSimulator.XHarnessID), + // Pass the simulator UDID to help XHarness use our already-booted simulator + Assert.IsTrue(XHarness.RunAppleForTimeout(appFile, Path.Combine(projectDir, "xh-results"), TestSimulator.XHarnessID, TestSimulator.GetUDID()), $"Project {Path.GetFileName(projectFile)} failed to run. Check test output/attachments for errors."); } } diff --git a/src/TestUtils/src/Microsoft.Maui.IntegrationTests/Utilities/XHarness.cs b/src/TestUtils/src/Microsoft.Maui.IntegrationTests/Utilities/XHarness.cs index 03e023525465..abecbc292e7a 100644 --- a/src/TestUtils/src/Microsoft.Maui.IntegrationTests/Utilities/XHarness.cs +++ b/src/TestUtils/src/Microsoft.Maui.IntegrationTests/Utilities/XHarness.cs @@ -21,12 +21,14 @@ public static bool RunAndroid(string packageName, string resultDir, int expected /// /// /// + /// Optional UDID of a specific already-booted simulator to use. /// /// True if the app launch command timed out, false if it exits early. - public static bool RunAppleForTimeout(string appPath, string resultDir, string targetDevice, int launchTimeoutSeconds = 75) + public static bool RunAppleForTimeout(string appPath, string resultDir, string targetDevice, string? deviceUDID = null, int launchTimeoutSeconds = 75) { var timeoutString = TimeSpan.FromSeconds(launchTimeoutSeconds).ToString(); - var args = $"apple run --app=\"{appPath}\" --output-directory=\"{resultDir}\" --target={targetDevice} --timeout=\"{timeoutString}\" --verbosity=Debug"; + var deviceArg = string.IsNullOrEmpty(deviceUDID) ? "" : $" --device=\"{deviceUDID}\""; + var args = $"apple run --app=\"{appPath}\" --output-directory=\"{resultDir}\" --target={targetDevice}{deviceArg} --timeout=\"{timeoutString}\" --verbosity=Debug"; var xhOutput = RunForOutput(args, out int exitCode, launchTimeoutSeconds + 30); var launchLogMatch = false;