Merge pull request #4972 from krwq/p2p-compat-check

add compat checks to dotnet add
This commit is contained in:
Krzysztof Wicher 2016-12-09 15:32:15 -08:00 committed by GitHub
commit 8eaec8715b
14 changed files with 397 additions and 60 deletions

View file

@ -4,7 +4,7 @@
<PropertyGroup>
<OutputType>Library</OutputType>
<TargetFrameworks>net451;netcoreapp1.0</TargetFrameworks>
<TargetFrameworks>net451;netcoreapp1.0;netstandard1.4</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<Compile Include="**\*.cs" />

View file

@ -0,0 +1,3 @@
public class Net452AndNetCoreApp10Lib
{
}

View file

@ -0,0 +1,25 @@
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" />
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
<OutputType>Library</OutputType>
<TargetFrameworks>net452;netcoreapp1.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<Compile Include="**\*.cs" />
<EmbeddedResource Include="**\*.resx" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Sdk">
<Version>$(CLI_NETSDK_Version)</Version>
<PrivateAssets>All</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netcoreapp1.0' ">
<PackageReference Include="Microsoft.NETCore.App">
<Version>1.0.1</Version>
</PackageReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View file

@ -0,0 +1,3 @@
public class Net45Lib
{
}

View file

@ -0,0 +1,25 @@
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" />
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
<OutputType>Library</OutputType>
<TargetFrameworks>net45</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<Compile Include="**\*.cs" />
<EmbeddedResource Include="**\*.resx" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Sdk">
<Version>$(CLI_NETSDK_Version)</Version>
<PrivateAssets>All</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netcoreapp1.0' ">
<PackageReference Include="Microsoft.NETCore.App">
<Version>1.0.1</Version>
</PackageReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View file

@ -4,7 +4,7 @@
<PropertyGroup>
<OutputType>Library</OutputType>
<TargetFrameworks>net451;netcoreapp1.0</TargetFrameworks>
<TargetFrameworks>net451;netcoreapp1.0;netstandard1.4</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<Compile Include="**\*.cs" />

View file

@ -179,5 +179,9 @@
public const string SpecifiedNameExists = "Specified name {0} already exists. Please specify a different name.";
public const string SpecifiedAliasExists = "Specified alias {0} already exists. Please specify a different alias.";
public const string MandatoryParameterMissing = "Mandatory parameter {0} missing for template {1}. ";
public const string ProjectNotCompatibleWithFrameworks = "Project `{0}` cannot be added due to incompatible targeted frameworks between the two projects. Please review the project you are trying to add and verify that is compatible with the following targets:";
public const string ProjectDoesNotTargetFramework = "Project `{0}` does not target framework `{1}`.";
public const string ProjectCouldNotBeEvaluated = "Project `{0}` could not be evaluated. Evaluation failed with following error:\n{1}";
}
}

View file

