Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add apple mlaunch command #844

Merged
merged 5 commits into from
Mar 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

namespace Microsoft.DotNet.XHarness.CLI.CommandArguments.Apple;

internal class AppleDeviceCommandsArguments : XHarnessCommandArguments, IAppleArguments
internal class AppleDeviceCommandArguments : XHarnessCommandArguments, IAppleArguments
{
public DeviceNameArgument DeviceName { get; } = new();
public IncludeWirelessArgument IncludeWireless { get; } = new();
Expand All @@ -15,9 +15,9 @@ internal class AppleDeviceCommandsArguments : XHarnessCommandArguments, IAppleAr

protected override IEnumerable<Argument> GetArguments() => new Argument[]
{
DeviceName,
IncludeWireless,
XcodeRoot,
MlaunchPath,
DeviceName,
IncludeWireless,
XcodeRoot,
MlaunchPath,
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;

namespace Microsoft.DotNet.XHarness.CLI.CommandArguments.Apple;

internal class AppleMlaunchCommandArguments : XHarnessCommandArguments, IAppleArguments
{
public MlaunchArgument MlaunchPath { get; } = new();
public XcodeArgument XcodeRoot { get; } = new();
public TimeoutArgument Timeout { get; set; } = new(TimeSpan.FromMinutes(2));
public EnvironmentalVariablesArgument EnvironmentalVariables { get; } = new();

protected override IEnumerable<Argument> GetArguments() => new Argument[]
{
MlaunchPath,
XcodeRoot,
Timeout,
EnvironmentalVariables,
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ namespace Microsoft.DotNet.XHarness.CLI.CommandArguments.Apple;
/// </summary>
internal class MlaunchArgument : Argument<string>
{
public MlaunchArgument() : base("mlaunch=", "Path to the mlaunch binary", MacOSProcessManager.DetectMlaunchPath())
public MlaunchArgument() : base("mlaunch=", "Path to the mlaunch binary. Defaults to mlaunch bundled with the XHarness nupkg", MacOSProcessManager.DetectMlaunchPath())
{
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace Microsoft.DotNet.XHarness.CLI.CommandArguments.Apple;
/// </summary>
internal class XcodeArgument : PathArgument
{
public XcodeArgument() : base("xcode=", "Path where Xcode is installed", false)
public XcodeArgument() : base("xcode=", "Path where Xcode is installed. If not provided, determined from xcode-select", false)
{
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public AppleCommandSet() : base("apple")

// Commands for getting information
Add(new AppleDeviceCommand(services));
Add(new AppleMlaunchCommand(services));
Add(new AppleStateCommand());

// Commands for simulator management
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@

namespace Microsoft.DotNet.XHarness.CLI.Commands.Apple;

internal class AppleDeviceCommand : AppleCommand<AppleDeviceCommandsArguments>
internal class AppleDeviceCommand : AppleCommand<AppleDeviceCommandArguments>
{
protected override AppleDeviceCommandsArguments Arguments { get; } = new();
protected override AppleDeviceCommandArguments Arguments { get; } = new();

protected override string CommandUsage { get; } = "apple device [OPTIONS] [TARGET]";

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.DotNet.XHarness.CLI.CommandArguments.Apple;
using Microsoft.DotNet.XHarness.Common.CLI;
using Microsoft.DotNet.XHarness.Common.Logging;
using Microsoft.DotNet.XHarness.iOS.Shared.Execution;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

namespace Microsoft.DotNet.XHarness.CLI.Commands.Apple;

internal class AppleMlaunchCommand : AppleCommand<AppleMlaunchCommandArguments>
{
private const string Description = "Invoke bundled mlaunch with given arguments";
protected override string CommandUsage { get; } = "apple mlaunch [OPTIONS] -- [MLAUNCH ARGUMENTS]";
protected override string CommandDescription => Description;

protected override AppleMlaunchCommandArguments Arguments { get; } = new();

public AppleMlaunchCommand(IServiceCollection services) : base("mlaunch", false, services, Description)
{
}

protected override async Task<ExitCode> Invoke(ILogger logger)
{
if (!PassThroughArguments.Any())
{
logger.LogError("Please provide delimeter '--' followed by arguments for ADB:" + Environment.NewLine +
$" {CommandUsage}" + Environment.NewLine +
$"Example:" + Environment.NewLine +
$" apple mlaunch --timeout 00:01:30 -- devices -l");

return ExitCode.INVALID_ARGUMENTS;
}

var processManager = Services.BuildServiceProvider().GetRequiredService<IMlaunchProcessManager>();

try
{
var nullLog = new CallbackLog(s => { });
var stdout = new CallbackLog(Console.Write);
var stderr = new CallbackLog(Console.Error.Write);

var args = new MlaunchArguments(PassThroughArguments.Select(arg => new SimpleMlaunchArgument(arg)).ToArray());

var cts = new CancellationTokenSource();
cts.CancelAfter(Arguments.Timeout);

var result = await processManager.ExecuteCommandAsync(
args,
Arguments.Verbosity < LogLevel.Information ? stdout : nullLog,
Arguments.Verbosity <= LogLevel.Warning ? stdout : nullLog,
stderr,
Arguments.Timeout,
Arguments.EnvironmentalVariables.Value.ToDictionary(t => t.Item1, t => t.Item2),
verbosity: 0, // -v needs to be supplied by user
cts.Token);

if (result.TimedOut)
{
return ExitCode.TIMED_OUT;
}

return (ExitCode)result.ExitCode;
}
catch (Exception e)
{
logger.LogError(e.ToString());
return ExitCode.GENERAL_FAILURE;
}
}

// This is needed because ProcessManagers accepts MlaunchArguments only which are strong-typed args supported by mlaunch
// Since in this command, these are supplied by user, we need to forward them as-is
private class SimpleMlaunchArgument : iOS.Shared.Execution.MlaunchArgument
{
private readonly string _argument;

public SimpleMlaunchArgument(string argument)
{
_argument = argument;
}

public override string AsCommandLineArgument() => Escape(_argument);
}
}
40 changes: 20 additions & 20 deletions src/Microsoft.DotNet.XHarness.CLI/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,26 +96,26 @@ private static bool IsOutputSensitive(string[] args)
return false;
}

switch (args[0])
{
case "apple":
return args[1] switch
{
"device" => true,
"state" => args.Contains("--json"),
_ => false,
};

case "android":
return args[1] switch
{
"device" => true,
"state" => args.Contains("--json"),
"adb" => true,
_ => false,
};
}
var platform = args[0];
var command = args[1];

return false;
return platform switch
{
"apple" => command switch
{
"device" => true,
"state" => args.Contains("--json"),
"mlaunch" => true,
_ => false,
},
"android" => command switch
{
"device" => true,
"state" => args.Contains("--json"),
"adb" => true,
_ => false,
},
_ => false,
};
}
}