Merge pull request #5699 from krwq/2017-02-13-psi-extraction

Unit tests for dotnet build
This commit is contained in:
Livar 2017-02-19 09:57:07 -08:00 committed by GitHub
commit 99f7eb4843
10 changed files with 261 additions and 32 deletions

View file

@ -67,6 +67,11 @@ namespace Microsoft.DotNet.Cli
}
public int Execute()
{
return GetProcessStartInfo().Execute();
}
public ProcessStartInfo GetProcessStartInfo()
{
var processInfo = new ProcessStartInfo
{
@ -83,15 +88,7 @@ namespace Microsoft.DotNet.Cli
}
}
var process = new Process
{
StartInfo = processInfo
};
process.Start();
process.WaitForExit();
return process.ExitCode;
return processInfo;
}
public ForwardingApp WithEnvironmentVariable(string name, string value)

View file

@ -0,0 +1,26 @@
using System;
using System.Diagnostics;
namespace Microsoft.DotNet.Cli
{
internal static class ProcessStartInfoExtensions
{
public static int Execute(this ProcessStartInfo startInfo)
{
if (startInfo == null)
{
throw new ArgumentNullException(nameof(startInfo));
}
var process = new Process
{
StartInfo = startInfo
};
process.Start();
process.WaitForExit();
return process.ExitCode;
}
}
}

View file

@ -5,21 +5,29 @@ using System.Collections.Generic;
using Microsoft.DotNet.Cli.CommandLine;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.Tools.MSBuild;
using System.Diagnostics;
using System;
using Microsoft.DotNet.Cli;
namespace Microsoft.DotNet.Tools.Build
{
public class BuildCommand
{
public static int Run(string[] args)
{
DebugHelper.HandleDebugSwitch(ref args);
private MSBuildForwardingApp _forwardingApp;
public BuildCommand(IEnumerable<string> msbuildArgs, string msbuildPath = null)
{
_forwardingApp = new MSBuildForwardingApp(msbuildArgs, msbuildPath);
}
public static BuildCommand FromArgs(string[] args, string msbuildPath = null)
{
CommandLineApplication app = new CommandLineApplication(throwOnUnexpectedArg: false);
app.Name = "dotnet build";
app.FullName = LocalizableStrings.AppFullName;
app.Description = LocalizableStrings.AppDescription;
app.ArgumentSeparatorHelpText = HelpMessageStrings.MSBuildAdditionalArgsHelpText;
app.HandleRemainingArguments = true;
app.HandleRemainingArguments = true;
app.HelpOption("-h|--help");
CommandArgument projectArgument = app.Argument($"<{LocalizableStrings.ProjectArgumentValueName}>", LocalizableStrings.ProjectArgumentDescription);
@ -36,9 +44,12 @@ namespace Microsoft.DotNet.Tools.Build
CommandOption noDependenciesOption = app.Option("--no-dependencies", LocalizableStrings.NoDependenciesOptionDescription, CommandOptionType.NoValue);
CommandOption verbosityOption = MSBuildForwardingApp.AddVerbosityOption(app);
List<string> msbuildArgs = null;
app.OnExecute(() =>
{
List<string> msbuildArgs = new List<string>();
// this delayed initialization is here intentionally
// this code will not get run in some cases (i.e. --help)
msbuildArgs = new List<string>();
if (!string.IsNullOrEmpty(projectArgument.Value))
{
@ -93,10 +104,53 @@ namespace Microsoft.DotNet.Tools.Build
msbuildArgs.AddRange(app.RemainingArguments);
return new MSBuildForwardingApp(msbuildArgs).Execute();
return 0;
});
return app.Execute(args);
int exitCode = app.Execute(args);
if (msbuildArgs == null)
{
throw new CommandCreationException(exitCode);
}
return new BuildCommand(msbuildArgs, msbuildPath);
}
public static int Run(string[] args)
{
DebugHelper.HandleDebugSwitch(ref args);
BuildCommand cmd;
try
{
cmd = FromArgs(args);
}
catch (CommandCreationException e)
{
return e.ExitCode;
}
return cmd.Execute();
}
public ProcessStartInfo GetProcessStartInfo()
{
return _forwardingApp.GetProcessStartInfo();
}
public int Execute()
{
return GetProcessStartInfo().Execute();
}
private class CommandCreationException : Exception
{
public int ExitCode { get; private set; }
public CommandCreationException(int exitCode)
{
ExitCode = exitCode;
}
}
}
}

View file

@ -9,6 +9,7 @@ using System.Reflection;
using System.Runtime.InteropServices;
using Microsoft.DotNet.Cli;
using Microsoft.DotNet.Cli.CommandLine;
using System.Diagnostics;
namespace Microsoft.DotNet.Tools.MSBuild
{
@ -33,7 +34,7 @@ namespace Microsoft.DotNet.Tools.MSBuild
private readonly IEnumerable<string> _msbuildRequiredParameters =
new List<string> { "/m", "/v:m" };
public MSBuildForwardingApp(IEnumerable<string> argsToForward)
public MSBuildForwardingApp(IEnumerable<string> argsToForward, string msbuildPath = null)
{
if (Telemetry.CurrentSessionId != null)
{
@ -54,23 +55,21 @@ namespace Microsoft.DotNet.Tools.MSBuild
}
_forwardingApp = new ForwardingApp(
GetMSBuildExePath(),
msbuildPath ?? GetMSBuildExePath(),
_msbuildRequiredParameters.Concat(argsToForward.Select(Escape)),
environmentVariables: _msbuildRequiredEnvironmentVariables);
}
public ProcessStartInfo GetProcessStartInfo()
{
return _forwardingApp
.WithEnvironmentVariable(TelemetrySessionIdEnvironmentVariableName, Telemetry.CurrentSessionId)
.GetProcessStartInfo();
}
public int Execute()
{
try
{
Environment.SetEnvironmentVariable(TelemetrySessionIdEnvironmentVariableName, Telemetry.CurrentSessionId);
return _forwardingApp.Execute();
}
finally
{
Environment.SetEnvironmentVariable(TelemetrySessionIdEnvironmentVariableName, null);
}
return GetProcessStartInfo().Execute();
}
internal static CommandOption AddVerbosityOption(CommandLineApplication app)

View file

@ -1,3 +1,6 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using Microsoft.DotNet.PlatformAbstractions;
using Xunit;
@ -9,7 +12,7 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
{
if (RuntimeEnvironment.OperatingSystemPlatform == Platform.Windows)
{
this.Skip = "This test requires windows to run";
this.Skip = "This test requires non-Windows to run";
}
}
}

View file

@ -0,0 +1,19 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using Microsoft.DotNet.PlatformAbstractions;
using Xunit;
namespace Microsoft.DotNet.Tools.Test.Utilities
{
public class NonWindowsOnlyTheoryAttribute : TheoryAttribute
{
public NonWindowsOnlyTheoryAttribute()
{
if (RuntimeEnvironment.OperatingSystemPlatform == Platform.Windows)
{
this.Skip = "This test requires non-Windows to run";
}
}
}
}

View file

@ -12,7 +12,7 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
{
if (RuntimeEnvironment.OperatingSystemPlatform != Platform.Windows)
{
this.Skip = "This test requires windows to run";
this.Skip = "This test requires Windows to run";
}
}
}

View file

@ -1,4 +1,7 @@
using Microsoft.DotNet.PlatformAbstractions;
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using Microsoft.DotNet.PlatformAbstractions;
using Xunit;
namespace Microsoft.DotNet.Tools.Test.Utilities
@ -9,7 +12,7 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
{
if (RuntimeEnvironment.OperatingSystemPlatform != Platform.Windows)
{
this.Skip = "This test requires windows to run";
this.Skip = "This test requires Windows to run";
}
}
}

