Skip to content

Commit 1d3ec3b

Browse files
authored
Fix ios run command for devices (dotnet#404)
- `UninstallApp()` wasn't triggering for devices - mlaunch failures when running app didn't get detected Resolves dotnet#402
1 parent 841114a commit 1d3ec3b

File tree

3 files changed

+87
-59
lines changed

3 files changed

+87
-59
lines changed

src/Microsoft.DotNet.XHarness.CLI/Commands/iOS/iOSAppCommand.cs

+57-25
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// See the LICENSE file in the project root for more information.
44

55
using System;
6+
using System.Diagnostics.CodeAnalysis;
67
using System.IO;
78
using System.Text;
89
using System.Threading;
@@ -159,24 +160,49 @@ private async Task<ExitCode> RunApp(ILogger logger, TestTargetOs target, Logs lo
159160
return ExitCode.FAILED_TO_GET_BUNDLE_INFO;
160161
}
161162

163+
ExitCode exitCode = ExitCode.SUCCESS;
164+
162165
if (!target.Platform.IsSimulator())
163166
{
164-
var result = await InstallApp(
165-
appBundleInfo,
166-
deviceName,
167-
logger,
168-
target,
169-
logs,
170-
mainLog,
171-
cancellationToken);
167+
Exception? installException = null;
172168

173-
if (result != ExitCode.SUCCESS)
169+
try
174170
{
175-
return result;
171+
(deviceName, exitCode) = await InstallApp(appBundleInfo, deviceName, logger, target, mainLog, cancellationToken);
176172
}
177-
}
173+
catch (Exception e)
174+
{
175+
installException = e;
176+
}
177+
178+
if (exitCode != ExitCode.SUCCESS || installException != null)
179+
{
180+
var message = new StringBuilder().AppendLine("Application installation failed:");
181+
182+
if (ErrorKnowledgeBase.IsKnownInstallIssue(mainLog, out var failureMessage))
183+
{
184+
message.Append(failureMessage.Value.HumanMessage);
185+
if (failureMessage.Value.IssueLink != null)
186+
{
187+
message.AppendLine($" Find more information at {failureMessage.Value.IssueLink}");
188+
}
189+
}
190+
else if (installException != null)
191+
{
192+
message.AppendLine(installException.ToString());
193+
}
194+
195+
logger.LogError(message.ToString());
178196

179-
ExitCode exitCode;
197+
return exitCode;
198+
}
199+
200+
if (string.IsNullOrEmpty(deviceName))
201+
{
202+
logger.LogError("Failed to get the name of the device where application was installed!");
203+
return ExitCode.PACKAGE_INSTALLATION_FAILURE;
204+
}
205+
}
180206

