Skip to content

Add NativeAOT test #1656

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

Merged
merged 15 commits into from
Mar 16, 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
2 changes: 2 additions & 0 deletions NuGet.config
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
<add key="dotnet-eng" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json" />
<add key="dotnet-tools" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json" />
<add key="dotnet-libraries" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-libraries/nuget/v3/index.json" />
<!-- required by NativeAOT -->
<add key="dotnet7" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet7/nuget/v3/index.json" />
</packageSources>
<disabledPackageSources />
</configuration>
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,18 @@
using System.IO;
using System.Text;
using FluentAssertions;
using Microsoft.DotNet.PlatformAbstractions;
using Xunit;
using Xunit.Abstractions;

namespace System.CommandLine.Tests;

public class TrimmingTests
public class CompilationTests
{
private readonly ITestOutputHelper _output;
private readonly string _systemCommandLineDllPath;

public TrimmingTests(ITestOutputHelper output)
public CompilationTests(ITestOutputHelper output)
{
_output = output;

Expand All @@ -29,25 +30,35 @@ public TrimmingTests(ITestOutputHelper output)
[InlineData("")]
[InlineData("-p:PublishSingleFile=true")]
public void App_referencing_system_commandline_can_be_trimmed(string additionalArgs)
=> PublishAndValidate("Trimming", "warning IL", additionalArgs);

[ReleaseBuildOnlyFact]
public void App_referencing_system_commandline_can_be_compiled_ahead_of_time()
=> PublishAndValidate("NativeAOT", "AOT analysis warning");

private void PublishAndValidate(string appName, string warningText, string additionalArgs = null)
{
var stdOut = new StringBuilder();
var stdErr = new StringBuilder();

var workingDirectory = Path.Combine(Directory.GetCurrentDirectory(), "TrimmingTestApp");

var workingDirectory = Path.Combine(Directory.GetCurrentDirectory(), "TestApps", appName);

string rId = GetPortableRuntimeIdentifier();

Process.RunToCompletion(
DotnetMuxer.Path.FullName,
"clean -c Release -r win-x64",
$"clean -c Release -r {rId}",
workingDirectory: workingDirectory);

var commandLine = string.Format(
"publish -c Release -r win-x64 --self-contained -p:SystemCommandLineDllPath=\"{0}\" -p:TreatWarningsAsErrors=true -p:PublishTrimmed=true {1}",
string publishCommand = string.Format(
"publish -c Release -r {0} --self-contained -p:SystemCommandLineDllPath=\"{1}\" -p:TreatWarningsAsErrors=true {2}",
rId,
_systemCommandLineDllPath,
additionalArgs);

var exitCode = Process.RunToCompletion(
DotnetMuxer.Path.FullName,
commandLine,
publishCommand,
s =>
{
_output.WriteLine(s);
Expand All @@ -60,10 +71,16 @@ public void App_referencing_system_commandline_can_be_trimmed(string additionalA
},
workingDirectory);

stdOut.ToString().Should().NotContain("warning IL");
stdOut.ToString().Should().NotContain(warningText);
stdErr.ToString().Should().BeEmpty();
exitCode.Should().Be(0);
}

private static string GetPortableRuntimeIdentifier()
{
string osPart = OperatingSystem.IsWindows() ? "win" : (OperatingSystem.IsMacOS() ? "osx" : "linux");
return $"{osPart}-{RuntimeEnvironment.RuntimeArchitecture}";
}
}

#endif
13 changes: 6 additions & 7 deletions src/System.CommandLine.Tests/System.CommandLine.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,15 @@
<EmbeddedResource Remove="TestResults\**" />
<None Remove="TestResults\**" />

<Compile Remove="TrimmingTestApp/**" />
<Content Remove="TrimmingTestApp/**" />
<EmbeddedResource Remove="TrimmingTestApp/**" />
<None Remove="TrimmingTestApp/**" />
<Compile Remove="TestApps/**" />
<Content Remove="TestApps/**" />
<EmbeddedResource Remove="TestApps/**" />
<None Remove="TestApps/**" />


<Content Include="TrimmingTestApp/TrimmingTestApp.csproj">
<Content Include="TestApps/**/*.csproj">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="TrimmingTestApp/Program.cs">
<Content Include="TestApps/**/*.cs">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>

Expand Down
21 changes: 21 additions & 0 deletions src/System.CommandLine.Tests/TestApps/NativeAOT/NativeAOT.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<!-- producing more detailed log output -->
<TrimmerSingleWarn>false</TrimmerSingleWarn>
</PropertyGroup>

<PropertyGroup>
<SystemCommandLineDllPath Condition="'$(SystemCommandLineDllPath)'==''">..\..\..\System.CommandLine\bin\Release\net6.0\System.CommandLine.dll</SystemCommandLineDllPath>
</PropertyGroup>

<ItemGroup>
<Reference Include="SystemCommandLineDll">
<HintPath>$(SystemCommandLineDllPath)</HintPath>
</Reference>
<PackageReference Include="Microsoft.DotNet.ILCompiler" Version="7.0.0-preview.3.22123.2" />
</ItemGroup>

</Project>
29 changes: 29 additions & 0 deletions src/System.CommandLine.Tests/TestApps/NativeAOT/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using System;
using System.CommandLine;
using System.CommandLine.Builder;
using System.CommandLine.Parsing;

public class Program
{
static void Run(bool boolean, string text)
{
Console.WriteLine($"Bool option: {text}");
Console.WriteLine($"String option: {boolean}");
}

private static int Main(string[] args)
{
Option<bool> boolOption = new Option<bool>(new[] { "--bool", "-b" }, "Bool option");
Option<string> stringOption = new Option<string>(new[] { "--string", "-s" }, "String option");

RootCommand command = new RootCommand
{
boolOption,
stringOption
};

command.SetHandler<bool, string>(Run, boolOption, stringOption);

return new CommandLineBuilder(command).Build().Invoke(args);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
</PropertyGroup>

<PropertyGroup>
<SystemCommandLineDllPath Condition="'$(SystemCommandLineDllPath)'==''">..\..\System.CommandLine\bin\Release\net6.0\System.CommandLine.dll</SystemCommandLineDllPath>
<SystemCommandLineDllPath Condition="'$(SystemCommandLineDllPath)'==''">..\..\..\System.CommandLine\bin\Release\net6.0\System.CommandLine.dll</SystemCommandLineDllPath>
</PropertyGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ internal static partial class ArgumentConverter
private static ConstructorInfo? _listCtor;
#endif

private static Array CreateEmptyArray(Type itemType, int capacity = 0)
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL3050", Justification = "https://github.com/dotnet/command-line-api/issues/1638")]
private static Array CreateArray(Type itemType, int capacity)
=> Array.CreateInstance(itemType, capacity);

private static IList CreateEmptyList(Type listType)
Expand All @@ -40,18 +41,18 @@ private static IList CreateEnumerable(Type type, Type itemType, int capacity = 0
{
if (type.IsArray)
{
return CreateEmptyArray(itemType, capacity);
return CreateArray(itemType, capacity);
}

if (type.IsGenericType)
{
var x = type.GetGenericTypeDefinition() switch
{
{ } enumerable when typeof(IEnumerable<>).IsAssignableFrom(enumerable) =>
CreateEmptyArray(itemType, capacity),
CreateArray(itemType, capacity),
{ } array when typeof(IList<>).IsAssignableFrom(array) ||
typeof(ICollection<>).IsAssignableFrom(array) =>
CreateEmptyArray(itemType, capacity),
CreateArray(itemType, capacity),
{ } list when list == typeof(List<>) =>
CreateEmptyList(type),
_ => null
Expand Down
2 changes: 1 addition & 1 deletion src/System.CommandLine/Binding/ArgumentConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ public static bool TryConvertArgument(ArgumentResult argumentResult, out object?
when nonGeneric == typeof(IList) ||
nonGeneric == typeof(ICollection) ||
nonGeneric == typeof(IEnumerable)
=> CreateEmptyArray(typeof(object)),
=> Array.Empty<object>(),
_ when type.IsValueType => CreateDefaultValueType(type),
_ => null
};
Expand Down
23 changes: 0 additions & 23 deletions src/System.CommandLine/Binding/TypeDefaultValueSource.cs

This file was deleted.