@ -3,8 +3,11 @@
using Microsoft.Build.Construction;
using Microsoft.Build.Evaluation;
using Microsoft.Build.Exceptions;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.Tools.Common;
using Microsoft.DotNet.Tools.ProjectExtensions;
using NuGet.Frameworks;
using System;
using System.Collections.Generic;
using System.IO;
@ -16,44 +19,48 @@ namespace Microsoft.DotNet.Tools
{
const string ProjectItemElementType = "ProjectReference";
public ProjectRootElement Project { get; private set; }
public ProjectRootElement ProjectRootElement { get; private set; }
public string ProjectDirectory { get; private set; }
private MsbuildProject(ProjectRootElement project)
private ProjectCollection _projects;
private List<NuGetFramework> _cachedTfms = null;
private MsbuildProject(ProjectCollection projects, ProjectRootElement project)
{
Project = project;
ProjectDirectory = PathUtility.EnsureTrailingSlash(Project.DirectoryPath);
_projects = projects;
ProjectRootElement = project;
ProjectDirectory = PathUtility.EnsureTrailingSlash(ProjectRootElement.DirectoryPath);
}
public static MsbuildProject FromFileOrDirectory(string fileOrDirectory)
public static MsbuildProject FromFileOrDirectory(ProjectCollection projects, string fileOrDirectory)
{
if (File.Exists(fileOrDirectory))
{
return FromFile(fileOrDirectory);
return FromFile(projects, fileOrDirectory);
}
else
{
return FromDirectory(fileOrDirectory);
return FromDirectory(projects, fileOrDirectory);
}
}
public static MsbuildProject FromFile(string projectPath)
public static MsbuildProject FromFile(ProjectCollection projects, string projectPath)
{
if (!File.Exists(projectPath))
{
throw new GracefulException(CommonLocalizableStrings.ProjectDoesNotExist, projectPath);
}
var project = TryOpenProject(projectPath);
var project = TryOpenProject(projects, projectPath);
if (project == null)
{
throw new GracefulException(CommonLocalizableStrings.ProjectIsInvalid, projectPath);
}
return new MsbuildProject(project);
return new MsbuildProject(projects, project);
}
public static MsbuildProject FromDirectory(string projectDirectory)
public static MsbuildProject FromDirectory(ProjectCollection projects, string projectDirectory)
{
DirectoryInfo dir;
try
@ -73,7 +80,9 @@ namespace Microsoft.DotNet.Tools
FileInfo[] files = dir.GetFiles("*proj");
if (files.Length == 0)
{
throw new GracefulException(CommonLocalizableStrings.CouldNotFindAnyProjectInDirectory, projectDirectory);
throw new GracefulException(
CommonLocalizableStrings.CouldNotFindAnyProjectInDirectory,
projectDirectory);
}
if (files.Length > 1)
@ -85,33 +94,39 @@ namespace Microsoft.DotNet.Tools
if (!projectFile.Exists)
{
throw new GracefulException(CommonLocalizableStrings.CouldNotFindAnyProjectInDirectory, projectDirectory);
throw new GracefulException(
CommonLocalizableStrings.CouldNotFindAnyProjectInDirectory,
projectDirectory);
}
var project = TryOpenProject(projectFile.FullName);
var project = TryOpenProject(projects, projectFile.FullName);
if (project == null)
{
throw new GracefulException(CommonLocalizableStrings.FoundInvalidProject, projectFile.FullName);
}
return new MsbuildProject(project);
return new MsbuildProject(projects, project);
}
public int AddProjectToProjectReferences(string framework, IEnumerable<string> refs)
{
int numberOfAddedReferences = 0;
ProjectItemGroupElement itemGroup = Project.FindUniformOrCreateItemGroupWithCondition(ProjectItemElementType, framework);
ProjectItemGroupElement itemGroup = ProjectRootElement.FindUniformOrCreateItemGroupWithCondition(
ProjectItemElementType,
framework);
foreach (var @ref in refs.Select((r) => NormalizeSlashes(r)))
{
if (Project.HasExistingItemWithCondition(framework, @ref))
if (ProjectRootElement.HasExistingItemWithCondition(framework, @ref))
{
Reporter.Output.WriteLine(string.Format(CommonLocalizableStrings.ProjectAlreadyHasAreference, @ref));
Reporter.Output.WriteLine(string.Format(
CommonLocalizableStrings.ProjectAlreadyHasAreference,
@ref));
continue;
}
numberOfAddedReferences++;
itemGroup.AppendChild(Project.CreateItemElement(ProjectItemElementType, @ref));
itemGroup.AppendChild(ProjectRootElement.CreateItemElement(ProjectItemElementType, @ref));
Reporter.Output.WriteLine(string.Format(CommonLocalizableStrings.ReferenceAddedToTheProject, @ref));
}
@ -133,12 +148,16 @@ namespace Microsoft.DotNet.Tools
public IEnumerable<ProjectItemElement> GetProjectToProjectReferences()
{
return Project.GetAllItemsWithElementType(ProjectItemElementType);
return ProjectRootElement.GetAllItemsWithElementType(ProjectItemElementType);
}
public void ConvertPathsToRelative(ref List<string> references)
{
references = references.Select((r) => PathUtility.GetRelativePath(ProjectDirectory, Path.GetFullPath(r))).ToList();
references = references.Select((r) =>
PathUtility.GetRelativePath(
ProjectDirectory,
Path.GetFullPath(r)))
.ToList();
}
public static string NormalizeSlashes(string path)
@ -166,12 +185,64 @@ namespace Microsoft.DotNet.Tools
}
}
public IEnumerable<NuGetFramework> GetTargetFrameworks()
{
if (_cachedTfms != null)
{
return _cachedTfms;
}
var project = GetEvaluatedProject();
_cachedTfms = project.GetTargetFrameworks().ToList();
return _cachedTfms;
}
public bool CanWorkOnFramework(NuGetFramework framework)
{
foreach (var tfm in GetTargetFrameworks())
{
if (DefaultCompatibilityProvider.Instance.IsCompatible(framework, tfm))
{
return true;
}
}
return false;
}
public bool IsTargettingFramework(NuGetFramework framework)
{
foreach (var tfm in GetTargetFrameworks())
{
if (framework.Equals(tfm))
{
return true;
}
}
return false;
}
private Project GetEvaluatedProject()
{
try
{
return _projects.LoadProject(ProjectRootElement.FullPath);
}
catch (InvalidProjectFileException e)
{
throw new GracefulException(string.Format(
CommonLocalizableStrings.ProjectCouldNotBeEvaluated,
ProjectRootElement.FullPath, e.Message));
}
}
private int RemoveProjectToProjectReferenceAlternatives(string framework, string reference)
{
int numberOfRemovedRefs = 0;
foreach (var r in GetIncludeAlternativesForRemoval(reference))
{
foreach (var existingItem in Project.FindExistingItemsWithCondition(framework, r))
foreach (var existingItem in ProjectRootElement.FindExistingItemsWithCondition(framework, r))
{
ProjectElementContainer itemGroup = existingItem.Parent;
itemGroup.RemoveChild(existingItem);
@ -187,7 +258,9 @@ namespace Microsoft.DotNet.Tools
if (numberOfRemovedRefs == 0)
{
Reporter.Output.WriteLine(string.Format(CommonLocalizableStrings.ProjectReferenceCouldNotBeFound, reference));
Reporter.Output.WriteLine(string.Format(
CommonLocalizableStrings.ProjectReferenceCouldNotBeFound,
reference));
}
return numberOfRemovedRefs;
@ -219,13 +292,13 @@ namespace Microsoft.DotNet.Tools
// There is ProjectRootElement.TryOpen but it does not work as expected
// I.e. it returns null for some valid projects
private static ProjectRootElement TryOpenProject(string filename)
private static ProjectRootElement TryOpenProject(ProjectCollection projects, string filename)
{
try
{
return ProjectRootElement.Open(filename, new ProjectCollection(), preserveFormatting: true);
return ProjectRootElement.Open(filename, projects, preserveFormatting: true);
}
catch (Microsoft.Build.Exceptions.InvalidProjectFileException)
catch (InvalidProjectFileException)
{
return null;
}

View file

@ -0,0 +1,36 @@
// 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.Build.Construction;
using Microsoft.Build.Evaluation;
using Microsoft.DotNet.ProjectJsonMigration;
using NuGet.Frameworks;
using System.Collections.Generic;
using System.Linq;
namespace Microsoft.DotNet.Tools.ProjectExtensions
{
internal static class ProjectExtensions
{
public static IEnumerable<NuGetFramework> GetTargetFrameworks(this Project project)
{
var targetFramewoksStrings = project
.GetPropertyCommaSeparatedValues("TargetFramework")
.Union(project.GetPropertyCommaSeparatedValues("TargetFrameworks"))
.Select((value) => value.ToLower());
var uniqueTargetFrameworkStrings = new HashSet<string>(targetFramewoksStrings);
return uniqueTargetFrameworkStrings
.Select((frameworkString) => NuGetFramework.Parse(frameworkString));
}
public static IEnumerable<string> GetPropertyCommaSeparatedValues(this Project project, string propertyName)
{
return project.GetPropertyValue(propertyName)
.Split(';')
.Select((value) => value.Trim())
.Where((value) => !string.IsNullOrEmpty(value));
}
}
}

View file

@ -1,9 +1,13 @@
// 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.Build.Evaluation;
using Microsoft.DotNet.Cli.CommandLine;
using Microsoft.DotNet.Cli.Utils;
using NuGet.Frameworks;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Microsoft.DotNet.Tools.Add.ProjectToProjectReference
{
@ -44,17 +48,58 @@ namespace Microsoft.DotNet.Tools.Add.ProjectToProjectReference
throw new GracefulException(CommonLocalizableStrings.RequiredArgumentNotPassed, $"<{LocalizableStrings.ProjectException}>");
}
var msbuildProj = MsbuildProject.FromFileOrDirectory(projectArgument.Value);
var projects = new ProjectCollection();
var msbuildProj = MsbuildProject.FromFileOrDirectory(projects, projectArgument.Value);
if (app.RemainingArguments.Count == 0)
{
throw new GracefulException(LocalizableStrings.SpecifyAtLeastOneReferenceToAdd);
}
string frameworkString = frameworkOption.Value();
List<string> references = app.RemainingArguments;
if (!forceOption.HasValue())
{
MsbuildProject.EnsureAllReferencesExist(references);
IEnumerable<MsbuildProject> refs = references.Select((r) => MsbuildProject.FromFile(projects, r));
if (frameworkString == null)
{
foreach (var tfm in msbuildProj.GetTargetFrameworks())
{
foreach (var @ref in refs)
{
if (!@ref.CanWorkOnFramework(tfm))
{
Reporter.Error.Write(GetProjectNotCompatibleWithFrameworksDisplayString(
@ref,
msbuildProj.GetTargetFrameworks().Select((fx) => fx.GetShortFolderName())));
return 1;
}
}
}
}
else
{
var framework = NuGetFramework.Parse(frameworkString);
if (!msbuildProj.IsTargettingFramework(framework))
{
Reporter.Error.WriteLine(string.Format(CommonLocalizableStrings.ProjectDoesNotTargetFramework, msbuildProj.ProjectRootElement.FullPath, frameworkString));
return 1;
}
foreach (var @ref in refs)
{
if (!@ref.CanWorkOnFramework(framework))
{
Reporter.Error.Write(GetProjectNotCompatibleWithFrameworksDisplayString(
@ref,
new string[] { frameworkString }));
return 1;
}
}
}
msbuildProj.ConvertPathsToRelative(ref references);
}
@ -64,7 +109,7 @@ namespace Microsoft.DotNet.Tools.Add.ProjectToProjectReference
if (numberOfAddedReferences != 0)
{
msbuildProj.Project.Save();
msbuildProj.ProjectRootElement.Save();
}
return 0;
@ -81,5 +126,17 @@ namespace Microsoft.DotNet.Tools.Add.ProjectToProjectReference
return 1;
}
}
private static string GetProjectNotCompatibleWithFrameworksDisplayString(MsbuildProject project, IEnumerable<string> frameworksDisplayStrings)
{
var sb = new StringBuilder();
sb.AppendLine(string.Format(CommonLocalizableStrings.ProjectNotCompatibleWithFrameworks, project.ProjectRootElement.FullPath));
foreach (var tfm in frameworksDisplayStrings)
{
sb.AppendLine($" - {tfm}");
}
return sb.ToString();
}
}
}