181207
try
182208
{
@@ -201,22 +227,24 @@ private async Task<ExitCode> RunApp(ILogger logger, TestTargetOs target, Logs lo
201227
}
202228
catch (Exception e)
203229
{
230+
var message = new StringBuilder().AppendLine("Application run failed:");
231+
204232
if (ErrorKnowledgeBase.IsKnownTestIssue(mainLog, out var failureMessage))
205233
{
206-
var msg = $"Application run failed:{Environment.NewLine}{failureMessage.Value.HumanMessage}.";
234+
message.Append(failureMessage.Value.HumanMessage);
207235
if (failureMessage.Value.IssueLink != null)
208236
{
209-
msg += $" Find more information at {failureMessage.Value.IssueLink}";
237+
message.AppendLine($" Find more information at {failureMessage.Value.IssueLink}");
210238
}
211-
212-
logger.LogError(msg);
213239
}
214240
else
215241
{
216-
logger.LogError($"Application run failed:{Environment.NewLine}{e}");
242+
message.AppendLine(e.ToString());
217243
}
218244

219-
return ExitCode.APP_CRASH;
245+
logger.LogError(message.ToString());
246+
247+
exitCode = ExitCode.APP_LAUNCH_FAILURE;
220248
}
221249
finally
222250
{
@@ -236,12 +264,11 @@ private async Task<ExitCode> RunApp(ILogger logger, TestTargetOs target, Logs lo
236264
return exitCode;
237265
}
238266

239-
private async Task<ExitCode> InstallApp(
267+
private async Task<(string?, ExitCode)> InstallApp(
240268
AppBundleInformation appBundleInfo,
241269
string? deviceName,
242270
ILogger logger,
243271
TestTargetOs target,
244-
Logs logs,
245272
IFileBackedLog mainLog,
246273
CancellationToken cancellationToken)
247274
{
@@ -259,12 +286,12 @@ private async Task<ExitCode> InstallApp(
259286
{
260287
logger.LogError($"Failed to find suitable device for target {target.AsString()}" + Environment.NewLine +
261288
"Please make sure the device is connected and unlocked.");
262-
return ExitCode.DEVICE_NOT_FOUND;
289+
return (null, ExitCode.DEVICE_NOT_FOUND);
263290
}
264291
catch (Exception e)
265292
{
266293
logger.LogError($"Failed to install the app bundle:{Environment.NewLine}{e}");
267-
return ExitCode.PACKAGE_INSTALLATION_FAILURE;
294+
return (null, ExitCode.PACKAGE_INSTALLATION_FAILURE);
268295
}
269296

270297
if (!result.Succeeded)
@@ -286,15 +313,20 @@ private async Task<ExitCode> InstallApp(
286313
logger.LogError($"Failed to install the app bundle (exit code={result.ExitCode})");
287314
}
288315

289-
return ExitCode.PACKAGE_INSTALLATION_FAILURE;
316+
return (deviceName, ExitCode.PACKAGE_INSTALLATION_FAILURE);
290317
}
291318

292319
logger.LogInformation($"Application '{appBundleInfo.AppName}' was installed successfully on device '{deviceName}'");
293320

294-
return ExitCode.SUCCESS;
321+
return (deviceName, ExitCode.SUCCESS);
295322
}
296323

297-
private async Task UninstallApp(AppBundleInformation appBundleInfo, string deviceName, ILogger logger, IFileBackedLog mainLog, CancellationToken cancellationToken)
324+
private async Task UninstallApp(
325+
AppBundleInformation appBundleInfo,
326+
string deviceName,
327+
ILogger logger,
328+
IFileBackedLog mainLog,
329+
CancellationToken cancellationToken)
298330
{
299331
logger.LogInformation($"Uninstalling the application '{appBundleInfo.AppName}' from device '{deviceName}'");
300332

src/Microsoft.DotNet.XHarness.iOS/AppRunner.cs

+6-7
Original file line numberDiff line numberDiff line change
@@ -230,23 +230,22 @@ private async Task RunDeviceApp(
230230

231231
_mainLog.WriteLine("Starting test run");
232232

233-
await _processManager.ExecuteCommandAsync(
233+
var result = await _processManager.ExecuteCommandAsync(
234234
mlaunchArguments,
235235
_mainLog,
236236
timeout,
237237
cancellationToken: cancellationToken);
238+
239+
if (!result.Succeeded)
240+
{
241+
throw new Exception("Failed to run the application!");
242+
}
238243
}
239244
finally
240245
{
241246
deviceLogCapturer.StopCapture();
242247
deviceSystemLog.Dispose();
243248
}
244-
245-
// Upload the system log
246-
if (File.Exists(deviceSystemLog.FullPath))
247-
{
248-
_mainLog.WriteLine("A capture of the device log is: {0}", deviceSystemLog.FullPath);
249-
}
250249
}
251250

252251
private MlaunchArguments GetCommonArguments(int verbosity)

tests/Microsoft.DotNet.XHarness.iOS.Tests/AppRunnerTests.cs

+24-27
Original file line numberDiff line numberDiff line change
@@ -404,39 +404,36 @@ public async Task RunOnDeviceSuccessfullyTest()
404404
}
405405

406406
[Fact]
407-
public async Task RunOnDeviceWithMissingSystemLogTest()
407+
public async Task RunOnSimulatorWithMissingSystemLogTest()
408408
{
409-
var testLog = new Mock<IFileBackedLog>();
410-
testLog.SetupGet(x => x.FullPath).Returns(Path.GetTempFileName());
411-
testLog.SetupGet(x => x.Description).Returns("test log");
412-
413-
SetupLogList(new[] { testLog.Object });
414-
_logs
415-
.Setup(x => x.Create("device-" + DeviceName + "-mocked_timestamp.log", LogType.SystemLog.ToString(), It.IsAny<bool?>()))
416-
.Returns(testLog.Object);
409+
_simulatorLoader
410+
.Setup(x => x.FindSimulators(It.Is<TestTargetOs>(t => t.Platform == TestTarget.Simulator_tvOS), _mainLog.Object, It.IsAny<int>(), true, false))
411+
.ReturnsAsync((_mockSimulator.Object, null));
417412

418-
var deviceLogCapturer = new Mock<IDeviceLogCapturer>();
413+
var captureLog = new Mock<ICaptureLog>();
414+
captureLog.SetupGet(x => x.FullPath).Returns(_simulatorLogPath);
415+
captureLog.SetupGet(x => x.Description).Returns(LogType.TestLog.ToString());
419416

420-
var deviceLogCapturerFactory = new Mock<IDeviceLogCapturerFactory>();
421-
deviceLogCapturerFactory
422-
.Setup(x => x.Create(_mainLog.Object, testLog.Object, DeviceName))
423-
.Returns(deviceLogCapturer.Object);
417+
var captureLogFactory = new Mock<ICaptureLogFactory>();
418+
captureLogFactory
419+
.Setup(x => x.Create(
420+
Path.Combine(_logs.Object.Directory, _mockSimulator.Object.Name + ".log"),
421+
_mockSimulator.Object.SystemLog,
422+
false,
423+
It.IsAny<string>()))
424+
.Returns(captureLog.Object);
424425

425-
var x = _logs.Object.First();
426+
SetupLogList(new[] { captureLog.Object });
426427

427428
var appInformation = GetMockedAppBundleInfo();
428429

429-
_exitCodeDetector
430-
.Setup(x => x.DetectExitCode(appInformation, It.IsAny<IReadableLog>()))
431-
.Returns(0);
432-
433430
// Act
434431
var appRunner = new AppRunner(_processManager.Object,
435432
_hardwareDeviceLoader.Object,
436433
_simulatorLoader.Object,
437434
_snapshotReporterFactory,
438-
Mock.Of<ICaptureLogFactory>(),
439-
deviceLogCapturerFactory.Object,
435+
captureLogFactory.Object,
436+
Mock.Of<IDeviceLogCapturerFactory>(),
440437
_exitCodeDetector.Object,
441438
_mainLog.Object,
442439
_logs.Object,
@@ -445,31 +442,31 @@ public async Task RunOnDeviceWithMissingSystemLogTest()
445442

446443
var (deviceName, exitCode) = await appRunner.RunApp(
447444
appInformation,
448-
new TestTargetOs(TestTarget.Device_iOS, null),
445+
new TestTargetOs(TestTarget.Simulator_tvOS, null),
449446
TimeSpan.FromSeconds(30));
450447

451448
// Verify
452-
Assert.Equal(DeviceName, deviceName);
449+
Assert.Equal(SimulatorDeviceName, deviceName);
453450
Assert.Null(exitCode);
454451

455-
var expectedArgs = GetExpectedDeviceMlaunchArgs();
452+
var expectedArgs = GetExpectedSimulatorMlaunchArgs();
456453

457454
_processManager
458455
.Verify(
459456
x => x.ExecuteCommandAsync(
460457
It.Is<MlaunchArguments>(args => args.AsCommandLine() == expectedArgs),
461-
It.IsAny<ILog>(),
458+
_mainLog.Object,
462459
It.IsAny<TimeSpan>(),
463460
null,
464461
It.IsAny<CancellationToken>()),
465462
Times.Once);
466463

467-
_hardwareDeviceLoader.VerifyAll();
464+
_simulatorLoader.VerifyAll();
468465

469466
_snapshotReporter.Verify(x => x.StartCaptureAsync(), Times.AtLeastOnce);
470467
_snapshotReporter.Verify(x => x.StartCaptureAsync(), Times.AtLeastOnce);
471468

472-
testLog.Verify(x => x.Dispose(), Times.AtLeastOnce);
469+
captureLog.Verify(x => x.Dispose(), Times.AtLeastOnce);
473470
}
474471

475472
private static AppBundleInformation GetMockedAppBundleInfo() =>

0 commit comments

Comments
 (0)