2016-08-22 12:24:10 -07:00
using Microsoft.Build.Construction ;
using Microsoft.DotNet.ProjectJsonMigration ;
2016-10-27 18:46:43 -07:00
using Microsoft.DotNet.Internal.ProjectModel ;
2016-10-24 16:25:57 -07:00
using Microsoft.DotNet.TestFramework ;
2016-08-22 12:24:10 -07:00
using Microsoft.DotNet.Tools.Test.Utilities ;
using NuGet.Frameworks ;
using System ;
using System.Collections.Generic ;
using System.IO ;
using System.Linq ;
using System.Threading.Tasks ;
using Xunit ;
using FluentAssertions ;
2016-08-23 13:50:05 -07:00
using Microsoft.DotNet.ProjectJsonMigration.Rules ;
2016-08-22 12:24:10 -07:00
2016-09-14 15:30:11 -07:00
namespace Microsoft.DotNet.ProjectJsonMigration.Tests
2016-08-22 12:24:10 -07:00
{
public class GivenThatIWantToMigrateProjectDependencies : TestBase
{
[Fact]
public void Project_dependencies_are_migrated_to_ProjectReference ( )
{
var solutionDirectory =
2016-09-21 21:14:48 -07:00
TestAssetsManager . CreateTestInstance ( "TestAppWithLibrary" , callingMethod : "p" ) . Path ;
2016-08-22 12:24:10 -07:00
var appDirectory = Path . Combine ( solutionDirectory , "TestApp" ) ;
var projectContext = ProjectContext . Create ( appDirectory , FrameworkConstants . CommonFrameworks . NetCoreApp10 ) ;
var mockProj = ProjectRootElement . Create ( ) ;
2016-09-21 17:27:02 -07:00
var testSettings = new MigrationSettings ( appDirectory , appDirectory , "1.0.0" , mockProj , null ) ;
2016-08-22 12:24:10 -07:00
var testInputs = new MigrationRuleInputs ( new [ ] { projectContext } , mockProj , mockProj . AddItemGroup ( ) ,
mockProj . AddPropertyGroup ( ) ) ;
new MigrateProjectDependenciesRule ( ) . Apply ( testSettings , testInputs ) ;
var projectReferences = mockProj . Items . Where ( item = > item . ItemType . Equals ( "ProjectReference" , StringComparison . Ordinal ) ) ;
projectReferences . Count ( ) . Should ( ) . Be ( 1 ) ;
2016-10-21 18:00:17 -07:00
var projectReference = projectReferences . First ( ) ;
projectReference . Include . Should ( ) . Be ( Path . Combine ( ".." , "TestLibrary" , "TestLibrary.csproj" ) ) ;
projectReference . Parent . Condition . Should ( ) . BeEmpty ( ) ;
}
2016-10-24 16:25:57 -07:00
[Fact]
public void It_does_not_migrate_a_dependency_with_target_package_that_has_a_matching_project_as_a_ProjectReference ( )
{
var testAssetsManager = GetTestGroupTestAssetsManager ( "NonRestoredTestProjects" ) ;
var solutionDirectory =
testAssetsManager . CreateTestInstance ( "AppWithProjectDependencyAsTarget" , callingMethod : "p" ) . Path ;
var appDirectory = Path . Combine ( solutionDirectory , "TestApp" ) ;
var projectContext = ProjectContext . Create ( appDirectory , FrameworkConstants . CommonFrameworks . NetCoreApp10 ) ;
var mockProj = ProjectRootElement . Create ( ) ;
var testSettings = new MigrationSettings ( appDirectory , appDirectory , "1.0.0" , mockProj , null ) ;
var testInputs = new MigrationRuleInputs ( new [ ] { projectContext } , mockProj , mockProj . AddItemGroup ( ) ,
mockProj . AddPropertyGroup ( ) ) ;
new MigrateProjectDependenciesRule ( ) . Apply ( testSettings , testInputs ) ;
var projectReferences = mockProj . Items . Where (
item = > item . ItemType . Equals ( "ProjectReference" , StringComparison . Ordinal ) ) ;
projectReferences . Should ( ) . BeEmpty ( ) ;
}
2016-10-21 18:00:17 -07:00
[Fact]
public void TFM_specific_Project_dependencies_are_migrated_to_ProjectReference_under_condition_ItemGroup ( )
{
var solutionDirectory =
TestAssetsManager . CreateTestInstance ( "TestAppWithLibraryUnderTFM" , callingMethod : "p" ) . Path ;
var appDirectory = Path . Combine ( solutionDirectory , "TestApp" ) ;
var projectContext = ProjectContext . Create ( appDirectory , FrameworkConstants . CommonFrameworks . NetCoreApp10 ) ;
var mockProj = ProjectRootElement . Create ( ) ;
var testSettings = new MigrationSettings ( appDirectory , appDirectory , "1.0.0" , mockProj , null ) ;
var testInputs = new MigrationRuleInputs ( new [ ] { projectContext } , mockProj , mockProj . AddItemGroup ( ) ,
mockProj . AddPropertyGroup ( ) ) ;
new MigrateProjectDependenciesRule ( ) . Apply ( testSettings , testInputs ) ;
var projectReferences = mockProj . Items . Where ( item = > item . ItemType . Equals ( "ProjectReference" , StringComparison . Ordinal ) ) ;
projectReferences . Count ( ) . Should ( ) . Be ( 1 ) ;
var projectReference = projectReferences . First ( ) ;
projectReference . Include . Should ( ) . Be ( Path . Combine ( ".." , "TestLibrary" , "TestLibrary.csproj" ) ) ;
projectReference . Parent . Condition . Should ( ) . Be ( " '$(TargetFramework)' == 'netcoreapp1.0' " ) ;
2016-08-22 12:24:10 -07:00
}
[Fact]
public void It_throws_when_project_dependency_is_unresolved ( )
{
// No Lock file => unresolved
var solutionDirectory =
TestAssetsManager . CreateTestInstance ( "TestAppWithLibrary" ) . Path ;
var appDirectory = Path . Combine ( solutionDirectory , "TestApp" ) ;
2016-09-21 21:14:48 -07:00
var libraryDirectory = Path . Combine ( solutionDirectory , "TestLibrary" ) ;
Directory . Delete ( libraryDirectory , true ) ;
2016-08-22 12:24:10 -07:00
var projectContext = ProjectContext . Create ( appDirectory , FrameworkConstants . CommonFrameworks . NetCoreApp10 ) ;
var mockProj = ProjectRootElement . Create ( ) ;
var testSettings = new MigrationSettings ( appDirectory , appDirectory , "1.0.0" , mockProj ) ;
var testInputs = new MigrationRuleInputs ( new [ ] { projectContext } , mockProj , mockProj . AddItemGroup ( ) , mockProj . AddPropertyGroup ( ) ) ;
Action action = ( ) = > new MigrateProjectDependenciesRule ( ) . Apply ( testSettings , testInputs ) ;
action . ShouldThrow < Exception > ( )
2016-08-23 13:50:05 -07:00
. Where ( e = > e . Message . Contains ( "MIGRATE1014::Unresolved Dependency: Unresolved project dependency (TestLibrary)" ) ) ;
2016-08-22 12:24:10 -07:00
}
2016-09-21 17:27:02 -07:00
[Theory]
[InlineData(@"some/path/to.cSproj", new [] { @"some/path/to.cSproj" } ) ]
[InlineData(@"to.CSPROJ",new [] { @"to.CSPROJ" } ) ]
public void It_migrates_csproj_ProjectReference_in_xproj ( string projectReference , string [ ] expectedMigratedReferences )
{
var xproj = ProjectRootElement . Create ( ) ;
xproj . AddItem ( "ProjectReference" , projectReference ) ;
var projectReferenceName = Path . GetFileNameWithoutExtension ( projectReference ) ;
var projectJson = @ "
{
"" dependencies "" : { " +
$"\" { projectReferenceName } \ "" + @ ": {
"" target "" : "" project ""
}
}
}
";
var testDirectory = Temp . CreateDirectory ( ) . Path ;
var migratedProj = TemporaryProjectFileRuleRunner . RunRules ( new IMigrationRule [ ]
{
new MigrateProjectDependenciesRule ( )
} , projectJson , testDirectory , xproj ) ;
var migratedProjectReferenceItems = migratedProj . Items . Where ( i = > i . ItemType = = "ProjectReference" ) ;
migratedProjectReferenceItems . Should ( ) . HaveCount ( expectedMigratedReferences . Length ) ;
migratedProjectReferenceItems . Select ( m = > m . Include ) . Should ( ) . BeEquivalentTo ( expectedMigratedReferences ) ;
}
2016-09-22 12:51:23 -07:00
2016-09-22 14:30:56 -07:00
[Fact]
2016-09-22 12:51:23 -07:00
public void It_migrates_csproj_ProjectReference_in_xproj_including_condition_on_ProjectReference ( )
{
var projectReference = "some/to.csproj" ;
var xproj = ProjectRootElement . Create ( ) ;
var csprojReferenceItem = xproj . AddItem ( "ProjectReference" , projectReference ) ;
csprojReferenceItem . Condition = " '$(Foo)' == 'bar' " ;
var projectReferenceName = Path . GetFileNameWithoutExtension ( projectReference ) ;
var projectJson = @ "
{
"" dependencies "" : { " +
$"\" { projectReferenceName } \ "" + @ ": {
"" target "" : "" project ""
}
}
}
";
var testDirectory = Temp . CreateDirectory ( ) . Path ;
var migratedProj = TemporaryProjectFileRuleRunner . RunRules ( new IMigrationRule [ ]
{
new MigrateProjectDependenciesRule ( )
} , projectJson , testDirectory , xproj ) ;
var migratedProjectReferenceItems = migratedProj . Items . Where ( i = > i . ItemType = = "ProjectReference" ) ;
migratedProjectReferenceItems . Should ( ) . HaveCount ( 1 ) ;
var migratedProjectReferenceItem = migratedProjectReferenceItems . First ( ) ;
migratedProjectReferenceItem . Include . Should ( ) . Be ( projectReference ) ;
migratedProjectReferenceItem . Condition . Should ( ) . Be ( " '$(Foo)' == 'bar' " ) ;
}
2016-09-22 14:30:56 -07:00
[Fact]
2016-09-22 12:51:23 -07:00
public void It_migrates_csproj_ProjectReference_in_xproj_including_condition_on_ProjectReference_parent ( )
{
var projectReference = "some/to.csproj" ;
var xproj = ProjectRootElement . Create ( ) ;
var csprojReferenceItem = xproj . AddItem ( "ProjectReference" , projectReference ) ;
csprojReferenceItem . Parent . Condition = " '$(Foo)' == 'bar' " ;
var projectReferenceName = Path . GetFileNameWithoutExtension ( projectReference ) ;
var projectJson = @ "
{
"" dependencies "" : { " +
$"\" { projectReferenceName } \ "" + @ ": {
"" target "" : "" project ""
}
}
}
";
var testDirectory = Temp . CreateDirectory ( ) . Path ;
var migratedProj = TemporaryProjectFileRuleRunner . RunRules ( new IMigrationRule [ ]
{
new MigrateProjectDependenciesRule ( )
} , projectJson , testDirectory , xproj ) ;
var migratedProjectReferenceItems = migratedProj . Items . Where ( i = > i . ItemType = = "ProjectReference" ) ;
migratedProjectReferenceItems . Should ( ) . HaveCount ( 1 ) ;
var migratedProjectReferenceItem = migratedProjectReferenceItems . First ( ) ;
migratedProjectReferenceItem . Include . Should ( ) . Be ( projectReference ) ;
migratedProjectReferenceItem . Condition . Should ( ) . Be ( " '$(Foo)' == 'bar' " ) ;
}
2016-09-22 14:30:56 -07:00
[Fact]
2016-09-22 12:51:23 -07:00
public void It_migrates_csproj_ProjectReference_in_xproj_including_condition_on_ProjectReference_parent_and_item ( )
{
var projectReference = "some/to.csproj" ;
var xproj = ProjectRootElement . Create ( ) ;
var csprojReferenceItem = xproj . AddItem ( "ProjectReference" , projectReference ) ;
csprojReferenceItem . Parent . Condition = " '$(Foo)' == 'bar' " ;
csprojReferenceItem . Condition = " '$(Bar)' == 'foo' " ;
var projectReferenceName = Path . GetFileNameWithoutExtension ( projectReference ) ;
var projectJson = @ "
{
"" dependencies "" : { " +
$"\" { projectReferenceName } \ "" + @ ": {
"" target "" : "" project ""
}
}
}
";
var testDirectory = Temp . CreateDirectory ( ) . Path ;
var migratedProj = TemporaryProjectFileRuleRunner . RunRules ( new IMigrationRule [ ]
{
new MigrateProjectDependenciesRule ( )
} , projectJson , testDirectory , xproj ) ;
var migratedProjectReferenceItems = migratedProj . Items . Where ( i = > i . ItemType = = "ProjectReference" ) ;
migratedProjectReferenceItems . Should ( ) . HaveCount ( 1 ) ;
var migratedProjectReferenceItem = migratedProjectReferenceItems . First ( ) ;
migratedProjectReferenceItem . Include . Should ( ) . Be ( projectReference ) ;
2016-09-22 17:16:37 -07:00
migratedProjectReferenceItem . Condition . Should ( ) . Be ( " '$(Bar)' == 'foo' and '$(Foo)' == 'bar' " ) ;
2016-09-22 12:51:23 -07:00
}
2016-10-27 16:35:35 -07:00
[Fact]
public void It_promotes_P2P_references_up_in_the_dependency_chain ( )
2016-11-01 14:11:11 -07:00
{
var mockProj = MigrateProject ( "TestAppDependencyGraph" , "ProjectA" ) ;
var projectReferences = mockProj . Items . Where (
item = > item . ItemType . Equals ( "ProjectReference" , StringComparison . Ordinal ) ) ;
projectReferences . Count ( ) . Should ( ) . Be ( 7 ) ;
}
2016-11-03 16:54:15 -07:00
[Fact]
public void It_promotes_FrameworkAssemblies_from_P2P_references_up_in_the_dependency_chain ( )
{
var solutionDirectory = TestAssets . Get ( TestAssetKinds . DesktopTestProjects , "TestAppWithFrameworkAssemblies" )
. CreateInstance ( )
. WithSourceFiles ( ) . Root ;
var appDirectory = Path . Combine ( solutionDirectory . FullName , "ProjectA" ) ;
var projectContext = ProjectContext . Create ( appDirectory , FrameworkConstants . CommonFrameworks . Net451 ) ;
var mockProj = ProjectRootElement . Create ( ) ;
var testSettings = new MigrationSettings ( appDirectory , appDirectory , "1.0.0" , mockProj , null ) ;
var testInputs = new MigrationRuleInputs ( new [ ] { projectContext } , mockProj , mockProj . AddItemGroup ( ) ,
mockProj . AddPropertyGroup ( ) ) ;
new MigrateProjectDependenciesRule ( ) . Apply ( testSettings , testInputs ) ;
var frameworkAssemblyReferences = mockProj . Items . Where (
item = > item . ItemType = = "Reference" & &
item . Include = = "System.ComponentModel.DataAnnotations" & &
item . Parent . Condition = = " '$(TargetFramework)' == 'net451' " ) ;
frameworkAssemblyReferences . Count ( ) . Should ( ) . Be ( 1 ) ;
}
2016-11-03 10:27:51 -07:00
[Fact]
public void All_promoted_P2P_references_are_marked_with_a_FromP2P_attribute ( )
{
var expectedHoistedProjectReferences = new [ ] {
Path . Combine ( ".." , "ProjectD" , "ProjectD.csproj" ) ,
Path . Combine ( ".." , "ProjectE" , "ProjectE.csproj" ) ,
Path . Combine ( ".." , "CsprojLibrary1" , "CsprojLibrary1.csproj" ) ,
Path . Combine ( ".." , "CsprojLibrary2" , "CsprojLibrary2.csproj" ) ,
Path . Combine ( ".." , "CsprojLibrary3" , "CsprojLibrary3.csproj" )
} ;
var mockProj = MigrateProject ( "TestAppDependencyGraph" , "ProjectA" ) ;
var projectReferences = mockProj . Items
. Where ( item = >
item . ItemType = = "ProjectReference" & & item . GetMetadataWithName ( "FromP2P" ) ! = null )
. Select ( i = > i . Include ) ;
projectReferences . Should ( ) . BeEquivalentTo ( expectedHoistedProjectReferences ) ;
}
[Fact]
public void All_non_promoted_P2P_references_are_not_marked_with_a_FromP2P_attribute ( )
{
var expectedNonHoistedProjectReferences = new [ ] {
Path . Combine ( ".." , "ProjectB" , "ProjectB.csproj" ) ,
Path . Combine ( ".." , "ProjectC" , "ProjectC.csproj" )
} ;
var mockProj = MigrateProject ( "TestAppDependencyGraph" , "ProjectA" ) ;
var projectReferences = mockProj . Items
. Where ( item = >
item . ItemType = = "ProjectReference" & & item . GetMetadataWithName ( "FromP2P" ) = = null )
. Select ( i = > i . Include ) ;
projectReferences . Should ( ) . BeEquivalentTo ( expectedNonHoistedProjectReferences ) ;
}
2016-11-01 14:11:11 -07:00
[Fact]
public void It_migrates_unqualified_dependencies_as_ProjectReference_when_a_matching_project_is_found ( )
{
var mockProj = MigrateProject ( "TestAppWithUnqualifiedDependencies" , "ProjectA" ) ;
2016-11-01 14:58:11 -07:00
var projectReferenceInclude = Path . Combine ( ".." , "ProjectB" , "ProjectB.csproj" ) ;
2016-11-01 14:11:11 -07:00
var projectReferences = mockProj . Items . Should ( ) . ContainSingle (
2016-11-01 14:58:11 -07:00
item = > item . ItemType = = "ProjectReference" & & item . Include = = projectReferenceInclude ) ;
2016-11-01 14:11:11 -07:00
}
private ProjectRootElement MigrateProject ( string solution , string project )
2016-11-03 16:54:15 -07:00
{
return MigrateProject ( solution , project , FrameworkConstants . CommonFrameworks . NetCoreApp10 ) ;
}
private ProjectRootElement MigrateProject (
string solution ,
string project ,
NuGetFramework targetFramework )
2016-10-27 16:35:35 -07:00
{
var solutionDirectory =
2016-11-01 14:11:11 -07:00
TestAssetsManager . CreateTestInstance ( solution , callingMethod : "p" ) . Path ;
2016-10-27 16:35:35 -07:00
2016-11-01 14:11:11 -07:00
var appDirectory = Path . Combine ( solutionDirectory , project ) ;
2016-10-27 16:35:35 -07:00
2016-11-03 16:54:15 -07:00
var projectContext = ProjectContext . Create ( appDirectory , targetFramework ) ;
2016-10-27 16:35:35 -07:00
var mockProj = ProjectRootElement . Create ( ) ;
var testSettings = new MigrationSettings ( appDirectory , appDirectory , "1.0.0" , mockProj , null ) ;
var testInputs = new MigrationRuleInputs ( new [ ] { projectContext } , mockProj , mockProj . AddItemGroup ( ) ,
mockProj . AddPropertyGroup ( ) ) ;
new MigrateProjectDependenciesRule ( ) . Apply ( testSettings , testInputs ) ;
2016-11-01 14:11:11 -07:00
var s = mockProj . Items . Select ( p = > $"ItemType = {p.ItemType}, Include = {p.Include}" ) ;
Console . WriteLine ( string . Join ( Environment . NewLine , s ) ) ;
return mockProj ;
2016-10-27 16:35:35 -07:00
}
2016-08-22 12:24:10 -07:00
}
}