View file

@ -0,0 +1,33 @@
using Microsoft.DotNet.Tools.Build;
using FluentAssertions;
using Xunit;
namespace Microsoft.DotNet.Cli.MSBuild.Tests
{
public class GivenDotnetBuildInvocation
{
[Theory]
[InlineData(new string[] { }, @"exec <msbuildpath> /m /v:m /t:Build /clp:Summary")]
[InlineData(new string[] { "-o", "foo" }, @"exec <msbuildpath> /m /v:m /t:Build /p:OutputPath=foo /clp:Summary")]
[InlineData(new string[] { "--output", "foo" }, @"exec <msbuildpath> /m /v:m /t:Build /p:OutputPath=foo /clp:Summary")]
[InlineData(new string[] { "-o", "foo1 foo2" }, @"exec <msbuildpath> /m /v:m /t:Build ""/p:OutputPath=foo1 foo2"" /clp:Summary")]
[InlineData(new string[] { "--no-incremental" }, @"exec <msbuildpath> /m /v:m /t:Rebuild /clp:Summary")]
[InlineData(new string[] { "-f", "framework" }, @"exec <msbuildpath> /m /v:m /t:Build /p:TargetFramework=framework /clp:Summary")]
[InlineData(new string[] { "--framework", "framework" }, @"exec <msbuildpath> /m /v:m /t:Build /p:TargetFramework=framework /clp:Summary")]
[InlineData(new string[] { "-r", "runtime" }, @"exec <msbuildpath> /m /v:m /t:Build /p:RuntimeIdentifier=runtime /clp:Summary")]
[InlineData(new string[] { "--runtime", "runtime" }, @"exec <msbuildpath> /m /v:m /t:Build /p:RuntimeIdentifier=runtime /clp:Summary")]
[InlineData(new string[] { "-c", "configuration" }, @"exec <msbuildpath> /m /v:m /t:Build /p:Configuration=configuration /clp:Summary")]
[InlineData(new string[] { "--configuration", "configuration" }, @"exec <msbuildpath> /m /v:m /t:Build /p:Configuration=configuration /clp:Summary")]
[InlineData(new string[] { "--version-suffix", "mysuffix" }, @"exec <msbuildpath> /m /v:m /t:Build /p:VersionSuffix=mysuffix /clp:Summary")]
[InlineData(new string[] { "--no-dependencies" }, @"exec <msbuildpath> /m /v:m /t:Build /p:BuildProjectReferences=false /clp:Summary")]
[InlineData(new string[] { "-v", "verbosity" }, @"exec <msbuildpath> /m /v:m /t:Build /verbosity:verbosity /clp:Summary")]
[InlineData(new string[] { "--verbosity", "verbosity" }, @"exec <msbuildpath> /m /v:m /t:Build /verbosity:verbosity /clp:Summary")]
[InlineData(new string[] { "--no-incremental", "-o", "myoutput", "-r", "myruntime", "-v", "diag" }, @"exec <msbuildpath> /m /v:m /t:Rebuild /p:OutputPath=myoutput /p:RuntimeIdentifier=myruntime /verbosity:diag /clp:Summary")]
public void MsbuildInvocationIsCorrect(string[] args, string expectedCommand)
{
var msbuildPath = "<msbuildpath>";
BuildCommand.FromArgs(args, msbuildPath)
.GetProcessStartInfo().Arguments.Should().Be(expectedCommand);
}
}
}

