diff --git a/Microsoft.DotNet.Cli.sln b/Microsoft.DotNet.Cli.sln
index 0748db81a..6e03ba1ff 100644
--- a/Microsoft.DotNet.Cli.sln
+++ b/Microsoft.DotNet.Cli.sln
@@ -232,6 +232,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.ShellShim.
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.ToolPackage.Tests", "test\Microsoft.DotNet.ToolPackage.Tests\Microsoft.DotNet.ToolPackage.Tests.csproj", "{91BFE800-1624-4A58-A1CE-339705A8FFD0}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.Tools.Tests.ComponentMocks", "test\Microsoft.DotNet.Tools.Tests.ComponentMocks\Microsoft.DotNet.Tools.Tests.ComponentMocks.csproj", "{E442F4C1-08DB-470F-B9A6-197444CD0295}"
+EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "tool_launcher", "src\tool_launcher\tool_launcher.csproj", "{EDF19BE6-F20F-4AD0-8E3B-E837030726A5}"
EndProject
Global
@@ -1666,6 +1668,30 @@ Global
{EDF19BE6-F20F-4AD0-8E3B-E837030726A5}.RelWithDebInfo|x64.Build.0 = Release|Any CPU
{EDF19BE6-F20F-4AD0-8E3B-E837030726A5}.RelWithDebInfo|x86.ActiveCfg = Release|Any CPU
{EDF19BE6-F20F-4AD0-8E3B-E837030726A5}.RelWithDebInfo|x86.Build.0 = Release|Any CPU
+ {E442F4C1-08DB-470F-B9A6-197444CD0295}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E442F4C1-08DB-470F-B9A6-197444CD0295}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E442F4C1-08DB-470F-B9A6-197444CD0295}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {E442F4C1-08DB-470F-B9A6-197444CD0295}.Debug|x64.Build.0 = Debug|Any CPU
+ {E442F4C1-08DB-470F-B9A6-197444CD0295}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {E442F4C1-08DB-470F-B9A6-197444CD0295}.Debug|x86.Build.0 = Debug|Any CPU
+ {E442F4C1-08DB-470F-B9A6-197444CD0295}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU
+ {E442F4C1-08DB-470F-B9A6-197444CD0295}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU
+ {E442F4C1-08DB-470F-B9A6-197444CD0295}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU
+ {E442F4C1-08DB-470F-B9A6-197444CD0295}.MinSizeRel|x64.Build.0 = Debug|Any CPU
+ {E442F4C1-08DB-470F-B9A6-197444CD0295}.MinSizeRel|x86.ActiveCfg = Debug|Any CPU
+ {E442F4C1-08DB-470F-B9A6-197444CD0295}.MinSizeRel|x86.Build.0 = Debug|Any CPU
+ {E442F4C1-08DB-470F-B9A6-197444CD0295}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E442F4C1-08DB-470F-B9A6-197444CD0295}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E442F4C1-08DB-470F-B9A6-197444CD0295}.Release|x64.ActiveCfg = Release|Any CPU
+ {E442F4C1-08DB-470F-B9A6-197444CD0295}.Release|x64.Build.0 = Release|Any CPU
+ {E442F4C1-08DB-470F-B9A6-197444CD0295}.Release|x86.ActiveCfg = Release|Any CPU
+ {E442F4C1-08DB-470F-B9A6-197444CD0295}.Release|x86.Build.0 = Release|Any CPU
+ {E442F4C1-08DB-470F-B9A6-197444CD0295}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU
+ {E442F4C1-08DB-470F-B9A6-197444CD0295}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU
+ {E442F4C1-08DB-470F-B9A6-197444CD0295}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU
+ {E442F4C1-08DB-470F-B9A6-197444CD0295}.RelWithDebInfo|x64.Build.0 = Release|Any CPU
+ {E442F4C1-08DB-470F-B9A6-197444CD0295}.RelWithDebInfo|x86.ActiveCfg = Release|Any CPU
+ {E442F4C1-08DB-470F-B9A6-197444CD0295}.RelWithDebInfo|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -1740,6 +1766,7 @@ Global
{E84C08C9-70D7-48B0-9507-ADB8B9A2694C} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7}
{91BFE800-1624-4A58-A1CE-339705A8FFD0} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7}
{EDF19BE6-F20F-4AD0-8E3B-E837030726A5} = {ED2FE3E2-F7E7-4389-8231-B65123F2076F}
+ {E442F4C1-08DB-470F-B9A6-197444CD0295} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {B526D2CE-EE2D-4AD4-93EF-1867D90FF1F5}
diff --git a/build/test/TestProjects.targets b/build/test/TestProjects.targets
index 8a5d21a55..96b08c34d 100644
--- a/build/test/TestProjects.targets
+++ b/build/test/TestProjects.targets
@@ -15,6 +15,7 @@
diff --git a/src/Microsoft.DotNet.InternalAbstractions/Properties/Properties.cs b/src/Microsoft.DotNet.InternalAbstractions/Properties/Properties.cs
index 4b08b51db..ecdec5b5d 100644
--- a/src/Microsoft.DotNet.InternalAbstractions/Properties/Properties.cs
+++ b/src/Microsoft.DotNet.InternalAbstractions/Properties/Properties.cs
@@ -8,6 +8,7 @@ using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("Microsoft.Extensions.DependencyModel, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
[assembly: InternalsVisibleTo("dotnet, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
[assembly: InternalsVisibleTo("Microsoft.DotNet.Tools.Tests.Utilities, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
+[assembly: InternalsVisibleTo("Microsoft.DotNet.Tools.Tests.ComponentMocks, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
[assembly: InternalsVisibleTo("Microsoft.Extensions.DependencyModel.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
[assembly: InternalsVisibleTo("Microsoft.DotNet.Configurer, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
[assembly: InternalsVisibleTo("Microsoft.DotNet.Configurer.UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
@@ -15,3 +16,5 @@ using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("dotnet-test.UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100039ac461fa5c82c7dd2557400c4fd4e9dcdf7ac47e3d572548c04cd4673e004916610f4ea5cbf86f2b1ca1cb824f2a7b3976afecfcf4eb72d9a899aa6786effa10c30399e6580ed848231fec48374e41b3acf8811931343fc2f73acf72dae745adbcb7063cc4b50550618383202875223fc75401351cd89c44bf9b50e7fa3796")]
[assembly: InternalsVisibleTo("Microsoft.DotNet.Tools.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
[assembly: InternalsVisibleTo("Microsoft.DotNet.ShellShim.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
+[assembly: InternalsVisibleTo("Microsoft.DotNet.ToolPackage.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
+[assembly: InternalsVisibleTo("dotnet.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
diff --git a/src/dotnet/Properties/AssemblyInfo.cs b/src/dotnet/Properties/AssemblyInfo.cs
index 249576dc2..25bd8cb8c 100644
--- a/src/dotnet/Properties/AssemblyInfo.cs
+++ b/src/dotnet/Properties/AssemblyInfo.cs
@@ -17,5 +17,7 @@ using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("dotnet-sln-remove.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
[assembly: InternalsVisibleTo("dotnet-msbuild.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
[assembly: InternalsVisibleTo("dotnet-run.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
+[assembly: InternalsVisibleTo("Microsoft.DotNet.Tools.Tests.Utilities, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
+[assembly: InternalsVisibleTo("Microsoft.DotNet.Tools.Tests.ComponentMocks, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
[assembly: InternalsVisibleTo("Microsoft.DotNet.ToolPackage.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
[assembly: InternalsVisibleTo("Microsoft.DotNet.ShellShim.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
diff --git a/src/dotnet/ShellShim/IShellShimMaker.cs b/src/dotnet/ShellShim/IShellShimMaker.cs
new file mode 100644
index 000000000..35ff02493
--- /dev/null
+++ b/src/dotnet/ShellShim/IShellShimMaker.cs
@@ -0,0 +1,8 @@
+namespace Microsoft.DotNet.ShellShim
+{
+ public interface IShellShimMaker
+ {
+ void CreateShim(string packageExecutablePath, string shellCommandName);
+ void EnsureCommandNameUniqueness(string shellCommandName);
+ }
+}
diff --git a/src/dotnet/ShellShim/ShellShimMaker.cs b/src/dotnet/ShellShim/ShellShimMaker.cs
index bf204a1ef..f3247c620 100644
--- a/src/dotnet/ShellShim/ShellShimMaker.cs
+++ b/src/dotnet/ShellShim/ShellShimMaker.cs
@@ -13,7 +13,7 @@ using Microsoft.Extensions.EnvironmentAbstractions;
namespace Microsoft.DotNet.ShellShim
{
- public class ShellShimMaker
+ public class ShellShimMaker : IShellShimMaker
{
private const string LauncherExeResourceName = "Microsoft.DotNet.Tools.Launcher.Executable";
private const string LauncherConfigResourceName = "Microsoft.DotNet.Tools.Launcher.Config";
diff --git a/src/dotnet/ToolPackage/IToolPackageObtainer.cs b/src/dotnet/ToolPackage/IToolPackageObtainer.cs
new file mode 100644
index 000000000..e48694f9e
--- /dev/null
+++ b/src/dotnet/ToolPackage/IToolPackageObtainer.cs
@@ -0,0 +1,17 @@
+// 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.Extensions.EnvironmentAbstractions;
+
+namespace Microsoft.DotNet.ToolPackage
+{
+ internal interface IToolPackageObtainer
+ {
+ ToolConfigurationAndExecutablePath ObtainAndReturnExecutablePath(
+ string packageId,
+ string packageVersion = null,
+ FilePath? nugetconfig = null,
+ string targetframework = null,
+ string source = null);
+ }
+}
diff --git a/src/dotnet/ToolPackage/ToolPackageObtainer.cs b/src/dotnet/ToolPackage/ToolPackageObtainer.cs
index 151fe83e7..3ef3597b0 100644
--- a/src/dotnet/ToolPackage/ToolPackageObtainer.cs
+++ b/src/dotnet/ToolPackage/ToolPackageObtainer.cs
@@ -10,7 +10,7 @@ using NuGet.ProjectModel;
namespace Microsoft.DotNet.ToolPackage
{
- internal class ToolPackageObtainer
+ internal class ToolPackageObtainer : IToolPackageObtainer
{
private readonly Lazy _bundledTargetFrameworkMoniker;
private readonly Func _getTempProjectPath;
diff --git a/src/dotnet/commands/dotnet-install/dotnet-install-tool/InstallToolCommand.cs b/src/dotnet/commands/dotnet-install/dotnet-install-tool/InstallToolCommand.cs
index 276a681f5..783666939 100644
--- a/src/dotnet/commands/dotnet-install/dotnet-install-tool/InstallToolCommand.cs
+++ b/src/dotnet/commands/dotnet-install/dotnet-install-tool/InstallToolCommand.cs
@@ -14,18 +14,27 @@ using Microsoft.Extensions.EnvironmentAbstractions;
namespace Microsoft.DotNet.Tools.Install.Tool
{
- public class InstallToolCommand : CommandBase
+ internal class InstallToolCommand : CommandBase
{
- private static string _packageId;
- private static string _packageVersion;
- private static string _configFilePath;
- private static string _framework;
- private static string _source;
- private static bool _global;
+ private readonly IToolPackageObtainer _toolPackageObtainer;
+ private readonly IEnvironmentPathInstruction _environmentPathInstruction;
+ private readonly IShellShimMaker _shellShimMaker;
+ private readonly IReporter _reporter;
+
+ private readonly string _packageId;
+ private readonly string _packageVersion;
+ private readonly string _configFilePath;
+ private readonly string _framework;
+ private readonly string _source;
+ private readonly bool _global;
public InstallToolCommand(
AppliedOption appliedCommand,
- ParseResult parseResult)
+ ParseResult parseResult,
+ IToolPackageObtainer toolPackageObtainer = null,
+ IShellShimMaker shellShimMaker = null,
+ IEnvironmentPathInstruction environmentPathInstruction = null,
+ IReporter reporter = null)
: base(parseResult)
{
if (appliedCommand == null)
@@ -39,6 +48,27 @@ namespace Microsoft.DotNet.Tools.Install.Tool
_framework = appliedCommand.ValueOrDefault("framework");
_source = appliedCommand.ValueOrDefault("source");
_global = appliedCommand.ValueOrDefault("global");
+
+ var cliFolderPathCalculator = new CliFolderPathCalculator();
+ var executablePackagePath = new DirectoryPath(cliFolderPathCalculator.ExecutablePackagesPath);
+ var offlineFeedPath = new DirectoryPath(cliFolderPathCalculator.CliFallbackFolderPath);
+ _toolPackageObtainer = toolPackageObtainer ?? new ToolPackageObtainer(
+ executablePackagePath,
+ offlineFeedPath,
+ () => new DirectoryPath(Path.GetTempPath())
+ .WithSubDirectories(Path.GetRandomFileName())
+ .WithFile(Path.GetRandomFileName() + ".csproj"),
+ new Lazy(BundledTargetFramework.GetTargetFrameworkMoniker),
+ new PackageToProjectFileAdder(),
+ new ProjectRestorer());
+
+ _environmentPathInstruction = environmentPathInstruction
+ ?? EnvironmentPathFactory
+ .CreateEnvironmentPathInstruction();
+
+ _shellShimMaker = shellShimMaker ?? new ShellShimMaker(executablePackagePath.Value);
+
+ _reporter = reporter ?? Reporter.Output;
}
public override int Execute()
@@ -48,33 +78,25 @@ namespace Microsoft.DotNet.Tools.Install.Tool
throw new GracefulException(LocalizableStrings.InstallToolCommandOnlySupportGlobal);
}
- var cliFolderPathCalculator = new CliFolderPathCalculator();
- var executablePackagePath = new DirectoryPath(cliFolderPathCalculator.ExecutablePackagesPath);
- var offlineFeedPath = new DirectoryPath(cliFolderPathCalculator.CliFallbackFolderPath);
+ var toolConfigurationAndExecutablePath = ObtainPackage();
- var toolConfigurationAndExecutablePath = ObtainPackage(executablePackagePath, offlineFeedPath);
-
- var shellShimMaker = new ShellShimMaker(executablePackagePath.Value);
var commandName = toolConfigurationAndExecutablePath.Configuration.CommandName;
- shellShimMaker.EnsureCommandNameUniqueness(commandName);
+ _shellShimMaker.EnsureCommandNameUniqueness(commandName);
- shellShimMaker.CreateShim(
+ _shellShimMaker.CreateShim(
toolConfigurationAndExecutablePath.Executable.Value,
commandName);
- EnvironmentPathFactory
- .CreateEnvironmentPathInstruction()
+ _environmentPathInstruction
.PrintAddPathInstructionIfPathDoesNotExist();
- Reporter.Output.WriteLine(
+ _reporter.WriteLine(
string.Format(LocalizableStrings.InstallationSucceeded, commandName));
return 0;
}
- private static ToolConfigurationAndExecutablePath ObtainPackage(
- DirectoryPath executablePackagePath,
- DirectoryPath offlineFeedPath)
+ private ToolConfigurationAndExecutablePath ObtainPackage()
{
try
{
@@ -84,18 +106,7 @@ namespace Microsoft.DotNet.Tools.Install.Tool
configFile = new FilePath(_configFilePath);
}
- var toolPackageObtainer =
- new ToolPackageObtainer(
- executablePackagePath,
- offlineFeedPath,
- () => new DirectoryPath(Path.GetTempPath())
- .WithSubDirectories(Path.GetRandomFileName())
- .WithFile(Path.GetRandomFileName() + ".csproj"),
- new Lazy(BundledTargetFramework.GetTargetFrameworkMoniker),
- new PackageToProjectFileAdder(),
- new ProjectRestorer());
-
- return toolPackageObtainer.ObtainAndReturnExecutablePath(
+ return _toolPackageObtainer.ObtainAndReturnExecutablePath(
packageId: _packageId,
packageVersion: _packageVersion,
nugetconfig: configFile,
diff --git a/test/Microsoft.DotNet.Cli.Tests.sln b/test/Microsoft.DotNet.Cli.Tests.sln
index 863d564db..05bde078d 100644
--- a/test/Microsoft.DotNet.Cli.Tests.sln
+++ b/test/Microsoft.DotNet.Cli.Tests.sln
@@ -86,6 +86,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.ShellShim.
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.ToolPackage.Tests", "Microsoft.DotNet.ToolPackage.Tests\Microsoft.DotNet.ToolPackage.Tests.csproj", "{453C809B-40FC-4A93-93B8-DE449D48B9FF}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.Tools.Tests.ComponentMocks", "Microsoft.DotNet.Tools.Tests.ComponentMocks\Microsoft.DotNet.Tools.Tests.ComponentMocks.csproj", "{A3DE5654-7755-45C8-8AE5-5B5B00BEB248}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -564,6 +566,18 @@ Global
{453C809B-40FC-4A93-93B8-DE449D48B9FF}.Release|x64.Build.0 = Release|Any CPU
{453C809B-40FC-4A93-93B8-DE449D48B9FF}.Release|x86.ActiveCfg = Release|Any CPU
{453C809B-40FC-4A93-93B8-DE449D48B9FF}.Release|x86.Build.0 = Release|Any CPU
+ {A3DE5654-7755-45C8-8AE5-5B5B00BEB248}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A3DE5654-7755-45C8-8AE5-5B5B00BEB248}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A3DE5654-7755-45C8-8AE5-5B5B00BEB248}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {A3DE5654-7755-45C8-8AE5-5B5B00BEB248}.Debug|x64.Build.0 = Debug|Any CPU
+ {A3DE5654-7755-45C8-8AE5-5B5B00BEB248}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {A3DE5654-7755-45C8-8AE5-5B5B00BEB248}.Debug|x86.Build.0 = Debug|Any CPU
+ {A3DE5654-7755-45C8-8AE5-5B5B00BEB248}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A3DE5654-7755-45C8-8AE5-5B5B00BEB248}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A3DE5654-7755-45C8-8AE5-5B5B00BEB248}.Release|x64.ActiveCfg = Release|Any CPU
+ {A3DE5654-7755-45C8-8AE5-5B5B00BEB248}.Release|x64.Build.0 = Release|Any CPU
+ {A3DE5654-7755-45C8-8AE5-5B5B00BEB248}.Release|x86.ActiveCfg = Release|Any CPU
+ {A3DE5654-7755-45C8-8AE5-5B5B00BEB248}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/test/Microsoft.DotNet.ShellShim.Tests/Microsoft.DotNet.ShellShim.Tests.csproj b/test/Microsoft.DotNet.ShellShim.Tests/Microsoft.DotNet.ShellShim.Tests.csproj
index 64fdac72b..6cae0fd85 100644
--- a/test/Microsoft.DotNet.ShellShim.Tests/Microsoft.DotNet.ShellShim.Tests.csproj
+++ b/test/Microsoft.DotNet.ShellShim.Tests/Microsoft.DotNet.ShellShim.Tests.csproj
@@ -9,6 +9,7 @@
+
diff --git a/test/Microsoft.DotNet.ShellShim.Tests/ShellShimMakerTests.cs b/test/Microsoft.DotNet.ShellShim.Tests/ShellShimMakerTests.cs
index 75379aaae..3bf4ff3d0 100644
--- a/test/Microsoft.DotNet.ShellShim.Tests/ShellShimMakerTests.cs
+++ b/test/Microsoft.DotNet.ShellShim.Tests/ShellShimMakerTests.cs
@@ -11,6 +11,8 @@ using FluentAssertions;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.TestFramework;
using Microsoft.DotNet.Tools.Test.Utilities;
+using Microsoft.DotNet.Tools.Test.Utilities.Mock;
+using Microsoft.DotNet.Tools.Tests.ComponentMocks;
using Xunit;
using Xunit.Abstractions;
@@ -91,14 +93,23 @@ namespace Microsoft.DotNet.ShellShim.Tests
}
}
- [Fact]
- public void GivenAnExecutablePathWithExistingSameNameShimItThrows()
+ [InlineData(false)]
+ [InlineData(true)]
+ public void GivenAnExecutablePathWithExistingSameNameShimItThrows(bool testMockBehaviorIsInSync)
{
var shellCommandName = nameof(ShellShimMakerTests) + Path.GetRandomFileName();
MakeNameConflictingCommand(TempRoot.Root, shellCommandName);
- var shellShimMaker = new ShellShimMaker(TempRoot.Root);
+ IShellShimMaker shellShimMaker;
+ if (testMockBehaviorIsInSync)
+ {
+ shellShimMaker = new ShellShimMakerMock(TempRoot.Root);
+ }
+ else
+ {
+ shellShimMaker = new ShellShimMaker(TempRoot.Root);
+ }
Action a = () => shellShimMaker.EnsureCommandNameUniqueness(shellCommandName);
a.ShouldThrow()
@@ -107,13 +118,22 @@ namespace Microsoft.DotNet.ShellShim.Tests
$"Failed to install tool {shellCommandName}. A command with the same name already exists.");
}
-
- [Fact]
- public void GivenAnExecutablePathWithoutExistingSameNameShimItShouldNotThrow()
+ [Theory]
+ [InlineData(false)]
+ [InlineData(true)]
+ public void GivenAnExecutablePathWithoutExistingSameNameShimItShouldNotThrow(bool testMockBehaviorIsInSync)
{
var shellCommandName = nameof(ShellShimMakerTests) + Path.GetRandomFileName();
- var shellShimMaker = new ShellShimMaker(TempRoot.Root);
+ IShellShimMaker shellShimMaker;
+ if (testMockBehaviorIsInSync)
+ {
+ shellShimMaker = new ShellShimMakerMock(TempRoot.Root);
+ }
+ else
+ {
+ shellShimMaker = new ShellShimMaker(TempRoot.Root);
+ }
Action a = () => shellShimMaker.EnsureCommandNameUniqueness(shellCommandName);
a.ShouldNotThrow();
diff --git a/test/Microsoft.DotNet.ToolPackage.Tests/Microsoft.DotNet.ToolPackage.Tests.csproj b/test/Microsoft.DotNet.ToolPackage.Tests/Microsoft.DotNet.ToolPackage.Tests.csproj
index 736655e5b..0670e8c91 100644
--- a/test/Microsoft.DotNet.ToolPackage.Tests/Microsoft.DotNet.ToolPackage.Tests.csproj
+++ b/test/Microsoft.DotNet.ToolPackage.Tests/Microsoft.DotNet.ToolPackage.Tests.csproj
@@ -13,6 +13,7 @@
+
diff --git a/test/Microsoft.DotNet.ToolPackage.Tests/ToolPackageObtainerTests.cs b/test/Microsoft.DotNet.ToolPackage.Tests/ToolPackageObtainerTests.cs
index 4e948966e..8b60baef3 100644
--- a/test/Microsoft.DotNet.ToolPackage.Tests/ToolPackageObtainerTests.cs
+++ b/test/Microsoft.DotNet.ToolPackage.Tests/ToolPackageObtainerTests.cs
@@ -2,48 +2,35 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
+using System.Collections.Generic;
using System.IO;
using System.Reflection;
using FluentAssertions;
using Microsoft.DotNet.Tools.Test.Utilities;
using Microsoft.Extensions.EnvironmentAbstractions;
using Microsoft.DotNet.Cli;
+using Microsoft.DotNet.Tools;
using Microsoft.DotNet.Tools.Install.Tool;
using Xunit;
+using Microsoft.DotNet.Tools.Tests.ComponentMocks;
namespace Microsoft.DotNet.ToolPackage.Tests
{
public class ToolPackageObtainerTests : TestBase
{
- [Fact]
- public void GivenNugetConfigAndPackageNameAndVersionAndTargetFrameworkWhenCallItCanDownloadThePackage()
- {
- FilePath nugetConfigPath = WriteNugetConfigFileToPointToTheFeed();
- var toolsPath = Path.Combine(Directory.GetCurrentDirectory(), Path.GetRandomFileName());
-
- var packageObtainer =
- ConstructDefaultPackageObtainer(toolsPath);
- ToolConfigurationAndExecutablePath toolConfigurationAndExecutablePath = packageObtainer.ObtainAndReturnExecutablePath(
- packageId: TestPackageId,
- packageVersion: TestPackageVersion,
- nugetconfig: nugetConfigPath,
- targetframework: _testTargetframework);
-
- var executable = toolConfigurationAndExecutablePath
- .Executable;
-
- File.Exists(executable.Value)
- .Should()
- .BeTrue(executable + " should have the executable");
- }
-
[Fact]
public void GivenNoFeedItThrows()
{
var toolsPath = Path.Combine(Directory.GetCurrentDirectory(), Path.GetRandomFileName());
ToolPackageObtainer packageObtainer =
- ConstructDefaultPackageObtainer(toolsPath);
+ new ToolPackageObtainer(
+ new DirectoryPath(toolsPath),
+ new DirectoryPath("no such path"),
+ GetUniqueTempProjectPathEachTest,
+ new Lazy(),
+ new PackageToProjectFileAdder(),
+ new ProjectRestorer());
Action a = () => packageObtainer.ObtainAndReturnExecutablePath(
packageId: TestPackageId,
@@ -80,24 +67,57 @@ namespace Microsoft.DotNet.ToolPackage.Tests
.Should()
.BeTrue(executable + " should have the executable");
- executable.Value.Should().NotContain(GetTestLocalFeedPath(), "Executalbe should not be still in fallbackfolder");
- executable.Value.Should().Contain(toolsPath, "Executalbe should be copied to tools Path");
+ executable.Value.Should().NotContain(GetTestLocalFeedPath(), "Executable should not be still in fallbackfolder");
+ executable.Value.Should().Contain(toolsPath, "Executable should be copied to tools Path");
+
+ File.Delete(executable.Value);
}
- [Fact]
- public void GivenNugetConfigAndPackageNameAndVersionAndTargetFrameworkWhenCallItCreateAssetFile()
+ [Theory]
+ [InlineData(false)]
+ [InlineData(true)]
+ public void GivenNugetConfigAndPackageNameAndVersionAndTargetFrameworkWhenCallItCanDownloadThePackage(
+ bool testMockBehaviorIsInSync)
+ {
+ FilePath nugetConfigPath = WriteNugetConfigFileToPointToTheFeed();
+ var toolsPath = Path.Combine(Directory.GetCurrentDirectory(), Path.GetRandomFileName());
+
+ var packageObtainer =
+ ConstructDefaultPackageObtainer(toolsPath, testMockBehaviorIsInSync, nugetConfigPath.Value);
+
+ ToolConfigurationAndExecutablePath toolConfigurationAndExecutablePath
+ = packageObtainer.ObtainAndReturnExecutablePath(
+ packageId: TestPackageId,
+ packageVersion: TestPackageVersion,
+ nugetconfig: nugetConfigPath,
+ targetframework: _testTargetframework);
+
+ FilePath executable = toolConfigurationAndExecutablePath.Executable;
+ File.Exists(executable.Value)
+ .Should()
+ .BeTrue(executable + " should have the executable");
+
+ File.Delete(executable.Value);
+ }
+
+ [Theory]
+ [InlineData(false)]
+ [InlineData(true)]
+ public void GivenNugetConfigAndPackageNameAndVersionAndTargetFrameworkWhenCallItCreateAssetFile(
+ bool testMockBehaviorIsInSync)
{
var nugetConfigPath = WriteNugetConfigFileToPointToTheFeed();
var toolsPath = Path.Combine(Directory.GetCurrentDirectory(), Path.GetRandomFileName());
var packageObtainer =
- ConstructDefaultPackageObtainer(toolsPath);
+ ConstructDefaultPackageObtainer(toolsPath, testMockBehaviorIsInSync, nugetConfigPath.Value);
- ToolConfigurationAndExecutablePath toolConfigurationAndExecutablePath = packageObtainer.ObtainAndReturnExecutablePath(
- packageId: TestPackageId,
- packageVersion: TestPackageVersion,
- nugetconfig: nugetConfigPath,
- targetframework: _testTargetframework);
+ ToolConfigurationAndExecutablePath toolConfigurationAndExecutableDirectory =
+ packageObtainer.ObtainAndReturnExecutablePath(
+ packageId: TestPackageId,
+ packageVersion: TestPackageVersion,
+ nugetconfig: nugetConfigPath,
+ targetframework: _testTargetframework);
/*
From mytool.dll to project.assets.json
@@ -106,7 +126,7 @@ namespace Microsoft.DotNet.ToolPackage.Tests
/dependency2 package id/
/project.assets.json
*/
- var assetJsonPath = toolConfigurationAndExecutablePath
+ var assetJsonPath = toolConfigurationAndExecutableDirectory
.Executable
.GetDirectoryPath()
.GetParentPath()
@@ -119,10 +139,14 @@ namespace Microsoft.DotNet.ToolPackage.Tests
File.Exists(assetJsonPath)
.Should()
.BeTrue(assetJsonPath + " should be created");
+
+ File.Delete(assetJsonPath);
}
- [Fact]
- public void GivenAllButNoNugetConfigFilePathItCanDownloadThePackage()
+ [Theory]
+ [InlineData(false)]
+ [InlineData(true)]
+ public void GivenAllButNoNugetConfigFilePathItCanDownloadThePackage(bool testMockBehaviorIsInSync)
{
var uniqueTempProjectPath = GetUniqueTempProjectPathEachTest();
var tempProjectDirectory = uniqueTempProjectPath.GetDirectoryPath();
@@ -137,14 +161,22 @@ namespace Microsoft.DotNet.ToolPackage.Tests
Directory.SetCurrentDirectory(nugetConfigPath.GetDirectoryPath().Value);
- var packageObtainer =
- new ToolPackageObtainer(
+ IToolPackageObtainer packageObtainer;
+ if (testMockBehaviorIsInSync)
+ {
+ packageObtainer = new ToolPackageObtainerMock();
+ }
+ else
+ {
+ packageObtainer = new ToolPackageObtainer(
new DirectoryPath(toolsPath),
new DirectoryPath("no such path"),
() => uniqueTempProjectPath,
new Lazy(),
new PackageToProjectFileAdder(),
new ProjectRestorer());
+ }
+
ToolConfigurationAndExecutablePath toolConfigurationAndExecutablePath =
packageObtainer.ObtainAndReturnExecutablePath(
packageId: TestPackageId,
@@ -156,37 +188,46 @@ namespace Microsoft.DotNet.ToolPackage.Tests
File.Exists(executable.Value)
.Should()
.BeTrue(executable + " should have the executable");
+
+ File.Delete(executable.Value);
}
- [Fact]
- public void GivenAllButNoPackageVersionItCanDownloadThePackage()
+ [Theory]
+ [InlineData(false)]
+ [InlineData(true)]
+ public void GivenAllButNoPackageVersionItCanDownloadThePackage(bool testMockBehaviorIsInSync)
{
var nugetConfigPath = WriteNugetConfigFileToPointToTheFeed();
var toolsPath = Path.Combine(Directory.GetCurrentDirectory(), Path.GetRandomFileName());
var packageObtainer =
- ConstructDefaultPackageObtainer(toolsPath);
- ToolConfigurationAndExecutablePath toolConfigurationAndExecutablePath = packageObtainer.ObtainAndReturnExecutablePath(
- packageId: TestPackageId,
- packageVersion: TestPackageVersion,
- nugetconfig: nugetConfigPath,
- targetframework: _testTargetframework);
+ ConstructDefaultPackageObtainer(toolsPath, testMockBehaviorIsInSync, nugetConfigPath.Value);
+
+ ToolConfigurationAndExecutablePath toolConfigurationAndExecutablePath =
+ packageObtainer.ObtainAndReturnExecutablePath(
+ packageId: TestPackageId,
+ nugetconfig: nugetConfigPath,
+ targetframework: _testTargetframework);
var executable = toolConfigurationAndExecutablePath.Executable;
File.Exists(executable.Value)
.Should()
.BeTrue(executable + " should have the executable");
+
+ File.Delete(executable.Value);
}
- [Fact]
- public void GivenAllButNoPackageVersionAndInvokeTwiceItShouldNotThrow()
+ [Theory]
+ [InlineData(false)]
+ [InlineData(true)]
+ public void GivenAllButNoPackageVersionAndInvokeTwiceItShouldNotThrow(bool testMockBehaviorIsInSync)
{
var nugetConfigPath = WriteNugetConfigFileToPointToTheFeed();
var toolsPath = Path.Combine(Directory.GetCurrentDirectory(), Path.GetRandomFileName());
var packageObtainer =
- ConstructDefaultPackageObtainer(toolsPath);
+ ConstructDefaultPackageObtainer(toolsPath, testMockBehaviorIsInSync, nugetConfigPath.Value);
packageObtainer.ObtainAndReturnExecutablePath(
packageId: TestPackageId,
@@ -201,21 +242,45 @@ namespace Microsoft.DotNet.ToolPackage.Tests
secondCall.ShouldNotThrow();
}
-
- [Fact]
- public void GivenAllButNoTargetFrameworkItCanDownloadThePackage()
+ [Theory]
+ [InlineData(false)]
+ [InlineData(true)]
+ public void GivenAllButNoTargetFrameworkItCanDownloadThePackage(bool testMockBehaviorIsInSync)
{
var nugetConfigPath = WriteNugetConfigFileToPointToTheFeed();
var toolsPath = Path.Combine(Directory.GetCurrentDirectory(), Path.GetRandomFileName());
- var packageObtainer =
- new ToolPackageObtainer(
+ IToolPackageObtainer packageObtainer;
+ if (testMockBehaviorIsInSync)
+ {
+ packageObtainer = new ToolPackageObtainerMock(additionalFeeds:
+ new List
+ {
+ new MockFeed
+ {
+ Type = MockFeedType.ExplicitNugetConfig,
+ Uri = nugetConfigPath.Value,
+ Packages = new List
+ {
+ new MockFeedPackage
+ {
+ PackageId = "global.tool.console.demo",
+ Version = "1.0.4"
+ }
+ }
+ }
+ });
+ }
+ else
+ {
+ packageObtainer = new ToolPackageObtainer(
new DirectoryPath(toolsPath),
new DirectoryPath("no such path"),
GetUniqueTempProjectPathEachTest,
new Lazy(() => BundledTargetFramework.GetTargetFrameworkMoniker()),
new PackageToProjectFileAdder(),
new ProjectRestorer());
+ }
ToolConfigurationAndExecutablePath toolConfigurationAndExecutablePath =
packageObtainer.ObtainAndReturnExecutablePath(
packageId: TestPackageId,
@@ -227,28 +292,41 @@ namespace Microsoft.DotNet.ToolPackage.Tests
File.Exists(executable.Value)
.Should()
.BeTrue(executable + " should have the executable");
+
+ File.Delete(executable.Value);
}
- [Fact]
- public void GivenNonExistentNugetConfigFileItThrows()
+ [Theory]
+ [InlineData(false)]
+ [InlineData(true)]
+ public void GivenNonExistentNugetConfigFileItThrows(bool testMockBehaviorIsInSync)
{
var toolsPath = Path.Combine(Directory.GetCurrentDirectory(), Path.GetRandomFileName());
var packageObtainer =
- ConstructDefaultPackageObtainer(toolsPath);
- Action a = () => packageObtainer.ObtainAndReturnExecutablePath(
- packageId: TestPackageId,
- packageVersion: TestPackageVersion,
- nugetconfig: new FilePath("NonExistent.file"),
- targetframework: _testTargetframework);
+ ConstructDefaultPackageObtainer(toolsPath, testMockBehaviorIsInSync);
+
+ var nonExistNugetConfigFile = new FilePath("NonExistent.file");
+ Action a = () =>
+ {
+ packageObtainer.ObtainAndReturnExecutablePath(
+ packageId: TestPackageId,
+ packageVersion: TestPackageVersion,
+ nugetconfig: nonExistNugetConfigFile,
+ targetframework: _testTargetframework);
+ };
a.ShouldThrow()
.And
- .Message.Should().Contain("does not exist");
+ .Message.Should().Contain(string.Format(
+ CommonLocalizableStrings.NuGetConfigurationFileDoesNotExist,
+ Path.GetFullPath(nonExistNugetConfigFile.Value)));
}
- [Fact]
- public void GivenASourceItCanObtainThePackageFromThatSource()
+ [Theory]
+ [InlineData(false)]
+ [InlineData(true)]
+ public void GivenASourceItCanObtainThePackageFromThatSource(bool testMockBehaviorIsInSync)
{
var toolsPath = Path.Combine(Directory.GetCurrentDirectory(), Path.GetRandomFileName());
@@ -257,13 +335,15 @@ namespace Microsoft.DotNet.ToolPackage.Tests
packageId: TestPackageId,
packageVersion: TestPackageVersion,
targetframework: _testTargetframework,
- source: GetTestLocalFeedPath());
+ source:GetTestLocalFeedPath());
var executable = toolConfigurationAndExecutableDirectory.Executable;
File.Exists(executable.Value)
.Should()
.BeTrue(executable + " should have the executable");
+
+ File.Delete(executable.Value);
}
private static readonly Func GetUniqueTempProjectPathEachTest = () =>
@@ -275,8 +355,59 @@ namespace Microsoft.DotNet.ToolPackage.Tests
return tempProjectPath;
};
- private static ToolPackageObtainer ConstructDefaultPackageObtainer(string toolsPath)
+ private static IToolPackageObtainer ConstructDefaultPackageObtainer(
+ string toolsPath,
+ bool testMockBehaviorIsInSync = false,
+ string addNugetConfigFeedWithFilePath = null,
+ string addSourceFeedWithFilePath = null)
{
+ if (testMockBehaviorIsInSync)
+ {
+ if (addNugetConfigFeedWithFilePath != null)
+ {
+ return new ToolPackageObtainerMock(additionalFeeds:
+ new List
+ {
+ new MockFeed
+ {
+ Type = MockFeedType.ExplicitNugetConfig,
+ Uri = addNugetConfigFeedWithFilePath,
+ Packages = new List
+ {
+ new MockFeedPackage
+ {
+ PackageId = "global.tool.console.demo",
+ Version = "1.0.4"
+ }
+ }
+ }
+ });
+ }
+
+ if (addSourceFeedWithFilePath != null)
+ {
+ return new ToolPackageObtainerMock(additionalFeeds:
+ new List
+ {
+ new MockFeed
+ {
+ Type = MockFeedType.ExplicitNugetConfig,
+ Uri = addSourceFeedWithFilePath,
+ Packages = new List
+ {
+ new MockFeedPackage
+ {
+ PackageId = "global.tool.console.demo",
+ Version = "1.0.4"
+ }
+ }
+ }
+ });
+ }
+
+ return new ToolPackageObtainerMock();
+ }
+
return new ToolPackageObtainer(
new DirectoryPath(toolsPath),
new DirectoryPath("no such path"),
@@ -292,7 +423,7 @@ namespace Microsoft.DotNet.ToolPackage.Tests
var tempPathForNugetConfigWithWhiteSpace =
Path.Combine(Path.GetTempPath(),
- Path.GetRandomFileName() + " " + Path.GetRandomFileName());
+ Path.GetRandomFileName() + " " + Path.GetRandomFileName());
Directory.CreateDirectory(tempPathForNugetConfigWithWhiteSpace);
NuGetConfig.Write(
diff --git a/test/Microsoft.DotNet.Tools.Tests.ComponentMocks/EnvironmentPathInstructionMock.cs b/test/Microsoft.DotNet.Tools.Tests.ComponentMocks/EnvironmentPathInstructionMock.cs
new file mode 100644
index 000000000..c07f5ad1b
--- /dev/null
+++ b/test/Microsoft.DotNet.Tools.Tests.ComponentMocks/EnvironmentPathInstructionMock.cs
@@ -0,0 +1,39 @@
+// 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 System;
+using Microsoft.DotNet.Cli.Utils;
+
+namespace Microsoft.DotNet.Tools.Tests.ComponentMocks
+{
+ internal class EnvironmentPathInstructionMock : IEnvironmentPathInstruction
+ {
+ private readonly string _packageExecutablePath;
+ private readonly bool _packageExecutablePathExists;
+ private readonly IReporter _reporter;
+
+ public EnvironmentPathInstructionMock(
+ IReporter reporter,
+ string packageExecutablePath,
+ bool packageExecutablePathExists = false)
+ {
+ _packageExecutablePath =
+ packageExecutablePath ?? throw new ArgumentNullException(nameof(packageExecutablePath));
+ _reporter = reporter ?? throw new ArgumentNullException(nameof(reporter));
+ _packageExecutablePathExists = packageExecutablePathExists;
+ }
+
+ public void PrintAddPathInstructionIfPathDoesNotExist()
+ {
+ if (!PackageExecutablePathExists())
+ {
+ _reporter.WriteLine("INSTRUCTION");
+ }
+ }
+
+ private bool PackageExecutablePathExists()
+ {
+ return _packageExecutablePathExists;
+ }
+ }
+}
diff --git a/test/Microsoft.DotNet.Tools.Tests.ComponentMocks/Microsoft.DotNet.Tools.Tests.ComponentMocks.csproj b/test/Microsoft.DotNet.Tools.Tests.ComponentMocks/Microsoft.DotNet.Tools.Tests.ComponentMocks.csproj
new file mode 100644
index 000000000..bd29dccd9
--- /dev/null
+++ b/test/Microsoft.DotNet.Tools.Tests.ComponentMocks/Microsoft.DotNet.Tools.Tests.ComponentMocks.csproj
@@ -0,0 +1,16 @@
+
+
+ $(CliTargetFramework)
+ $(MicrosoftNETCoreAppPackageVersion)
+ Microsoft.DotNet.Tools.Tests.ComponentMocks
+ ../../tools/Key.snk
+ $(AssetTargetFallback);dotnet5.4;portable-net451+win8
+ true
+ true
+
+
+
+
+
+
+
diff --git a/test/Microsoft.DotNet.Tools.Tests.ComponentMocks/MockFeed.cs b/test/Microsoft.DotNet.Tools.Tests.ComponentMocks/MockFeed.cs
new file mode 100644
index 000000000..a2199c75e
--- /dev/null
+++ b/test/Microsoft.DotNet.Tools.Tests.ComponentMocks/MockFeed.cs
@@ -0,0 +1,14 @@
+// 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 System.Collections.Generic;
+
+namespace Microsoft.DotNet.Tools.Tests.ComponentMocks
+{
+ public class MockFeed
+ {
+ public MockFeedType Type;
+ public string Uri;
+ public List Packages;
+ }
+}
diff --git a/test/Microsoft.DotNet.Tools.Tests.ComponentMocks/MockFeedPackage.cs b/test/Microsoft.DotNet.Tools.Tests.ComponentMocks/MockFeedPackage.cs
new file mode 100644
index 000000000..6bf9fc44a
--- /dev/null
+++ b/test/Microsoft.DotNet.Tools.Tests.ComponentMocks/MockFeedPackage.cs
@@ -0,0 +1,11 @@
+// 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.
+
+namespace Microsoft.DotNet.Tools.Tests.ComponentMocks
+{
+ public class MockFeedPackage
+ {
+ public string PackageId;
+ public string Version;
+ }
+}
diff --git a/test/Microsoft.DotNet.Tools.Tests.ComponentMocks/MockFeedType.cs b/test/Microsoft.DotNet.Tools.Tests.ComponentMocks/MockFeedType.cs
new file mode 100644
index 000000000..c79dc327e
--- /dev/null
+++ b/test/Microsoft.DotNet.Tools.Tests.ComponentMocks/MockFeedType.cs
@@ -0,0 +1,12 @@
+// 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.
+
+namespace Microsoft.DotNet.Tools.Tests.ComponentMocks
+{
+ public enum MockFeedType
+ {
+ FeedFromLookUpNugetConfig,
+ ExplicitNugetConfig,
+ Source
+ }
+}
diff --git a/test/Microsoft.DotNet.Tools.Tests.ComponentMocks/Properties/Properties.cs b/test/Microsoft.DotNet.Tools.Tests.ComponentMocks/Properties/Properties.cs
new file mode 100644
index 000000000..b358c68f3
--- /dev/null
+++ b/test/Microsoft.DotNet.Tools.Tests.ComponentMocks/Properties/Properties.cs
@@ -0,0 +1,8 @@
+// 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 System.Runtime.CompilerServices;
+
+[assembly: InternalsVisibleTo("dotnet.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
+[assembly: InternalsVisibleTo("Microsoft.DotNet.ToolPackage.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
+[assembly: InternalsVisibleTo("Microsoft.DotNet.ShellShim.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
diff --git a/test/Microsoft.DotNet.Tools.Tests.ComponentMocks/ShellShimMakerMock.cs b/test/Microsoft.DotNet.Tools.Tests.ComponentMocks/ShellShimMakerMock.cs
new file mode 100644
index 000000000..3e19da8db
--- /dev/null
+++ b/test/Microsoft.DotNet.Tools.Tests.ComponentMocks/ShellShimMakerMock.cs
@@ -0,0 +1,58 @@
+// 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 System;
+using System.IO;
+using Microsoft.DotNet.Cli.Utils;
+using Microsoft.DotNet.ShellShim;
+using Microsoft.Extensions.EnvironmentAbstractions;
+using Newtonsoft.Json;
+
+namespace Microsoft.DotNet.Tools.Tests.ComponentMocks
+{
+ internal class ShellShimMakerMock : IShellShimMaker
+ {
+ private static IFileSystem _fileSystem;
+ private readonly string _pathToPlaceShim;
+
+ public ShellShimMakerMock(string pathToPlaceShim, IFileSystem fileSystem = null)
+ {
+ _pathToPlaceShim =
+ pathToPlaceShim ?? throw new ArgumentNullException(nameof(pathToPlaceShim));
+
+ _fileSystem = fileSystem ?? new FileSystemWrapper();
+ }
+
+ public void CreateShim(string packageExecutablePath, string shellCommandName)
+ {
+ var packageExecutable = new FilePath(packageExecutablePath);
+
+
+ var fakeshim = new FakeShim
+ {
+ Runner = "dotnet",
+ ExecutablePath = packageExecutable.Value
+ };
+ var script = JsonConvert.SerializeObject(fakeshim);
+
+ FilePath scriptPath = new FilePath(Path.Combine(_pathToPlaceShim, shellCommandName));
+ _fileSystem.File.WriteAllText(scriptPath.Value, script);
+ }
+
+ public void EnsureCommandNameUniqueness(string shellCommandName)
+ {
+ if (_fileSystem.File.Exists(Path.Combine(_pathToPlaceShim, shellCommandName)))
+ {
+ throw new GracefulException(
+ string.Format(CommonLocalizableStrings.FailInstallToolSameName,
+ shellCommandName));
+ }
+ }
+
+ public class FakeShim
+ {
+ public string Runner { get; set; }
+ public string ExecutablePath { get; set; }
+ }
+ }
+}
diff --git a/test/Microsoft.DotNet.Tools.Tests.ComponentMocks/ToolPackageObtainerMock.cs b/test/Microsoft.DotNet.Tools.Tests.ComponentMocks/ToolPackageObtainerMock.cs
new file mode 100644
index 000000000..efc42f4e8
--- /dev/null
+++ b/test/Microsoft.DotNet.Tools.Tests.ComponentMocks/ToolPackageObtainerMock.cs
@@ -0,0 +1,159 @@
+// 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 System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using Microsoft.DotNet.ToolPackage;
+using Microsoft.Extensions.EnvironmentAbstractions;
+
+namespace Microsoft.DotNet.Tools.Tests.ComponentMocks
+{
+ internal class ToolPackageObtainerMock : IToolPackageObtainer
+ {
+ private readonly Action _beforeRunObtain;
+ public const string FakeEntrypointName = "SimulatorEntryPoint.dll";
+ public const string FakeCommandName = "SimulatorCommand";
+ private static IFileSystem _fileSystem;
+ private string _fakeExecutableDirectory;
+ private List _mockFeeds;
+
+ public ToolPackageObtainerMock(
+ IFileSystem fileSystemWrapper = null,
+ bool useDefaultFeed = true,
+ IEnumerable additionalFeeds = null,
+ Action beforeRunObtain = null)
+ {
+ _beforeRunObtain = beforeRunObtain ?? (() => { });
+ _fileSystem = fileSystemWrapper ?? new FileSystemWrapper();
+ _mockFeeds = new List();
+
+ if (useDefaultFeed)
+ {
+ _mockFeeds.Add(new MockFeed
+ {
+ Type = MockFeedType.FeedFromLookUpNugetConfig,
+ Packages = new List
+ {
+ new MockFeedPackage
+ {
+ PackageId = "global.tool.console.demo",
+ Version = "1.0.4"
+ }
+ }
+ });
+ }
+
+ if (additionalFeeds != null)
+ {
+ _mockFeeds.AddRange(additionalFeeds);
+ }
+ }
+
+ public ToolConfigurationAndExecutablePath ObtainAndReturnExecutablePath(
+ string packageId,
+ string packageVersion = null,
+ FilePath? nugetconfig = null,
+ string targetframework = null,
+ string source = null)
+ {
+ _beforeRunObtain();
+
+ PickFeedByNugetConfig(nugetconfig);
+ PickFeedBySource(source);
+
+ MockFeedPackage package = _mockFeeds
+ .SelectMany(f => f.Packages)
+ .Where(p => MatchPackageVersion(p, packageId, packageVersion)).OrderByDescending(p => p.Version)
+ .FirstOrDefault();
+
+ if (package == null)
+ {
+ throw new PackageObtainException("simulated cannot find package");
+ }
+
+ packageVersion = package.Version;
+ targetframework = targetframework ?? "targetframework";
+
+ var packageIdVersionDirectory = Path.Combine("toolPath", packageId, packageVersion);
+
+ _fakeExecutableDirectory = Path.Combine(packageIdVersionDirectory,
+ packageId, packageVersion, "morefolders", "tools",
+ targetframework);
+ var fakeExecutable = Path.Combine(_fakeExecutableDirectory, FakeEntrypointName);
+
+ if (!_fileSystem.Directory.Exists(_fakeExecutableDirectory))
+ {
+ _fileSystem.Directory.CreateDirectory(_fakeExecutableDirectory);
+ }
+
+ _fileSystem.File.CreateEmptyFile(Path.Combine(packageIdVersionDirectory, "project.assets.json"));
+ _fileSystem.File.CreateEmptyFile(fakeExecutable);
+
+ return new ToolConfigurationAndExecutablePath(
+ toolConfiguration: new ToolConfiguration(FakeCommandName, FakeEntrypointName),
+ executable: new FilePath(fakeExecutable));
+ }
+
+ private void PickFeedBySource(string source)
+ {
+ if (source != null)
+ {
+ var feed = _mockFeeds.SingleOrDefault(
+ f => f.Type == MockFeedType.Source
+ && f.Uri == source);
+
+ if (feed != null)
+ {
+ _mockFeeds = new List
+ {
+ feed
+ };
+ }
+ else
+ {
+ _mockFeeds = new List();
+ }
+ }
+ }
+
+ private void PickFeedByNugetConfig(FilePath? nugetconfig)
+ {
+ if (nugetconfig != null)
+ {
+ if (!_fileSystem.File.Exists(nugetconfig.Value.Value))
+ {
+ throw new PackageObtainException(
+ string.Format(CommonLocalizableStrings.NuGetConfigurationFileDoesNotExist,
+ Path.GetFullPath(nugetconfig.Value.Value)));
+ }
+
+ var feed = _mockFeeds.SingleOrDefault(
+ f => f.Type == MockFeedType.ExplicitNugetConfig
+ && f.Uri == nugetconfig.Value.Value);
+
+ if (feed != null)
+ {
+ _mockFeeds = new List
+ {
+ feed
+ };
+ }
+ else
+ {
+ _mockFeeds = new List();
+ }
+ }
+ }
+
+ private static bool MatchPackageVersion(MockFeedPackage p, string packageId, string packageVersion)
+ {
+ if (packageVersion == null)
+ {
+ return p.PackageId == packageId;
+ }
+ return p.PackageId == packageId && p.Version == packageVersion;
+ }
+ }
+}
diff --git a/test/Microsoft.DotNet.Tools.Tests.Utilities/Properties/Properties.cs b/test/Microsoft.DotNet.Tools.Tests.Utilities/Properties/Properties.cs
index 98bfc776e..be0d4944b 100644
--- a/test/Microsoft.DotNet.Tools.Tests.Utilities/Properties/Properties.cs
+++ b/test/Microsoft.DotNet.Tools.Tests.Utilities/Properties/Properties.cs
@@ -3,5 +3,8 @@
using System.Runtime.CompilerServices;
-[assembly: InternalsVisibleTo("Microsoft.Extensions.DependencyModel.Tests , PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
-[assembly: InternalsVisibleTo("Microsoft.DotNet.Configurer.UnitTests , PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
+[assembly: InternalsVisibleTo("Microsoft.Extensions.DependencyModel.Tests , PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
+[assembly: InternalsVisibleTo("Microsoft.DotNet.Configurer.UnitTests , PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
+[assembly: InternalsVisibleTo("dotnet.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
+[assembly: InternalsVisibleTo("Microsoft.DotNet.ToolPackage.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
+[assembly: InternalsVisibleTo("Microsoft.DotNet.ShellShim.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
diff --git a/test/dotnet.Tests/InstallToolCommandTests/InstallToolCommandTests.cs b/test/dotnet.Tests/InstallToolCommandTests/InstallToolCommandTests.cs
new file mode 100644
index 000000000..118db746b
--- /dev/null
+++ b/test/dotnet.Tests/InstallToolCommandTests/InstallToolCommandTests.cs
@@ -0,0 +1,211 @@
+// 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 System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using FluentAssertions;
+using Microsoft.DotNet.Cli;
+using Microsoft.DotNet.Cli.CommandLine;
+using Microsoft.DotNet.Cli.Utils;
+using Microsoft.DotNet.ToolPackage;
+using Microsoft.DotNet.Tools.Install.Tool;
+using Microsoft.DotNet.Tools.Tests.ComponentMocks;
+using Microsoft.Extensions.DependencyModel.Tests;
+using Microsoft.Extensions.EnvironmentAbstractions;
+using Newtonsoft.Json;
+using Xunit;
+using Parser = Microsoft.DotNet.Cli.Parser;
+using LocalizableStrings = Microsoft.DotNet.Tools.Install.Tool.LocalizableStrings;
+
+namespace Microsoft.DotNet.Tests.InstallToolCommandTests
+{
+ public class InstallToolCommandTests
+ {
+ private readonly IFileSystem _fileSystemWrapper;
+ private readonly ToolPackageObtainerMock _toolPackageObtainerMock;
+ private readonly ShellShimMakerMock _shellShimMakerMock;
+ private readonly EnvironmentPathInstructionMock _environmentPathInstructionMock;
+ private readonly AppliedOption _appliedCommand;
+ private readonly ParseResult _parseResult;
+ private readonly FakeReporter _fakeReporter;
+ private const string PathToPlaceShim = "pathToPlace";
+
+ public InstallToolCommandTests()
+ {
+ _fileSystemWrapper = new FileSystemMockBuilder().Build();
+ _toolPackageObtainerMock = new ToolPackageObtainerMock(_fileSystemWrapper);
+ _shellShimMakerMock = new ShellShimMakerMock(PathToPlaceShim, _fileSystemWrapper);
+ _fakeReporter = new FakeReporter();
+ _environmentPathInstructionMock =
+ new EnvironmentPathInstructionMock(_fakeReporter, PathToPlaceShim);
+
+ ParseResult result = Parser.Instance.Parse("dotnet install tool -g global.tool.console.demo");
+ _appliedCommand = result["dotnet"]["install"]["tool"];
+ var parser = Parser.Instance;
+ _parseResult = parser.ParseFrom("dotnet install", new[] {"tool", "global.tool.console.demo"});
+ }
+
+ [Fact]
+ public void WhenRunWithPackageIdItShouldCreateValidShim()
+ {
+ var installToolCommand = new InstallToolCommand(_appliedCommand,
+ _parseResult,
+ _toolPackageObtainerMock,
+ _shellShimMakerMock,
+ _environmentPathInstructionMock);
+
+ installToolCommand.Execute();
+
+ // It is hard to simulate shell behavior. Only Assert shim can point to executable dll
+ _fileSystemWrapper.File.Exists(Path.Combine("pathToPlace", ToolPackageObtainerMock.FakeCommandName))
+ .Should().BeTrue();
+ var deserializedFakeShim = JsonConvert.DeserializeObject(
+ _fileSystemWrapper.File.ReadAllText(
+ Path.Combine("pathToPlace",
+ ToolPackageObtainerMock.FakeCommandName)));
+ _fileSystemWrapper.File.Exists(deserializedFakeShim.ExecutablePath).Should().BeTrue();
+ }
+
+ [Fact]
+ public void WhenRunWithPackageIdWithSourceItShouldCreateValidShim()
+ {
+ const string sourcePath = "http://mysouce.com";
+ ParseResult result = Parser.Instance.Parse($"dotnet install tool -g global.tool.console.demo --source {sourcePath}");
+ AppliedOption appliedCommand = result["dotnet"]["install"]["tool"];
+ const string packageId = "global.tool.console.demo";
+ ParseResult parseResult =
+ Parser.Instance.ParseFrom("dotnet install", new[] {"tool", packageId, "--source", sourcePath});
+
+ var installToolCommand = new InstallToolCommand(appliedCommand,
+ parseResult,
+ new ToolPackageObtainerMock(_fileSystemWrapper, additionalFeeds: new List
+ {
+ new MockFeed
+ {
+ Type = MockFeedType.Source,
+ Uri = sourcePath,
+ Packages = new List
+ {
+ new MockFeedPackage
+ {
+ PackageId = packageId,
+ Version = "1.0.4"
+ }
+ }
+ }
+ }),
+ _shellShimMakerMock,
+ _environmentPathInstructionMock);
+
+ installToolCommand.Execute();
+
+ // It is hard to simulate shell behavior. Only Assert shim can point to executable dll
+ _fileSystemWrapper.File.Exists(Path.Combine("pathToPlace", ToolPackageObtainerMock.FakeCommandName))
+ .Should().BeTrue();
+ ShellShimMakerMock.FakeShim deserializedFakeShim =
+ JsonConvert.DeserializeObject(
+ _fileSystemWrapper.File.ReadAllText(
+ Path.Combine("pathToPlace",
+ ToolPackageObtainerMock.FakeCommandName)));
+ _fileSystemWrapper.File.Exists(deserializedFakeShim.ExecutablePath).Should().BeTrue();
+ }
+
+ [Fact]
+ public void WhenRunWithPackageIdItShouldShowPathInstruction()
+ {
+ var installToolCommand = new InstallToolCommand(_appliedCommand,
+ _parseResult,
+ _toolPackageObtainerMock,
+ _shellShimMakerMock,
+ _environmentPathInstructionMock);
+
+ installToolCommand.Execute();
+
+ _fakeReporter.Message.Single().Should().NotBeEmpty();
+ }
+
+ [Fact]
+ public void GivenFailedPackageObtainWhenRunWithPackageIdItShouldThrow()
+ {
+ var toolPackageObtainerSimulatorThatThrows
+ = new ToolPackageObtainerMock(
+ _fileSystemWrapper, true, null,
+ () => throw new PackageObtainException("Simulated error"));
+ var installToolCommand = new InstallToolCommand(
+ _appliedCommand,
+ _parseResult,
+ toolPackageObtainerSimulatorThatThrows,
+ _shellShimMakerMock,
+ _environmentPathInstructionMock,
+ _fakeReporter);
+
+ Action a = () => installToolCommand.Execute();
+
+ a.ShouldThrow()
+ .And.Message.Should()
+ .Contain(string.Format(LocalizableStrings.InstallFailedNuget, "Simulated error"));
+ }
+
+ [Fact]
+ public void GivenInCorrectToolConfigurationWhenRunWithPackageIdItShouldThrow()
+ {
+ var toolPackageObtainerSimulatorThatThrows
+ = new ToolPackageObtainerMock(
+ _fileSystemWrapper, true, null,
+ () => throw new ToolConfigurationException("Simulated error"));
+ var installToolCommand = new InstallToolCommand(
+ _appliedCommand,
+ _parseResult,
+ toolPackageObtainerSimulatorThatThrows,
+ _shellShimMakerMock,
+ _environmentPathInstructionMock,
+ _fakeReporter);
+
+ Action a = () => installToolCommand.Execute();
+ a.ShouldThrow()
+ .And.Message.Should()
+ .Contain(string.Format(LocalizableStrings.InstallFailedPackage, "Simulated error"));
+ }
+
+ [Fact]
+ public void WhenRunWithPackageIdItShouldShowSuccessMessage()
+ {
+ var installToolCommand = new InstallToolCommand(
+ _appliedCommand,
+ _parseResult,
+ _toolPackageObtainerMock,
+ _shellShimMakerMock,
+ new EnvironmentPathInstructionMock(_fakeReporter, PathToPlaceShim, true),
+ _fakeReporter);
+
+ installToolCommand.Execute();
+
+ _fakeReporter
+ .Message
+ .Single().Should()
+ .Contain(string.Format(LocalizableStrings.InstallationSucceeded, "SimulatorCommand"));
+ }
+
+ internal class FakeReporter : IReporter
+ {
+ public List Message { get; set; } = new List();
+
+ public void WriteLine(string message)
+ {
+ Message.Add(message);
+ }
+
+ public void WriteLine()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Write(string message)
+ {
+ throw new NotImplementedException();
+ }
+ }
+ }
+}
diff --git a/test/dotnet.Tests/dotnet.Tests.csproj b/test/dotnet.Tests/dotnet.Tests.csproj
index 6095d1a0e..561d03b72 100644
--- a/test/dotnet.Tests/dotnet.Tests.csproj
+++ b/test/dotnet.Tests/dotnet.Tests.csproj
@@ -71,6 +71,7 @@
+