123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430 |
- // Licensed to the .NET Foundation under one or more agreements.
- // The .NET Foundation licenses this file to you under the MIT license.
- using Microsoft.DotNet.Cli.Utils;
- using Microsoft.DotNet.CommandFactory;
- using Microsoft.DotNet.Tools.Test.Utilities;
- using NuGet.Frameworks;
- using NuGet.ProjectModel;
- using NuGet.Versioning;
- using LocalizableStrings = Microsoft.DotNet.CommandFactory.LocalizableStrings;
- namespace Microsoft.DotNet.Tests
- {
- public class GivenAProjectToolsCommandResolver : SdkTest
- {
- private static readonly NuGetFramework s_toolPackageFramework =
- FrameworkConstants.CommonFrameworks.NetCoreApp22;
- private const string TestProjectName = "AppWithToolDependency";
- public GivenAProjectToolsCommandResolver(ITestOutputHelper log) : base(log)
- {
- }
- [Fact]
- public void ItReturnsNullWhenCommandNameIsNull()
- {
- var projectToolsCommandResolver = SetupProjectToolsCommandResolver();
- var commandResolverArguments = new CommandResolverArguments()
- {
- CommandName = null,
- CommandArguments = new string[] { "" },
- ProjectDirectory = "/some/directory"
- };
- var result = projectToolsCommandResolver.Resolve(commandResolverArguments);
- result.Should().BeNull();
- }
- [Fact]
- public void ItReturnsNullWhenProjectDirectoryIsNull()
- {
- var projectToolsCommandResolver = SetupProjectToolsCommandResolver();
- var commandResolverArguments = new CommandResolverArguments()
- {
- CommandName = "command",
- CommandArguments = new string[] { "" },
- ProjectDirectory = null
- };
- var result = projectToolsCommandResolver.Resolve(commandResolverArguments);
- result.Should().BeNull();
- }
- [Fact]
- public void ItReturnsNullWhenProjectDirectoryDoesNotContainAProjectFile()
- {
- var projectToolsCommandResolver = SetupProjectToolsCommandResolver();
- var projectDirectory = _testAssetsManager.CreateTestDirectory();
- var commandResolverArguments = new CommandResolverArguments()
- {
- CommandName = "command",
- CommandArguments = new string[] { "" },
- ProjectDirectory = projectDirectory.Path
- };
- var result = projectToolsCommandResolver.Resolve(commandResolverArguments);
- result.Should().BeNull();
- }
- [Fact]
- public void ItReturnsNullWhenCommandNameDoesNotExistInProjectTools()
- {
- var projectToolsCommandResolver = SetupProjectToolsCommandResolver();
- var testInstance = _testAssetsManager.CopyTestAsset(TestProjectName)
- .WithSource();
- NuGetConfigWriter.Write(testInstance.Path, TestContext.Current.TestPackages);
- testInstance.Restore(Log);
- var commandResolverArguments = new CommandResolverArguments()
- {
- CommandName = "nonexistent-command",
- CommandArguments = null,
- ProjectDirectory = testInstance.Path
- };
- var result = projectToolsCommandResolver.Resolve(commandResolverArguments);
- result.Should().BeNull();
- }
- [Fact]
- public void ItReturnsACommandSpecWithDOTNETAsFileNameAndCommandNameInArgsWhenCommandNameExistsInProjectTools()
- {
- var projectToolsCommandResolver = SetupProjectToolsCommandResolver();
- var testInstance = _testAssetsManager.CopyTestAsset(TestProjectName)
- .WithSource();
- NuGetConfigWriter.Write(testInstance.Path, TestContext.Current.TestPackages);
- testInstance.Restore(Log);
- var commandResolverArguments = new CommandResolverArguments()
- {
- CommandName = "dotnet-portable",
- CommandArguments = null,
- ProjectDirectory = testInstance.Path
- };
- var result = projectToolsCommandResolver.Resolve(commandResolverArguments);
- result.Should().NotBeNull();
- var commandFile = Path.GetFileNameWithoutExtension(result.Path);
- commandFile.Should().Be("dotnet");
- result.Args.Should().Contain(commandResolverArguments.CommandName);
- }
- [Fact]
- public void ItEscapesCommandArgumentsWhenReturningACommandSpec()
- {
- var projectToolsCommandResolver = SetupProjectToolsCommandResolver();
- var testInstance = _testAssetsManager.CopyTestAsset(TestProjectName)
- .WithSource();
- NuGetConfigWriter.Write(testInstance.Path, TestContext.Current.TestPackages);
- testInstance.Restore(Log);
- var commandResolverArguments = new CommandResolverArguments()
- {
- CommandName = "dotnet-portable",
- CommandArguments = new[] { "arg with space" },
- ProjectDirectory = testInstance.Path
- };
- var result = projectToolsCommandResolver.Resolve(commandResolverArguments);
- result.Should().NotBeNull("Because the command is a project tool dependency");
- result.Args.Should().Contain("\"arg with space\"");
- }
- [Fact]
- public void ItReturnsACommandSpecWithArgsContainingCommandPathWhenReturningACommandSpecAndCommandArgumentsAreNull()
- {
- var projectToolsCommandResolver = SetupProjectToolsCommandResolver();
- var testInstance = _testAssetsManager.CopyTestAsset(TestProjectName)
- .WithSource();
- NuGetConfigWriter.Write(testInstance.Path, TestContext.Current.TestPackages);
- testInstance.Restore(Log);
- var commandResolverArguments = new CommandResolverArguments()
- {
- CommandName = "dotnet-portable",
- CommandArguments = null,
- ProjectDirectory = testInstance.Path
- };
- var result = projectToolsCommandResolver.Resolve(commandResolverArguments);
- result.Should().NotBeNull();
- var commandPath = result.Args.Trim('"');
- commandPath.Should().Contain("dotnet-portable.dll");
- }
- [Fact]
- public void ItReturnsACommandSpecWithArgsContainingCommandPathWhenInvokingAToolReferencedWithADifferentCasing()
- {
- var projectToolsCommandResolver = SetupProjectToolsCommandResolver();
- var testInstance = _testAssetsManager.CopyTestAsset(TestProjectName)
- .WithSource();
- NuGetConfigWriter.Write(testInstance.Path, TestContext.Current.TestPackages);
- testInstance.Restore(Log);
- var commandResolverArguments = new CommandResolverArguments()
- {
- CommandName = "dotnet-prefercliruntime",
- CommandArguments = null,
- ProjectDirectory = testInstance.Path
- };
- var result = projectToolsCommandResolver.Resolve(commandResolverArguments);
- result.Should().NotBeNull();
- var commandPath = result.Args.Trim('"');
- commandPath.Should().Contain("dotnet-prefercliruntime.dll");
- }
- [Fact]
- public void ItWritesADepsJsonFileNextToTheLockfile()
- {
- var projectToolsCommandResolver = SetupProjectToolsCommandResolver();
- var testInstance = _testAssetsManager.CopyTestAsset(TestProjectName)
- .WithSource()
- .WithRepoGlobalPackages();
- NuGetConfigWriter.Write(testInstance.Path, TestContext.Current.TestPackages);
- testInstance.Restore(Log);
- var commandResolverArguments = new CommandResolverArguments()
- {
- CommandName = "dotnet-portable",
- CommandArguments = null,
- ProjectDirectory = testInstance.Path
- };
- var nugetPackagesRoot = TestContext.Current.TestGlobalPackagesFolder;
- var toolPathCalculator = new ToolPathCalculator(nugetPackagesRoot);
- var lockFilePath = toolPathCalculator.GetLockFilePath(
- "dotnet-portable",
- new NuGetVersion("1.0.0"),
- s_toolPackageFramework);
- var directory = Path.GetDirectoryName(lockFilePath);
- var depsJsonFile = Directory
- .EnumerateFiles(directory)
- .FirstOrDefault(p => Path.GetFileName(p).EndsWith(FileNameSuffixes.DepsJson));
- if (depsJsonFile != null)
- {
- File.Delete(depsJsonFile);
- }
- var result = projectToolsCommandResolver.Resolve(commandResolverArguments);
- result.Should().NotBeNull();
- new DirectoryInfo(directory)
- .Should().HaveFilesMatching("*.deps.json", SearchOption.TopDirectoryOnly);
- }
- [Fact]
- public void GenerateDepsJsonMethodDoesntOverwriteWhenDepsFileAlreadyExists()
- {
- var testInstance = _testAssetsManager.CopyTestAsset(TestProjectName)
- .WithSource()
- .WithRepoGlobalPackages();
- NuGetConfigWriter.Write(testInstance.Path, TestContext.Current.TestPackages);
- testInstance.Restore(Log);
- var toolPathCalculator = new ToolPathCalculator(TestContext.Current.TestGlobalPackagesFolder);
- var lockFilePath = toolPathCalculator.GetLockFilePath(
- "dotnet-portable",
- new NuGetVersion("1.0.0"),
- s_toolPackageFramework);
- var lockFile = new LockFileFormat().Read(lockFilePath);
- // NOTE: We must not use the real deps.json path here as it will interfere with tests running in parallel.
- var depsJsonFile = Path.GetTempFileName();
- File.WriteAllText(depsJsonFile, "temp");
- var projectToolsCommandResolver = SetupProjectToolsCommandResolver();
- projectToolsCommandResolver.GenerateDepsJsonFile(
- lockFile,
- s_toolPackageFramework,
- depsJsonFile,
- new SingleProjectInfo("dotnet-portable", "1.0.0", Enumerable.Empty<ResourceAssemblyInfo>()),
- GetToolDepsJsonGeneratorProject());
- File.ReadAllText(depsJsonFile).Should().Be("temp");
- File.Delete(depsJsonFile);
- }
- [Fact]
- public void ItDoesNotAddFxVersionAsAParamWhenTheToolDoesNotHaveThePrefercliruntimeFile()
- {
- var projectToolsCommandResolver = SetupProjectToolsCommandResolver();
- var testInstance = _testAssetsManager.CopyTestAsset(TestProjectName)
- .WithSource();
- NuGetConfigWriter.Write(testInstance.Path, TestContext.Current.TestPackages);
- testInstance.Restore(Log);
- var commandResolverArguments = new CommandResolverArguments()
- {
- CommandName = "dotnet-portable",
- CommandArguments = null,
- ProjectDirectory = testInstance.Path
- };
- var result = projectToolsCommandResolver.Resolve(commandResolverArguments);
- result.Should().NotBeNull();
- result.Args.Should().NotContain("--fx-version");
- }
- [Fact]
- public void ItFindsToolsLocatedInTheNuGetFallbackFolder()
- {
- var testInstance = _testAssetsManager.CopyTestAsset("AppWithFallbackFolderToolDependency")
- .WithSource();
- var testProjectDirectory = testInstance.Path;
- var fallbackFolder = Path.Combine(testProjectDirectory, "fallbackFolder");
- var nugetConfig = UseNuGetConfigWithFallbackFolder(testInstance, fallbackFolder, TestContext.Current.TestPackages);
- PopulateFallbackFolder(testProjectDirectory, fallbackFolder);
- new DotnetRestoreCommand(Log)
- .WithWorkingDirectory(testProjectDirectory)
- .Execute()
- .Should()
- .Pass();
- new DotnetCommand(Log)
- .WithWorkingDirectory(testProjectDirectory)
- .Execute($"fallbackfoldertool").Should().Pass();
- }
- [Fact]
- public void ItShowsAnErrorWhenTheToolDllIsNotFound()
- {
- var testInstance = _testAssetsManager.CopyTestAsset("AppWithFallbackFolderToolDependency")
- .WithSource();
- var testProjectDirectory = testInstance.Path;
- var fallbackFolder = Path.Combine(testProjectDirectory, "fallbackFolder");
- var nugetPackages = Path.Combine(testProjectDirectory, "nugetPackages");
- var nugetConfig = UseNuGetConfigWithFallbackFolder(testInstance, fallbackFolder, TestContext.Current.TestPackages);
- PopulateFallbackFolder(testProjectDirectory, fallbackFolder);
- new DotnetRestoreCommand(Log)
- .WithWorkingDirectory(testProjectDirectory)
- .Execute($"/p:RestorePackagesPath={nugetPackages}")
- .Should()
- .Pass();
- // We need to run the tool once to generate the deps.json
- // otherwise we end up with a different error message.
- new DotnetCommand(Log)
- .WithWorkingDirectory(testProjectDirectory)
- .Execute("fallbackfoldertool", $"/p:RestorePackagesPath={nugetPackages}").Should().Pass();
- Directory.Delete(Path.Combine(fallbackFolder, "dotnet-fallbackfoldertool"), true);
- new DotnetCommand(Log)
- .WithWorkingDirectory(testProjectDirectory)
- .Execute("fallbackfoldertool", $"/p:RestorePackagesPath={nugetPackages}")
- .Should().Fail().And.NotHaveStdOutContaining(string.Format(LocalizableStrings.CommandAssembliesNotFound, "dotnet-fallbackfoldertool"));
- }
- private void PopulateFallbackFolder(string testProjectDirectory, string fallbackFolder)
- {
- var nugetConfigPath = Path.Combine(testProjectDirectory, "NuGet.Config");
- new DotnetRestoreCommand(Log)
- .WithWorkingDirectory(testProjectDirectory)
- .Execute("--packages", fallbackFolder)
- .Should()
- .Pass();
- Directory.Delete(Path.Combine(fallbackFolder, ".tools"), true);
- }
- private string UseNuGetConfigWithFallbackFolder(TestAsset testInstance, string fallbackFolder, string testPackagesSource)
- {
- var nugetConfig = Path.Combine(testInstance.Path, "NuGet.Config");
- File.WriteAllText(
- nugetConfig,
- $@"<?xml version=""1.0"" encoding=""utf-8""?>
- <configuration>
- <packageSources>
- <add key=""{Guid.NewGuid().ToString()}"" value=""{testPackagesSource}"" />
- </packageSources>
- <fallbackPackageFolders>
- <add key=""MachineWide"" value=""{fallbackFolder}""/>
- </fallbackPackageFolders>
- </configuration>
- ");
- return nugetConfig;
- }
- private ProjectToolsCommandResolver SetupProjectToolsCommandResolver()
- {
- var packagedCommandSpecFactory = new PackagedCommandSpecFactoryWithCliRuntime();
- var projectToolsCommandResolver =
- new ProjectToolsCommandResolver(packagedCommandSpecFactory, new EnvironmentProvider());
- return projectToolsCommandResolver;
- }
- private string GetToolDepsJsonGeneratorProject()
- {
- // When using the product, the ToolDepsJsonGeneratorProject property is used to get this path, but for testing
- // we'll hard code the path inside the SDK since we don't have a project to evaluate here
- return Path.Combine(TestContext.Current.ToolsetUnderTest.SdksPath, "Microsoft.NET.Sdk", "targets", "GenerateDeps", "GenerateDeps.proj");
- }
- }
- }
|