Skip to content

Commit d27acf3

Browse files
premunlpatalas
andauthored
Add apple simulators reset-simulator command (#784)
Co-authored-by: Łukasz Patalas <dev@lukaszpatalas.pl>
1 parent b2b296f commit d27acf3

File tree

12 files changed

+301
-38
lines changed

12 files changed

+301
-38
lines changed

src/Microsoft.DotNet.XHarness.Apple/Orchestration/BaseOrchestrator.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,15 +159,16 @@ protected async Task<ExitCode> OrchestrateOperation(
159159
if (target.Platform.IsSimulator() && resetSimulator)
160160
{
161161
var simulator = (ISimulatorDevice)device;
162+
var bundleIds = appBundleInfo.BundleIdentifier == string.Empty ? Array.Empty<string>() : new[] { appBundleInfo.BundleIdentifier };
162163

163164
_logger.LogInformation($"Reseting simulator '{device.Name}'");
164-
await simulator.PrepareSimulator(_mainLog, appBundleInfo.BundleIdentifier);
165+
await simulator.PrepareSimulator(_mainLog, bundleIds);
165166

166167
if (companionDevice != null)
167168
{
168169
_logger.LogInformation($"Reseting companion simulator '{companionDevice.Name}'");
169170
var companionSimulator = (ISimulatorDevice)companionDevice;
170-
await companionSimulator.PrepareSimulator(_mainLog, appBundleInfo.BundleIdentifier);
171+
await companionSimulator.PrepareSimulator(_mainLog, bundleIds);
171172
}
172173

173174
_logger.LogInformation("Simulator reset finished");

src/Microsoft.DotNet.XHarness.Apple/Orchestration/InstallOrchestrator.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,13 +78,13 @@ public async Task<ExitCode> OrchestrateInstall(
7878
return ExitCode.FAILED_TO_GET_BUNDLE_INFO;
7979
}
8080

81-
static Task<ExitCode> executeMacCatalystApp(AppBundleInformation appBundleInfo)
81+
static Task<ExitCode> ExecuteMacCatalystApp(AppBundleInformation appBundleInfo)
8282
=> throw new InvalidOperationException("install command not available on maccatalyst");
8383

84-
static Task<ExitCode> executeApp(AppBundleInformation appBundleInfo, IDevice device, IDevice? companionDevice)
84+
static Task<ExitCode> ExecuteApp(AppBundleInformation appBundleInfo, IDevice device, IDevice? companionDevice)
8585
=> Task.FromResult(ExitCode.SUCCESS); // no-op
8686

87-
var result = await OrchestrateOperation(target, deviceName, includeWirelessDevices, resetSimulator, enableLldb, appBundleInfo, executeMacCatalystApp, executeApp, cancellationToken);
87+
var result = await OrchestrateOperation(target, deviceName, includeWirelessDevices, resetSimulator, enableLldb, appBundleInfo, ExecuteMacCatalystApp, ExecuteApp, cancellationToken);
8888

8989
if (cancellationToken.IsCancellationRequested)
9090
{

src/Microsoft.DotNet.XHarness.Apple/Orchestration/RunOrchestrator.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,10 @@ public virtual async Task<ExitCode> OrchestrateRun(
111111
launchTimeoutCancellation.Token,
112112
cancellationToken);
113113

114-
Task<ExitCode> executeMacCatalystApp(AppBundleInformation appBundleInfo)
114+
Task<ExitCode> ExecuteMacCatalystApp(AppBundleInformation appBundleInfo)
115115
{
116116
appRunStarted = true;
117-
return ExecuteMacCatalystApp(
117+
return this.ExecuteMacCatalystApp(
118118
appBundleInfo,
119119
timeout,
120120
expectedExitCode,
@@ -124,10 +124,10 @@ Task<ExitCode> executeMacCatalystApp(AppBundleInformation appBundleInfo)
124124
cancellationToken);
125125
}
126126

127-
Task<ExitCode> executeApp(AppBundleInformation appBundleInfo, IDevice device, IDevice? companionDevice)
127+
Task<ExitCode> ExecuteApp(AppBundleInformation appBundleInfo, IDevice device, IDevice? companionDevice)
128128
{
129129
appRunStarted = true;
130-
return ExecuteApp(
130+
return this.ExecuteApp(
131131
appBundleInfo,
132132
target,
133133
device,
@@ -147,8 +147,8 @@ Task<ExitCode> executeApp(AppBundleInformation appBundleInfo, IDevice device, ID
147147
resetSimulator,
148148
enableLldb,
149149
appBundleInformation,
150-
executeMacCatalystApp,
151-
executeApp,
150+
ExecuteMacCatalystApp,
151+
ExecuteApp,
152152
launchTimeoutCancellationToken.Token);
153153
}
154154

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System;
6+
using System.Threading;
7+
using System.Threading.Tasks;
8+
using Microsoft.DotNet.XHarness.Common;
9+
using Microsoft.DotNet.XHarness.Common.CLI;
10+
using Microsoft.DotNet.XHarness.Common.Logging;
11+
using Microsoft.DotNet.XHarness.iOS.Shared;
12+
using Microsoft.DotNet.XHarness.iOS.Shared.Hardware;
13+
using Microsoft.DotNet.XHarness.iOS.Shared.Logging;
14+
using Microsoft.DotNet.XHarness.iOS.Shared.Utilities;
15+
16+
namespace Microsoft.DotNet.XHarness.Apple;
17+
18+
public interface ISimulatorResetOrchestrator
19+
{
20+
Task<ExitCode> OrchestrateSimulatorReset(
21+
TestTargetOs target,
22+
string? deviceName,
23+
TimeSpan timeout,
24+
CancellationToken cancellationToken);
25+
}
26+
27+
/// <summary>
28+
/// This orchestrator implements the `uninstall` command flow.
29+
/// </summary>
30+
public class SimulatorResetOrchestrator : BaseOrchestrator, ISimulatorResetOrchestrator
31+
{
32+
private readonly ILogger _consoleLogger;
33+
34+
public SimulatorResetOrchestrator(
35+
IAppInstaller appInstaller,
36+
IAppUninstaller appUninstaller,
37+
IDeviceFinder deviceFinder,
38+
ILogger consoleLogger,
39+
ILogs logs,
40+
IFileBackedLog mainLog,
41+
IErrorKnowledgeBase errorKnowledgeBase,
42+
IDiagnosticsData diagnosticsData,
43+
IHelpers helpers)
44+
: base(appInstaller, appUninstaller, deviceFinder, consoleLogger, logs, mainLog, errorKnowledgeBase, diagnosticsData, helpers)
45+
{
46+
_consoleLogger = consoleLogger;
47+
}
48+
49+
public Task<ExitCode> OrchestrateSimulatorReset(
50+
TestTargetOs target,
51+
string? deviceName,
52+
TimeSpan timeout,
53+
CancellationToken cancellationToken)
54+
{
55+
if (!target.Platform.IsSimulator() || target.Platform.ToRunMode() == RunMode.MacOS)
56+
{
57+
_consoleLogger.LogError($"The simulator reset action requires a simulator target while {target.AsString()} specified");
58+
return Task.FromResult(ExitCode.INVALID_ARGUMENTS);
59+
}
60+
61+
static Task<ExitCode> ExecuteMacCatalystApp(AppBundleInformation appBundleInfo)
62+
=> throw new InvalidOperationException("reset-simulator command not available on maccatalyst");
63+
64+
static Task<ExitCode> ExecuteApp(AppBundleInformation appBundleInfo, IDevice device, IDevice? companionDevice)
65+
=> Task.FromResult(ExitCode.SUCCESS); // no-op
66+
67+
return OrchestrateOperation(
68+
target,
69+
deviceName,
70+
includeWirelessDevices: false,
71+
resetSimulator: true,
72+
enableLldb: false,
73+
new AppBundleInformation(string.Empty, string.Empty, string.Empty, string.Empty, false),
74+
ExecuteMacCatalystApp,
75+
ExecuteApp,
76+
cancellationToken);
77+
}
78+
79+
protected override Task<ExitCode> InstallApp(AppBundleInformation appBundleInfo, IDevice device, TestTargetOs target, CancellationToken cancellationToken)
80+
=> Task.FromResult(ExitCode.SUCCESS); // no-op - we only want to reset the simulator
81+
82+
protected override Task<ExitCode> UninstallApp(TestTarget target, string bundleIdentifier, IDevice device, bool isPreparation, CancellationToken cancellationToken)
83+
=> Task.FromResult(ExitCode.SUCCESS); // no-op - we only want to reset the simulator
84+
85+
protected override Task CleanUpSimulators(IDevice device, IDevice? companionDevice)
86+
=> Task.CompletedTask; // no-op - reset is enough, clean-up is not needed afterwards
87+
}

src/Microsoft.DotNet.XHarness.Apple/Orchestration/TestOrchestrator.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,10 @@ public virtual async Task<ExitCode> OrchestrateTest(
111111
launchTimeoutCancellation.Token,
112112
cancellationToken);
113113

114-
Task<ExitCode> executeMacCatalystApp(AppBundleInformation appBundleInfo)
114+
Task<ExitCode> ExecuteMacCatalystApp(AppBundleInformation appBundleInfo)
115115
{
116116
appRunStarted = true;
117-
return ExecuteMacCatalystApp(
117+
return this.ExecuteMacCatalystApp(
118118
appBundleInfo,
119119
timeout,
120120
launchTimeout - watch.Elapsed,
@@ -128,10 +128,10 @@ Task<ExitCode> executeMacCatalystApp(AppBundleInformation appBundleInfo)
128128
cancellationToken);
129129
}
130130

131-
Task<ExitCode> executeApp(AppBundleInformation appBundleInfo, IDevice device, IDevice? companionDevice)
131+
Task<ExitCode> ExecuteApp(AppBundleInformation appBundleInfo, IDevice device, IDevice? companionDevice)
132132
{
133133
appRunStarted = true;
134-
return ExecuteApp(
134+
return this.ExecuteApp(
135135
appBundleInfo,
136136
target,
137137
device,
@@ -155,8 +155,8 @@ Task<ExitCode> executeApp(AppBundleInformation appBundleInfo, IDevice device, ID
155155
resetSimulator,
156156
enableLldb,
157157
appBundleInformation,
158-
executeMacCatalystApp,
159-
executeApp,
158+
ExecuteMacCatalystApp,
159+
ExecuteApp,
160160
launchTimeoutCancellationToken.Token);
161161
}
162162

src/Microsoft.DotNet.XHarness.Apple/Orchestration/UninstallOrchestrator.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,10 @@ public Task<ExitCode> OrchestrateAppUninstall(
5757
bool enableLldb,
5858
CancellationToken cancellationToken)
5959
{
60-
static Task<ExitCode> executeMacCatalystApp(AppBundleInformation appBundleInfo)
60+
static Task<ExitCode> ExecuteMacCatalystApp(AppBundleInformation appBundleInfo)
6161
=> throw new InvalidOperationException("uninstall command not available on maccatalyst");
6262

63-
static Task<ExitCode> executeApp(AppBundleInformation appBundleInfo, IDevice device, IDevice? companionDevice)
63+
static Task<ExitCode> ExecuteApp(AppBundleInformation appBundleInfo, IDevice device, IDevice? companionDevice)
6464
=> Task.FromResult(ExitCode.SUCCESS); // no-op
6565

6666
return OrchestrateOperation(
@@ -70,8 +70,8 @@ static Task<ExitCode> executeApp(AppBundleInformation appBundleInfo, IDevice dev
7070
resetSimulator,
7171
enableLldb,
7272
AppBundleInformation.FromBundleId(bundleIdentifier),
73-
executeMacCatalystApp,
74-
executeApp,
73+
ExecuteMacCatalystApp,
74+
ExecuteApp,
7575
cancellationToken);
7676
}
7777

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System;
6+
using System.Collections.Generic;
7+
8+
namespace Microsoft.DotNet.XHarness.CLI.CommandArguments.Apple;
9+
10+
internal class AppleResetSimulatorCommandArguments : XHarnessCommandArguments, IAppleAppRunArguments
11+
{
12+
public TargetArgument Target { get; } = new();
13+
public OutputDirectoryArgument OutputDirectory { get; } = new();
14+
public TimeoutArgument Timeout { get; } = new(TimeSpan.FromMinutes(10));
15+
public XcodeArgument XcodeRoot { get; } = new();
16+
public MlaunchArgument MlaunchPath { get; } = new();
17+
public DeviceNameArgument DeviceName { get; } = new();
18+
19+
protected override IEnumerable<Argument> GetArguments() => new Argument[]
20+
{
21+
Target,
22+
DeviceName,
23+
Timeout,
24+
OutputDirectory,
25+
XcodeRoot,
26+
MlaunchPath,
27+
};
28+
}

src/Microsoft.DotNet.XHarness.CLI/Commands/Apple/AppleCommandSet.cs

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,31 @@ namespace Microsoft.DotNet.XHarness.CLI.Commands.Apple;
1818
internal class AppleCommandSet : CommandSet
1919
{
2020
public AppleCommandSet() : base("apple")
21+
{
22+
var services = GetAppleDependencies();
23+
24+
// Commands for full install/execute/uninstall flows
25+
Add(new AppleTestCommand(services));
26+
Add(new AppleRunCommand(services));
27+
28+
// Commands for more fine grained control over the separate operations
29+
Add(new AppleInstallCommand(services));
30+
Add(new AppleUninstallCommand(services));
31+
Add(new AppleJustTestCommand(services));
32+
Add(new AppleJustRunCommand(services));
33+
34+
// Commands for getting information
35+
Add(new AppleGetDeviceCommand(services));
36+
Add(new AppleGetStateCommand());
37+
38+
// Commands for simulator management
39+
Add(new SimulatorsCommandSet());
40+
}
41+
42+
public static IServiceCollection GetAppleDependencies()
2143
{
2244
var services = new ServiceCollection();
45+
2346
services.TryAddSingleton<IAppBundleInformationParser, AppBundleInformationParser>();
2447
services.TryAddSingleton<ISimulatorLoader, SimulatorLoader>();
2548
services.TryAddSingleton<IHardwareDeviceLoader, HardwareDeviceLoader>();
@@ -48,22 +71,8 @@ public AppleCommandSet() : base("apple")
4871
services.TryAddTransient<IRunOrchestrator, RunOrchestrator>();
4972
services.TryAddTransient<ITestOrchestrator, TestOrchestrator>();
5073
services.TryAddTransient<IUninstallOrchestrator, UninstallOrchestrator>();
74+
services.TryAddTransient<ISimulatorResetOrchestrator, SimulatorResetOrchestrator>();
5175

52-
// Commands for full install/execute/uninstall flows
53-
Add(new AppleTestCommand(services));
54-
Add(new AppleRunCommand(services));
55-
56-
// Commands for more fine grained control over the separate operations
57-
Add(new AppleInstallCommand(services));
58-
Add(new AppleUninstallCommand(services));
59-
Add(new AppleJustTestCommand(services));
60-
Add(new AppleJustRunCommand(services));
61-
62-
// Commands for getting information
63-
Add(new AppleGetDeviceCommand(services));
64-
Add(new AppleGetStateCommand());
65-
66-
// Commands for simulator management
67-
Add(new SimulatorsCommandSet());
76+
return services;
6877
}
6978
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System.Threading;
6+
using System.Threading.Tasks;
7+
using Microsoft.DotNet.XHarness.Apple;
8+
using Microsoft.DotNet.XHarness.CLI.CommandArguments.Apple;
9+
using Microsoft.DotNet.XHarness.Common.CLI;
10+
using Microsoft.Extensions.DependencyInjection;
11+
12+
namespace Microsoft.DotNet.XHarness.CLI.Commands.Apple;
13+
14+
internal class AppleResetSimulatorCommand : AppleAppCommand<AppleResetSimulatorCommandArguments>
15+
{
16+
private const string CommandHelp = "Resets given iOS/tvOS simulator (wipes it clean)";
17+
18+
protected override AppleResetSimulatorCommandArguments Arguments { get; } = new();
19+
protected override string CommandUsage { get; } = "apple reset-simulator --target=... --output-directory=... [OPTIONS]";
20+
protected override string CommandDescription { get; } = CommandHelp;
21+
22+
public AppleResetSimulatorCommand(IServiceCollection services) : base("reset-simulator", false, services, CommandHelp)
23+
{
24+
}
25+
26+
protected override Task<ExitCode> InvokeInternal(ServiceProvider serviceProvider, CancellationToken cancellationToken) =>
27+
serviceProvider.GetRequiredService<ISimulatorResetOrchestrator>()
28+
.OrchestrateSimulatorReset(Arguments.Target, Arguments.DeviceName, Arguments.Timeout, cancellationToken);
29+
}

src/Microsoft.DotNet.XHarness.CLI/Commands/Apple/Simulators/SimulatorsCommandSet.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,6 @@ public SimulatorsCommandSet() : base("simulators")
1717
Add(new ListCommand());
1818
Add(new FindCommand());
1919
Add(new InstallCommand());
20+
Add(new AppleResetSimulatorCommand(AppleCommandSet.GetAppleDependencies()));
2021
}
2122
}

src/Microsoft.DotNet.XHarness.iOS.Shared/Hardware/SimulatorDevice.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.Collections.Generic;
77
using System.Diagnostics;
88
using System.IO;
9+
using System.Linq;
910
using System.Threading.Tasks;
1011
using Microsoft.DotNet.XHarness.Common.Logging;
1112
using Microsoft.DotNet.XHarness.iOS.Shared.Execution;
@@ -139,7 +140,7 @@ public async Task<bool> PrepareSimulator(ILog log, params string[] bundleIdentif
139140
}
140141

141142
var result = true;
142-
if (File.Exists(tccDB))
143+
if (bundleIdentifiers.Any() && File.Exists(tccDB))
143144
{
144145
result &= await _tCCDatabase.AgreeToPromptsAsync(SimRuntime, tccDB, UDID, log, bundleIdentifiers);
145146
}

0 commit comments

Comments
 (0)