View file

@ -0,0 +1,95 @@
using System.IO;
using Microsoft.DotNet.Tools.MSBuild;
using FluentAssertions;
using Xunit;
using static Microsoft.DotNet.Tools.Test.Utilities.DirectoryInfoExtensions;
using WindowsOnlyFactAttribute = Microsoft.DotNet.Tools.Test.Utilities.WindowsOnlyFactAttribute;
using NonWindowsOnlyFactAttribute = Microsoft.DotNet.Tools.Test.Utilities.NonWindowsOnlyFactAttribute;
namespace Microsoft.DotNet.Cli.MSBuild.Tests
{
public class GivenMsbuildForwardingApp
{
[WindowsOnlyFact]
public void DotnetExeIsExecuted()
{
var msbuildPath = "<msbuildpath>";
new MSBuildForwardingApp(new string[0], msbuildPath)
.GetProcessStartInfo().FileName.Should().Be("dotnet.exe");
}
[NonWindowsOnlyFact]
public void DotnetIsExecuted()
{
var msbuildPath = "<msbuildpath>";
new MSBuildForwardingApp(new string[0], msbuildPath)
.GetProcessStartInfo().FileName.Should().Be("dotnet");
}
[Theory]
[InlineData("MSBuildExtensionsPath")]
[InlineData("CscToolExe")]
[InlineData("MSBuildSDKsPath")]
[InlineData("DOTNET_CLI_TELEMETRY_SESSIONID")]
public void ItSetsEnvironmentalVariables(string envVarName)
{
var msbuildPath = "<msbuildpath>";
var startInfo = new MSBuildForwardingApp(new string[0], msbuildPath).GetProcessStartInfo();
startInfo.Environment.ContainsKey(envVarName).Should().BeTrue();
}
[Fact]
public void ItSetsMSBuildExtensionPathToExistingPath()
{
var msbuildPath = "<msbuildpath>";
var envVar = "MSBuildExtensionsPath";
new DirectoryInfo(new MSBuildForwardingApp(new string[0], msbuildPath)
.GetProcessStartInfo()
.Environment[envVar])
.Should()
.Exist();
}
[Fact]
public void ItSetsMSBuildSDKsPathToExistingPath()
{
var msbuildPath = "<msbuildpath>";
var envVar = "MSBuildSDKsPath";
new DirectoryInfo(new MSBuildForwardingApp(new string[0], msbuildPath)
.GetProcessStartInfo()
.Environment[envVar])
.Should()
.Exist();
}
[Fact]
public void ItSetsCscToolExePathToValidPath()
{
var msbuildPath = "<msbuildpath>";
var envVar = "CscToolExe";
new FileInfo(new MSBuildForwardingApp(new string[0], msbuildPath)
.GetProcessStartInfo()
.Environment[envVar])
.Should().NotBeNull("constructor will throw on invalid path");
}
[Fact]
public void ItSetsOrIgnoresTelemetrySessionId()
{
var msbuildPath = "<msbuildpath>";
var envVar = "DOTNET_CLI_TELEMETRY_SESSIONID";
var startInfo = new MSBuildForwardingApp(new string[0], msbuildPath)
.GetProcessStartInfo();
(startInfo.Environment[envVar] == null || int.TryParse(startInfo.Environment[envVar], out _))
.Should().BeTrue("DOTNET_CLI_TELEMETRY_SESSIONID should be null or current session id");
}
[Fact]
public void ItDoesNotSetCurrentWorkingDirectory()
{
var msbuildPath = "<msbuildpath>";
var startInfo = new MSBuildForwardingApp(new string[0], msbuildPath)
.GetProcessStartInfo().WorkingDirectory.Should().Be("");
}
}
}