2016-03-07 19:50:52 +00:00
// 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.
2016-10-28 01:46:43 +00:00
using System ;
2016-03-07 19:50:52 +00:00
using System.IO ;
using System.Linq ;
2016-04-28 23:30:32 +00:00
using FluentAssertions ;
2016-10-04 04:40:24 +00:00
using Microsoft.DotNet.Cli.Utils ;
2016-08-10 06:54:37 +00:00
using Microsoft.DotNet.TestFramework ;
2016-03-07 19:50:52 +00:00
using Microsoft.DotNet.Tools.Test.Utilities ;
using NuGet.Frameworks ;
2016-09-26 20:47:55 +00:00
using NuGet.ProjectModel ;
2016-03-17 18:43:17 +00:00
using NuGet.Versioning ;
2016-04-28 23:30:32 +00:00
using Xunit ;
2016-03-07 19:50:52 +00:00
2016-10-04 04:40:24 +00:00
namespace Microsoft.DotNet.Tests
2016-03-07 19:50:52 +00:00
{
2016-08-10 06:54:37 +00:00
public class GivenAProjectToolsCommandResolver : TestBase
2016-03-07 19:50:52 +00:00
{
2016-11-22 21:56:13 +00:00
private static readonly NuGetFramework s_toolPackageFramework =
2017-03-10 05:17:10 +00:00
FrameworkConstants . CommonFrameworks . NetCoreApp20 ;
2016-03-07 19:50:52 +00:00
2016-08-10 06:54:37 +00:00
private const string TestProjectName = "AppWithToolDependency" ;
2016-03-07 19:50:52 +00:00
[Fact]
2017-02-15 19:33:59 +00:00
public void ItReturnsNullWhenCommandNameIsNull ( )
2016-03-07 19:50:52 +00:00
{
var projectToolsCommandResolver = SetupProjectToolsCommandResolver ( ) ;
var commandResolverArguments = new CommandResolverArguments ( )
{
CommandName = null ,
2016-04-28 23:30:32 +00:00
CommandArguments = new string [ ] { "" } ,
2016-03-07 19:50:52 +00:00
ProjectDirectory = "/some/directory"
} ;
var result = projectToolsCommandResolver . Resolve ( commandResolverArguments ) ;
result . Should ( ) . BeNull ( ) ;
}
[Fact]
2017-02-15 19:33:59 +00:00
public void ItReturnsNullWhenProjectDirectoryIsNull ( )
2016-03-07 19:50:52 +00:00
{
var projectToolsCommandResolver = SetupProjectToolsCommandResolver ( ) ;
var commandResolverArguments = new CommandResolverArguments ( )
{
CommandName = "command" ,
2016-04-28 23:30:32 +00:00
CommandArguments = new string [ ] { "" } ,
2016-03-07 19:50:52 +00:00
ProjectDirectory = null
} ;
var result = projectToolsCommandResolver . Resolve ( commandResolverArguments ) ;
result . Should ( ) . BeNull ( ) ;
}
2016-10-28 01:46:43 +00:00
[Fact]
2017-02-15 19:33:59 +00:00
public void ItReturnsNullWhenProjectDirectoryDoesNotContainAProjectFile ( )
2016-10-28 01:46:43 +00:00
{
var projectToolsCommandResolver = SetupProjectToolsCommandResolver ( ) ;
2017-02-15 23:35:03 +00:00
var projectDirectory = TestAssets . CreateTestDirectory ( ) ;
2016-10-28 01:46:43 +00:00
var commandResolverArguments = new CommandResolverArguments ( )
{
CommandName = "command" ,
CommandArguments = new string [ ] { "" } ,
2017-02-15 23:35:03 +00:00
ProjectDirectory = projectDirectory . Root . FullName
2016-10-28 01:46:43 +00:00
} ;
var result = projectToolsCommandResolver . Resolve ( commandResolverArguments ) ;
result . Should ( ) . BeNull ( ) ;
}
2016-03-07 19:50:52 +00:00
[Fact]
2017-02-15 19:33:59 +00:00
public void ItReturnsNullWhenCommandNameDoesNotExistInProjectTools ( )
2016-03-07 19:50:52 +00:00
{
var projectToolsCommandResolver = SetupProjectToolsCommandResolver ( ) ;
2016-11-23 18:19:00 +00:00
var testInstance = TestAssets . Get ( TestProjectName )
. CreateInstance ( )
. WithSourceFiles ( )
. WithRestoreFiles ( ) ;
2016-08-10 06:54:37 +00:00
2016-03-07 19:50:52 +00:00
var commandResolverArguments = new CommandResolverArguments ( )
{
CommandName = "nonexistent-command" ,
CommandArguments = null ,
2016-11-23 18:19:00 +00:00
ProjectDirectory = testInstance . Root . FullName
2016-03-07 19:50:52 +00:00
} ;
var result = projectToolsCommandResolver . Resolve ( commandResolverArguments ) ;
result . Should ( ) . BeNull ( ) ;
}
[Fact]
2017-02-15 19:33:59 +00:00
public void ItReturnsACommandSpecWithDOTNETAsFileNameAndCommandNameInArgsWhenCommandNameExistsInProjectTools ( )
2016-03-07 19:50:52 +00:00
{
var projectToolsCommandResolver = SetupProjectToolsCommandResolver ( ) ;
2016-11-23 18:19:00 +00:00
var testInstance = TestAssets . Get ( TestProjectName )
. CreateInstance ( )
. WithSourceFiles ( )
. WithRestoreFiles ( ) ;
2016-08-10 06:54:37 +00:00
2016-03-07 19:50:52 +00:00
var commandResolverArguments = new CommandResolverArguments ( )
{
2016-03-17 18:43:17 +00:00
CommandName = "dotnet-portable" ,
2016-03-07 19:50:52 +00:00
CommandArguments = null ,
2016-11-23 18:19:00 +00:00
ProjectDirectory = testInstance . Root . FullName
2016-03-07 19:50:52 +00:00
} ;
var result = projectToolsCommandResolver . Resolve ( commandResolverArguments ) ;
result . Should ( ) . NotBeNull ( ) ;
var commandFile = Path . GetFileNameWithoutExtension ( result . Path ) ;
2016-03-17 21:41:56 +00:00
commandFile . Should ( ) . Be ( "dotnet" ) ;
2016-03-07 19:50:52 +00:00
result . Args . Should ( ) . Contain ( commandResolverArguments . CommandName ) ;
}
[Fact]
2017-02-15 19:33:59 +00:00
public void ItEscapesCommandArgumentsWhenReturningACommandSpec ( )
2016-03-07 19:50:52 +00:00
{
var projectToolsCommandResolver = SetupProjectToolsCommandResolver ( ) ;
2016-10-28 01:46:43 +00:00
var testInstance = TestAssets . Get ( TestProjectName )
. CreateInstance ( )
. WithSourceFiles ( )
. WithRestoreFiles ( ) ;
2016-08-10 06:54:37 +00:00
2016-03-07 19:50:52 +00:00
var commandResolverArguments = new CommandResolverArguments ( )
{
2016-03-17 18:43:17 +00:00
CommandName = "dotnet-portable" ,
2016-04-28 23:30:32 +00:00
CommandArguments = new [ ] { "arg with space" } ,
2016-10-28 01:46:43 +00:00
ProjectDirectory = testInstance . Root . FullName
2016-03-07 19:50:52 +00:00
} ;
var result = projectToolsCommandResolver . Resolve ( commandResolverArguments ) ;
2016-10-28 01:46:43 +00:00
result . Should ( ) . NotBeNull ( "Because the command is a project tool dependency" ) ;
2016-03-07 19:50:52 +00:00
result . Args . Should ( ) . Contain ( "\"arg with space\"" ) ;
}
[Fact]
2017-02-15 19:33:59 +00:00
public void ItReturnsACommandSpecWithArgsContainingCommandPathWhenReturningACommandSpecAndCommandArgumentsAreNull ( )
2016-03-07 19:50:52 +00:00
{
var projectToolsCommandResolver = SetupProjectToolsCommandResolver ( ) ;
2016-10-28 01:46:43 +00:00
var testInstance = TestAssets . Get ( TestProjectName )
. CreateInstance ( )
. WithSourceFiles ( )
. WithRestoreFiles ( ) ;
2016-08-10 06:54:37 +00:00
2016-03-07 19:50:52 +00:00
var commandResolverArguments = new CommandResolverArguments ( )
{
2016-03-17 18:43:17 +00:00
CommandName = "dotnet-portable" ,
2016-03-07 19:50:52 +00:00
CommandArguments = null ,
2016-10-28 01:46:43 +00:00
ProjectDirectory = testInstance . Root . FullName
2016-03-07 19:50:52 +00:00
} ;
var result = projectToolsCommandResolver . Resolve ( commandResolverArguments ) ;
result . Should ( ) . NotBeNull ( ) ;
2016-04-28 23:30:32 +00:00
2016-03-07 19:50:52 +00:00
var commandPath = result . Args . Trim ( '"' ) ;
2016-03-17 18:43:17 +00:00
commandPath . Should ( ) . Contain ( "dotnet-portable.dll" ) ;
}
[Fact]
2017-02-15 19:33:59 +00:00
public void ItReturnsACommandSpecWithArgsContainingCommandPathWhenInvokingAToolReferencedWithADifferentCasing ( )
{
var projectToolsCommandResolver = SetupProjectToolsCommandResolver ( ) ;
var testInstance = TestAssets . Get ( TestProjectName )
. CreateInstance ( )
. WithSourceFiles ( )
. WithRestoreFiles ( ) ;
var commandResolverArguments = new CommandResolverArguments ( )
{
CommandName = "dotnet-prefercliruntime" ,
CommandArguments = null ,
ProjectDirectory = testInstance . Root . FullName
} ;
var result = projectToolsCommandResolver . Resolve ( commandResolverArguments ) ;
result . Should ( ) . NotBeNull ( ) ;
var commandPath = result . Args . Trim ( '"' ) ;
commandPath . Should ( ) . Contain ( "dotnet-prefercliruntime.dll" ) ;
}
[Fact]
public void ItWritesADepsJsonFileNextToTheLockfile ( )
2016-03-17 18:43:17 +00:00
{
var projectToolsCommandResolver = SetupProjectToolsCommandResolver ( ) ;
2016-10-28 01:46:43 +00:00
var testInstance = TestAssets . Get ( TestProjectName )
. CreateInstance ( )
. WithSourceFiles ( )
. WithRestoreFiles ( ) ;
2016-08-10 06:54:37 +00:00
2016-03-17 18:43:17 +00:00
var commandResolverArguments = new CommandResolverArguments ( )
{
CommandName = "dotnet-portable" ,
CommandArguments = null ,
2016-10-28 01:46:43 +00:00
ProjectDirectory = testInstance . Root . FullName
2016-03-17 18:43:17 +00:00
} ;
2016-10-28 01:46:43 +00:00
var repoDirectoriesProvider = new RepoDirectoriesProvider ( ) ;
var nugetPackagesRoot = repoDirectoriesProvider . NugetPackages ;
2016-03-17 18:43:17 +00:00
var toolPathCalculator = new ToolPathCalculator ( nugetPackagesRoot ) ;
var lockFilePath = toolPathCalculator . GetLockFilePath (
2016-04-28 23:30:32 +00:00
"dotnet-portable" ,
new NuGetVersion ( "1.0.0" ) ,
2016-03-17 18:43:17 +00:00
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 ) ;
2016-04-28 23:30:32 +00:00
2016-10-28 01:46:43 +00:00
result . Should ( ) . NotBeNull ( ) ;
2016-03-07 19:50:52 +00:00
2016-10-28 01:46:43 +00:00
new DirectoryInfo ( directory )
. Should ( ) . HaveFilesMatching ( "*.deps.json" , SearchOption . TopDirectoryOnly ) ;
2016-03-07 19:50:52 +00:00
}
2016-04-09 00:07:29 +00:00
[Fact]
2017-02-15 19:33:59 +00:00
public void GenerateDepsJsonMethodDoesntOverwriteWhenDepsFileAlreadyExists ( )
2016-04-09 00:07:29 +00:00
{
2016-10-28 01:46:43 +00:00
var testInstance = TestAssets . Get ( TestProjectName )
. CreateInstance ( )
. WithSourceFiles ( )
. WithRestoreFiles ( ) ;
2016-08-10 06:54:37 +00:00
2016-10-28 01:46:43 +00:00
var repoDirectoriesProvider = new RepoDirectoriesProvider ( ) ;
var nugetPackagesRoot = repoDirectoriesProvider . NugetPackages ;
2016-04-09 00:07:29 +00:00
var toolPathCalculator = new ToolPathCalculator ( nugetPackagesRoot ) ;
var lockFilePath = toolPathCalculator . GetLockFilePath (
2016-04-28 23:30:32 +00:00
"dotnet-portable" ,
new NuGetVersion ( "1.0.0" ) ,
2016-04-09 00:07:29 +00:00
s_toolPackageFramework ) ;
2016-09-26 20:47:55 +00:00
var lockFile = new LockFileFormat ( ) . Read ( lockFilePath ) ;
2016-04-09 00:07:29 +00:00
var depsJsonFile = Path . Combine (
Path . GetDirectoryName ( lockFilePath ) ,
"dotnet-portable.deps.json" ) ;
if ( File . Exists ( depsJsonFile ) )
{
File . Delete ( depsJsonFile ) ;
}
File . WriteAllText ( depsJsonFile , "temp" ) ;
var projectToolsCommandResolver = SetupProjectToolsCommandResolver ( ) ;
2016-10-05 01:58:04 +00:00
projectToolsCommandResolver . GenerateDepsJsonFile (
lockFile ,
2017-02-20 16:01:29 +00:00
s_toolPackageFramework ,
2016-10-05 01:58:04 +00:00
depsJsonFile ,
2017-04-21 23:14:44 +00:00
new SingleProjectInfo ( "dotnet-portable" , "1.0.0" , Enumerable . Empty < ResourceAssemblyInfo > ( ) ) ,
GetToolDepsJsonGeneratorProject ( ) ) ;
2016-04-09 00:07:29 +00:00
File . ReadAllText ( depsJsonFile ) . Should ( ) . Be ( "temp" ) ;
2016-04-02 01:49:36 +00:00
File . Delete ( depsJsonFile ) ;
2016-04-09 00:07:29 +00:00
}
2016-11-22 21:56:13 +00:00
[Fact]
2017-02-15 19:33:59 +00:00
public void ItAddsFxVersionAsAParamWhenTheToolHasThePrefercliruntimeFile ( )
2016-11-22 21:56:13 +00:00
{
var projectToolsCommandResolver = SetupProjectToolsCommandResolver ( ) ;
2016-11-23 18:19:00 +00:00
var testInstance = TestAssets . Get ( "MSBuildTestApp" )
. CreateInstance ( )
. WithSourceFiles ( )
. WithRestoreFiles ( ) ;
2016-11-22 21:56:13 +00:00
var commandResolverArguments = new CommandResolverArguments ( )
{
CommandName = "dotnet-prefercliruntime" ,
CommandArguments = null ,
2016-11-23 18:19:00 +00:00
ProjectDirectory = testInstance . Root . FullName
2016-11-22 21:56:13 +00:00
} ;
var result = projectToolsCommandResolver . Resolve ( commandResolverArguments ) ;
result . Should ( ) . NotBeNull ( ) ;
2017-01-26 03:19:44 +00:00
result . Args . Should ( ) . Contain ( "--fx-version 2.0.0" ) ;
2016-11-22 21:56:13 +00:00
}
[Fact]
2017-02-15 19:33:59 +00:00
public void ItDoesNotAddFxVersionAsAParamWhenTheToolDoesNotHaveThePrefercliruntimeFile ( )
2016-11-22 21:56:13 +00:00
{
var projectToolsCommandResolver = SetupProjectToolsCommandResolver ( ) ;
2016-11-23 18:19:00 +00:00
var testInstance = TestAssets . Get ( TestProjectName )
. CreateInstance ( )
. WithSourceFiles ( )
. WithRestoreFiles ( ) ;
2016-11-22 21:56:13 +00:00
var commandResolverArguments = new CommandResolverArguments ( )
{
CommandName = "dotnet-portable" ,
CommandArguments = null ,
2016-11-23 18:19:00 +00:00
ProjectDirectory = testInstance . Root . FullName
2016-11-22 21:56:13 +00:00
} ;
var result = projectToolsCommandResolver . Resolve ( commandResolverArguments ) ;
result . Should ( ) . NotBeNull ( ) ;
2016-11-23 20:56:37 +00:00
result . Args . Should ( ) . NotContain ( "--fx-version" ) ;
2016-11-22 21:56:13 +00:00
}
2017-03-24 05:20:47 +00:00
[Fact]
public void ItFindsToolsLocatedInTheNuGetFallbackFolder ( )
{
var projectToolsCommandResolver = SetupProjectToolsCommandResolver ( ) ;
var testInstance = TestAssets . Get ( "AppWithFallbackFolderToolDependency" )
. CreateInstance ( )
2017-04-04 05:15:40 +00:00
. WithSourceFiles ( )
. WithNuGetConfig ( new RepoDirectoriesProvider ( ) . TestPackages ) ;
2017-03-24 05:20:47 +00:00
var testProjectDirectory = testInstance . Root . FullName ;
var fallbackFolder = Path . Combine ( testProjectDirectory , "fallbackFolder" ) ;
PopulateFallbackFolder ( testProjectDirectory , fallbackFolder ) ;
2017-03-27 04:52:27 +00:00
var nugetConfig = UseNuGetConfigWithFallbackFolder ( testInstance , fallbackFolder ) ;
2017-03-24 05:20:47 +00:00
new RestoreCommand ( )
. WithWorkingDirectory ( testProjectDirectory )
. Execute ( $"--configfile {nugetConfig}" )
. Should ( )
. Pass ( ) ;
var commandResolverArguments = new CommandResolverArguments ( )
{
CommandName = "dotnet-fallbackfoldertool" ,
CommandArguments = null ,
ProjectDirectory = testProjectDirectory
} ;
var result = projectToolsCommandResolver . Resolve ( commandResolverArguments ) ;
result . Should ( ) . NotBeNull ( ) ;
2017-03-24 05:26:25 +00:00
var commandPath = result . Args . Trim ( '"' ) ;
commandPath . Should ( ) . Contain ( Path . Combine (
fallbackFolder ,
"dotnet-fallbackfoldertool" ,
"1.0.0" ,
"lib" ,
"netcoreapp2.0" ,
"dotnet-fallbackfoldertool.dll" ) ) ;
2017-03-24 05:20:47 +00:00
}
2017-03-27 04:52:27 +00:00
[Fact]
2017-04-04 05:15:40 +00:00
public void ItShowsAnErrorWhenTheToolDllIsNotFound ( )
2017-03-27 04:52:27 +00:00
{
var projectToolsCommandResolver = SetupProjectToolsCommandResolver ( ) ;
var testInstance = TestAssets . Get ( "AppWithFallbackFolderToolDependency" )
. CreateInstance ( )
2017-04-04 05:15:40 +00:00
. WithSourceFiles ( )
. WithNuGetConfig ( new RepoDirectoriesProvider ( ) . TestPackages ) ;
2017-03-27 04:52:27 +00:00
var testProjectDirectory = testInstance . Root . FullName ;
var fallbackFolder = Path . Combine ( testProjectDirectory , "fallbackFolder" ) ;
PopulateFallbackFolder ( testProjectDirectory , fallbackFolder ) ;
var nugetConfig = UseNuGetConfigWithFallbackFolder ( testInstance , fallbackFolder ) ;
new RestoreCommand ( )
. WithWorkingDirectory ( testProjectDirectory )
. Execute ( $"--configfile {nugetConfig}" )
. Should ( )
. Pass ( ) ;
Directory . Delete ( Path . Combine ( fallbackFolder , "dotnet-fallbackfoldertool" ) , true ) ;
var commandResolverArguments = new CommandResolverArguments ( )
{
CommandName = "dotnet-fallbackfoldertool" ,
CommandArguments = null ,
ProjectDirectory = testProjectDirectory
} ;
Action action = ( ) = > projectToolsCommandResolver . Resolve ( commandResolverArguments ) ;
action . ShouldThrow < GracefulException > ( ) . WithMessage (
"The command executable for \"dotnet-fallbackfoldertool\" was not found. The project may not have been restored or restore failed - run `dotnet restore`" ) ;
}
2017-03-24 05:20:47 +00:00
private void PopulateFallbackFolder ( string testProjectDirectory , string fallbackFolder )
{
2017-04-04 05:15:40 +00:00
var nugetConfigPath = Path . Combine ( testProjectDirectory , "NuGet.Config" ) ;
2017-03-24 05:20:47 +00:00
new RestoreCommand ( )
. WithWorkingDirectory ( testProjectDirectory )
2017-04-04 05:15:40 +00:00
. Execute ( $"--configfile {nugetConfigPath} --packages {fallbackFolder}" )
2017-03-24 05:20:47 +00:00
. Should ( )
. Pass ( ) ;
Directory . Delete ( Path . Combine ( fallbackFolder , ".tools" ) , true ) ;
}
2017-03-27 04:52:27 +00:00
private string UseNuGetConfigWithFallbackFolder ( TestAssetInstance testInstance , string fallbackFolder )
{
var nugetConfig = testInstance . Root . GetFile ( "NuGet.Config" ) . FullName ;
File . WriteAllText (
nugetConfig ,
$@"<?xml version=""1.0"" encoding=""utf-8" "?>
< configuration >
< fallbackPackageFolders >
< add key = "" MachineWide "" value = "" { fallbackFolder } "" / >
< / fallbackPackageFolders >
< / configuration >
");
return nugetConfig ;
}
2016-11-22 21:56:13 +00:00
private ProjectToolsCommandResolver SetupProjectToolsCommandResolver ( )
2016-03-07 19:50:52 +00:00
{
2016-10-28 01:46:43 +00:00
Environment . SetEnvironmentVariable (
Constants . MSBUILD_EXE_PATH ,
Path . Combine ( new RepoDirectoriesProvider ( ) . Stage2Sdk , "MSBuild.dll" ) ) ;
2016-11-22 21:56:13 +00:00
var packagedCommandSpecFactory = new PackagedCommandSpecFactoryWithCliRuntime ( ) ;
2016-03-07 19:50:52 +00:00
2016-11-22 21:56:13 +00:00
var projectToolsCommandResolver =
new ProjectToolsCommandResolver ( packagedCommandSpecFactory , new EnvironmentProvider ( ) ) ;
2016-03-07 19:50:52 +00:00
return projectToolsCommandResolver ;
}
2017-04-21 23:14:44 +00:00
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
2017-04-26 21:57:18 +00:00
return Path . Combine ( new RepoDirectoriesProvider ( ) . Stage2Sdk , "Sdks" , "Microsoft.NET.Sdk" , "build" , "GenerateDeps" , "GenerateDeps.proj" ) ;
2017-04-21 23:14:44 +00:00
}
2016-03-07 19:50:52 +00:00
}
}