View file

@ -1,6 +1,7 @@
// 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.Build.Evaluation;
using Microsoft.DotNet.Cli.CommandLine;
using Microsoft.DotNet.Cli.Utils;
using System.Collections.Generic;
@ -31,7 +32,7 @@ namespace Microsoft.DotNet.Tools.List.ProjectToProjectReferences
throw new GracefulException(CommonLocalizableStrings.RequiredArgumentNotPassed, $"<{LocalizableStrings.ProjectArgumentValueName}>");
}
var msbuildProj = MsbuildProject.FromFileOrDirectory(projectArgument.Value);
var msbuildProj = MsbuildProject.FromFileOrDirectory(new ProjectCollection(), projectArgument.Value);
var p2ps = msbuildProj.GetProjectToProjectReferences();
if (p2ps.Count() == 0)

View file

@ -1,6 +1,7 @@
// 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.Build.Evaluation;
using Microsoft.DotNet.Cli.CommandLine;
using Microsoft.DotNet.Cli.Utils;
using System.Collections.Generic;
@ -39,7 +40,7 @@ namespace Microsoft.DotNet.Tools.Remove.ProjectToProjectReference
throw new GracefulException(CommonLocalizableStrings.RequiredArgumentNotPassed, $"<{LocalizableStrings.ProjectException}>");
}
var msbuildProj = MsbuildProject.FromFileOrDirectory(projectArgument.Value);
var msbuildProj = MsbuildProject.FromFileOrDirectory(new ProjectCollection(), projectArgument.Value);
if (app.RemainingArguments.Count == 0)
{
@ -54,7 +55,7 @@ namespace Microsoft.DotNet.Tools.Remove.ProjectToProjectReference
if (numberOfRemovedReferences != 0)
{
msbuildProj.Project.Save();
msbuildProj.ProjectRootElement.Save();
}
return 0;

View file

@ -7,6 +7,7 @@ using Microsoft.DotNet.Tools.Test.Utilities;
using Msbuild.Tests.Utilities;
using System;
using System.IO;
using System.Linq;
using Xunit;
namespace Microsoft.DotNet.Cli.Add.P2P.Tests
@ -17,6 +18,9 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
const string ConditionFrameworkNet451 = "== 'net451'";
const string FrameworkNetCoreApp10Arg = "-f netcoreapp1.0";
const string ConditionFrameworkNetCoreApp10 = "== 'netcoreapp1.0'";
const string ProjectNotCompatibleErrorMessageRegEx = "Project `[^`]*` cannot be added due to incompatible targeted frameworks between the two projects\\. Please review the project you are trying to add and verify that is compatible with the following targets\\:";
const string ProjectDoesNotTargetFrameworkErrorMessageRegEx = "Project `[^`]*` does not target framework `[^`]*`.";
static readonly string[] DefaultFrameworks = new string[] { "netcoreapp1.0", "net451" };
private TestSetup Setup([System.Runtime.CompilerServices.CallerMemberName] string callingMethod = nameof(Setup), string identifier = "")
{
@ -52,6 +56,20 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
return dir;
}
private static void SetTargetFrameworks(ProjDir proj, string[] frameworks)
{
var csproj = proj.CsProj();
csproj.AddProperty("TargetFrameworks", string.Join(";", frameworks));
csproj.Save();
}
private ProjDir NewLibWithFrameworks([System.Runtime.CompilerServices.CallerMemberName] string callingMethod = nameof(NewDir), string identifier = "")
{
var ret = NewLib(callingMethod: callingMethod, identifier: identifier);
SetTargetFrameworks(ret, DefaultFrameworks);
return ret;
}
[Theory]
[InlineData("--help")]
[InlineData("-h")]
@ -122,7 +140,7 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
[Fact]
public void ItAddsRefWithoutCondAndPrintsStatus()
{
var lib = NewLib();
var lib = NewLibWithFrameworks();
var setup = Setup();
int noCondBefore = lib.CsProj().NumberOfItemGroupsWithoutCondition();
@ -141,7 +159,7 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
[Fact]
public void ItAddsRefWithCondAndPrintsStatus()
{
var lib = NewLib();
var lib = NewLibWithFrameworks();
var setup = Setup();
int condBefore = lib.CsProj().NumberOfItemGroupsWithConditionContaining(ConditionFrameworkNet451);
@ -160,7 +178,7 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
[Fact]
public void WhenRefWithoutCondIsPresentItAddsDifferentRefWithoutCond()
{
var lib = NewLib();
var lib = NewLibWithFrameworks();
var setup = Setup();
new AddP2PCommand()
@ -184,7 +202,7 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
[Fact]
public void WhenRefWithCondIsPresentItAddsDifferentRefWithCond()
{
var lib = NewLib();
var lib = NewLibWithFrameworks();
var setup = Setup();
new AddP2PCommand()
@ -208,7 +226,7 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
[Fact]
public void WhenRefWithCondIsPresentItAddsRefWithDifferentCond()
{
var lib = NewLib();
var lib = NewLibWithFrameworks();
var setup = Setup();
new AddP2PCommand()
@ -232,7 +250,7 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
[Fact]
public void WhenRefWithConditionIsPresentItAddsDifferentRefWithoutCond()
{
var lib = NewLib();
var lib = NewLibWithFrameworks();
var setup = Setup();
new AddP2PCommand()
@ -256,7 +274,7 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
[Fact]
public void WhenRefWithNoCondAlreadyExistsItDoesntDuplicate()
{
var lib = NewLib();
var lib = NewLibWithFrameworks();
var setup = Setup();
new AddP2PCommand()
@ -297,7 +315,7 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
[Fact]
public void WhenRefWithCondOnItemGroupAlreadyExistsItDoesntDuplicate()
{
var lib = NewLib();
var lib = NewLibWithFrameworks();
var setup = Setup();
new AddP2PCommand()
@ -421,7 +439,7 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
[Fact]
public void ItAddsMultipleRefsNoCondToTheSameItemGroup()
{
var lib = NewLib();
var lib = NewLibWithFrameworks();
var setup = Setup();
int noCondBefore = lib.CsProj().NumberOfItemGroupsWithoutCondition();
@ -440,7 +458,7 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
[Fact]
public void ItAddsMultipleRefsWithCondToTheSameItemGroup()
{
var lib = NewLib();
var lib = NewLibWithFrameworks();
var setup = Setup();
int noCondBefore = lib.CsProj().NumberOfItemGroupsWithConditionContaining(ConditionFrameworkNet451);
@ -459,7 +477,7 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
[Fact]
public void WhenProjectNameIsNotPassedItFindsItAndAddsReference()
{
var lib = NewLib();
var lib = NewLibWithFrameworks();
var setup = Setup();
int noCondBefore = lib.CsProj().NumberOfItemGroupsWithoutCondition();
@ -477,7 +495,7 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
[Fact]
public void ItAddsRefBetweenImports()
{
var lib = NewLib();
var lib = NewLibWithFrameworks();
var setup = Setup();
var cmd = new AddP2PCommand()
@ -522,7 +540,7 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
[Fact]
public void WhenPassedReferenceDoesNotExistItShowsAnError()
{
var lib = NewLib();
var lib = NewLibWithFrameworks();
var contentBefore = lib.CsProjContent();
var cmd = new AddP2PCommand()
@ -537,7 +555,7 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
[Fact]
public void WhenPassedMultipleRefsAndOneOfthemDoesNotExistItCancelsWholeOperation()
{
var lib = NewLib();
var lib = NewLibWithFrameworks();
var setup = Setup();
var contentBefore = lib.CsProjContent();
@ -554,7 +572,7 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
[Fact]
public void WhenPassedReferenceDoesNotExistAndForceSwitchIsPassedItAddsIt()
{
var lib = NewLib();
var lib = NewLibWithFrameworks();
const string nonExisting = "IDoNotExist.csproj";
int noCondBefore = lib.CsProj().NumberOfItemGroupsWithoutCondition();
@ -573,7 +591,7 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
[Fact]
public void WhenPassedReferenceIsUsingSlashesItNormalizesItToBackslashes()
{
var lib = NewLib();
var lib = NewLibWithFrameworks();
var setup = Setup();
int noCondBefore = lib.CsProj().NumberOfItemGroupsWithoutCondition();
@ -626,5 +644,81 @@ namespace Microsoft.DotNet.Cli.Add.P2P.Tests
csproj.NumberOfItemGroupsWithoutCondition().Should().Be(noCondBefore + 1);
csproj.NumberOfProjectReferencesWithIncludeContaining(setup.ValidRefCsprojRelPath.Replace('/', '\\')).Should().Be(1);
}
[Fact]
public void ItCanAddReferenceWithConditionOnCompatibleFramework()
{
var setup = Setup();
var lib = new ProjDir(setup.LibDir);
var net45lib = new ProjDir(Path.Combine(setup.TestRoot, "Net45Lib"));
int condBefore = lib.CsProj().NumberOfItemGroupsWithConditionContaining(ConditionFrameworkNet451);
var cmd = new AddP2PCommand()
.WithProject(lib.CsProjPath)
.Execute($"{FrameworkNet451Arg} \"{net45lib.CsProjPath}\"");
cmd.Should().Pass();
cmd.StdOut.Should().Contain("added to the project");
var csproj = lib.CsProj();
csproj.NumberOfItemGroupsWithConditionContaining(ConditionFrameworkNet451).Should().Be(condBefore + 1);
csproj.NumberOfProjectReferencesWithIncludeAndConditionContaining(net45lib.CsProjName, ConditionFrameworkNet451).Should().Be(1);
}
[Fact]
public void ItCanAddRefWithoutCondAndTargetingSupersetOfFrameworksAndOneOfReferencesCompatible()
{
var setup = Setup();
var lib = new ProjDir(setup.LibDir);
var net452netcoreapp10lib = new ProjDir(Path.Combine(setup.TestRoot, "Net452AndNetCoreApp10Lib"));
int noCondBefore = net452netcoreapp10lib.CsProj().NumberOfItemGroupsWithoutCondition();
var cmd = new AddP2PCommand()
.WithProject(net452netcoreapp10lib.CsProjPath)
.Execute($"\"{lib.CsProjPath}\"");
cmd.Should().Pass();
cmd.StdOut.Should().Contain("added to the project");
var csproj = net452netcoreapp10lib.CsProj();
csproj.NumberOfItemGroupsWithoutCondition().Should().Be(noCondBefore + 1);
csproj.NumberOfProjectReferencesWithIncludeContaining(lib.CsProjName).Should().Be(1);
}
[Theory]
[InlineData("net45")]
[InlineData("net40")]
[InlineData("netcoreapp1.1")]
[InlineData("nonexistingframeworkname")]
public void WhenFrameworkSwitchIsNotMatchingAnyOfTargetedFrameworksItPrintsError(string framework)
{
var setup = Setup();
var lib = new ProjDir(setup.LibDir);
var net45lib = new ProjDir(Path.Combine(setup.TestRoot, "Net45Lib"));
var csProjContent = lib.CsProjContent();
var cmd = new AddP2PCommand()
.WithProject(lib.CsProjPath)
.Execute($"-f {framework} \"{net45lib.CsProjPath}\"");
cmd.Should().Fail();
cmd.StdErr.Should().MatchRegex(ProjectDoesNotTargetFrameworkErrorMessageRegEx);
cmd.StdErr.Should().Contain($"`{framework}`");
lib.CsProjContent().Should().BeEquivalentTo(csProjContent);
}
[Theory]
[InlineData("")]
[InlineData("-f net45")]
public void WhenIncompatibleFrameworkDetectedItPrintsError(string frameworkArg)
{
var setup = Setup();
var lib = new ProjDir(setup.LibDir);
var net45lib = new ProjDir(Path.Combine(setup.TestRoot, "Net45Lib"));
var csProjContent = net45lib.CsProjContent();
var cmd = new AddP2PCommand()
.WithProject(net45lib.CsProjPath)
.Execute($"{frameworkArg} \"{lib.CsProjPath}\"");
cmd.Should().Fail();
cmd.StdErr.Should().MatchRegex(ProjectNotCompatibleErrorMessageRegEx);
cmd.StdErr.Should().MatchRegex(" - net45(\n|\r)");
net45lib.CsProjContent().Should().BeEquivalentTo(csProjContent);
}
}
}

View file

@ -17,6 +17,7 @@ namespace Microsoft.DotNet.Cli.Remove.P2P.Tests
const string ConditionFrameworkNet451 = "== 'net451'";
const string FrameworkNetCoreApp10Arg = "-f netcoreapp1.0";
const string ConditionFrameworkNetCoreApp10 = "== 'netcoreapp1.0'";
static readonly string[] DefaultFrameworks = new string[] { "netcoreapp1.0", "net451" };
private TestSetup Setup([System.Runtime.CompilerServices.CallerMemberName] string callingMethod = nameof(Setup), string identifier = "")
{
@ -52,6 +53,20 @@ namespace Microsoft.DotNet.Cli.Remove.P2P.Tests
return dir;
}
private static void SetTargetFrameworks(ProjDir proj, string[] frameworks)
{
var csproj = proj.CsProj();
csproj.AddProperty("TargetFrameworks", string.Join(";", frameworks));
csproj.Save();
}
private ProjDir NewLibWithFrameworks([System.Runtime.CompilerServices.CallerMemberName] string callingMethod = nameof(NewDir), string identifier = "")
{
var ret = NewLib(callingMethod: callingMethod, identifier: identifier);
SetTargetFrameworks(ret, DefaultFrameworks);
return ret;
}
private ProjDir GetLibRef(TestSetup setup)
{
return new ProjDir(setup.LibDir);
@ -151,7 +166,7 @@ namespace Microsoft.DotNet.Cli.Remove.P2P.Tests
[Fact]
public void ItRemovesRefWithoutCondAndPrintsStatus()
{
var lib = NewLib();
var lib = NewLibWithFrameworks();
var setup = Setup();
var libref = AddLibRef(setup, lib);
@ -170,7 +185,7 @@ namespace Microsoft.DotNet.Cli.Remove.P2P.Tests
[Fact]
public void ItRemovesRefWithCondAndPrintsStatus()
{
var lib = NewLib();
var lib = NewLibWithFrameworks();
var setup = Setup();
var libref = AddLibRef(setup, lib, FrameworkNet451Arg);
@ -189,7 +204,7 @@ namespace Microsoft.DotNet.Cli.Remove.P2P.Tests
[Fact]
public void WhenTwoDifferentRefsArePresentItDoesNotRemoveBoth()
{
var lib = NewLib();
var lib = NewLibWithFrameworks();
var setup = Setup();
var libref = AddLibRef(setup, lib);
var validref = AddValidRef(setup, lib);
@ -210,7 +225,7 @@ namespace Microsoft.DotNet.Cli.Remove.P2P.Tests
[Fact]
public void WhenRefWithoutCondIsNotThereItPrintsMessage()
{
var lib = NewLib();
var lib = NewLibWithFrameworks();
var setup = Setup();
var libref = GetLibRef(setup);
@ -227,7 +242,7 @@ namespace Microsoft.DotNet.Cli.Remove.P2P.Tests
[Fact]
public void WhenRefWithCondIsNotThereItPrintsMessage()
{
var lib = NewLib();
var lib = NewLibWithFrameworks();
var setup = Setup();
var libref = GetLibRef(setup);
@ -244,7 +259,7 @@ namespace Microsoft.DotNet.Cli.Remove.P2P.Tests
[Fact]
public void WhenRefWithAndWithoutCondArePresentAndRemovingNoCondItDoesNotRemoveOther()
{
var lib = NewLib();
var lib = NewLibWithFrameworks();
var setup = Setup();
var librefCond = AddLibRef(setup, lib, FrameworkNet451Arg);
var librefNoCond = AddLibRef(setup, lib);
@ -269,7 +284,7 @@ namespace Microsoft.DotNet.Cli.Remove.P2P.Tests
[Fact]
public void WhenRefWithAndWithoutCondArePresentAndRemovingCondItDoesNotRemoveOther()
{
var lib = NewLib();
var lib = NewLibWithFrameworks();
var setup = Setup();
var librefCond = AddLibRef(setup, lib, FrameworkNet451Arg);
var librefNoCond = AddLibRef(setup, lib);
@ -294,7 +309,7 @@ namespace Microsoft.DotNet.Cli.Remove.P2P.Tests
[Fact]
public void WhenRefWithDifferentCondIsPresentItDoesNotRemoveIt()
{
var lib = NewLib();
var lib = NewLibWithFrameworks();
var setup = Setup();
var librefCondNet451 = AddLibRef(setup, lib, FrameworkNet451Arg);
var librefCondNetCoreApp10 = AddLibRef(setup, lib, FrameworkNetCoreApp10Arg);
@ -396,7 +411,7 @@ namespace Microsoft.DotNet.Cli.Remove.P2P.Tests
[Fact]
public void WhenPassingMultipleReferencesItRemovesThemAll()
{
var lib = NewLib();
var lib = NewLibWithFrameworks();
var setup = Setup();
var libref = AddLibRef(setup, lib);
var validref = AddValidRef(setup, lib);
@ -417,7 +432,7 @@ namespace Microsoft.DotNet.Cli.Remove.P2P.Tests
[Fact]
public void WhenPassingMultipleReferencesAndOneOfThemDoesNotExistItRemovesOne()
{
var lib = NewLib();
var lib = NewLibWithFrameworks();
var setup = Setup();
var libref = GetLibRef(setup);
var validref = AddValidRef(setup, lib);