2016-12-20 13:04:01 -10: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.
using FluentAssertions ;
using Microsoft.DotNet.Cli.Sln.Internal ;
using Microsoft.DotNet.TestFramework ;
using Microsoft.DotNet.Tools.Test.Utilities ;
using System.IO ;
using System.Linq ;
2017-01-11 17:06:03 -08:00
using System.Runtime.CompilerServices ;
2016-12-20 13:04:01 -10:00
using Xunit ;
namespace Microsoft.DotNet.Migration.Tests
{
public class GivenThatIWantToMigrateSolutions : TestBase
{
2017-01-17 14:48:54 -08:00
[Theory]
[InlineData("PJAppWithSlnVersion14", "Visual Studio 15", "15.0.26114.2", "10.0.40219.1")]
[InlineData("PJAppWithSlnVersion15", "Visual Studio 15 Custom", "15.9.12345.4", "10.9.1234.5")]
[InlineData("PJAppWithSlnVersionUnknown", "Visual Studio 15", "15.0.26114.2", "10.0.40219.1")]
public void ItMigratesSlnAndEnsuresAtLeastVS15 (
string projectName ,
string productDescription ,
string visualStudioVersion ,
string minVisualStudioVersion )
{
var projectDirectory = TestAssets
2017-01-22 14:40:00 -08:00
. GetProjectJson ( TestAssetKinds . NonRestoredTestProjects , projectName )
. CreateInstance ( identifier : projectName )
2017-01-17 14:48:54 -08:00
. WithSourceFiles ( )
2017-01-25 23:48:31 -08:00
. WithEmptyGlobalJson ( )
2017-01-17 14:48:54 -08:00
. Root ;
var solutionRelPath = "TestApp.sln" ;
new DotnetCommand ( )
. WithWorkingDirectory ( projectDirectory )
. Execute ( $"migrate \" { solutionRelPath } \ "" )
. Should ( ) . Pass ( ) ;
SlnFile slnFile = SlnFile . Read ( Path . Combine ( projectDirectory . FullName , solutionRelPath ) ) ;
slnFile . ProductDescription . Should ( ) . Be ( productDescription ) ;
slnFile . VisualStudioVersion . Should ( ) . Be ( visualStudioVersion ) ;
slnFile . MinimumVisualStudioVersion . Should ( ) . Be ( minVisualStudioVersion ) ;
}
2016-12-20 13:04:01 -10:00
[Fact]
public void ItMigratesAndBuildsSln ( )
{
MigrateAndBuild (
"NonRestoredTestProjects" ,
2017-01-05 12:04:57 -10:00
"PJAppWithSlnAndXprojRefs" ) ;
2016-12-20 13:04:01 -10:00
}
2017-01-19 13:59:31 -08:00
[Fact]
public void ItOnlyMigratesProjectsInTheSlnFile ( )
{
var projectDirectory = TestAssets
2017-01-22 14:40:00 -08:00
. GetProjectJson ( TestAssetKinds . NonRestoredTestProjects , "PJAppWithSlnAndXprojRefs" )
2017-01-19 13:59:31 -08:00
. CreateInstance ( )
. WithSourceFiles ( )
2017-01-25 23:48:31 -08:00
. WithEmptyGlobalJson ( )
2017-01-19 13:59:31 -08:00
. Root ;
var solutionRelPath = Path . Combine ( "TestApp" , "TestApp.sln" ) ;
new DotnetCommand ( )
. WithWorkingDirectory ( projectDirectory )
. Execute ( $"migrate \" { solutionRelPath } \ "" )
. Should ( ) . Pass ( ) ;
2017-01-22 14:40:00 -08:00
projectDirectory
2017-01-19 13:59:31 -08:00
. Should ( ) . HaveFiles ( new [ ]
{
Path . Combine ( "TestApp" , "TestApp.csproj" ) ,
Path . Combine ( "TestLibrary" , "TestLibrary.csproj" ) ,
Path . Combine ( "TestApp" , "src" , "subdir" , "subdir.csproj" ) ,
Path . Combine ( "TestApp" , "TestAssets" , "TestAsset" , "project.json" )
} ) ;
2017-01-22 14:40:00 -08:00
projectDirectory
2017-01-19 13:59:31 -08:00
. Should ( ) . NotHaveFile ( Path . Combine ( "TestApp" , "TestAssets" , "TestAsset" , "TestAsset.csproj" ) ) ;
}
2016-12-20 13:04:01 -10:00
[Fact]
public void WhenDirectoryAlreadyContainsCsprojFileItMigratesAndBuildsSln ( )
{
MigrateAndBuild (
"NonRestoredTestProjects" ,
2017-01-05 12:04:57 -10:00
"PJAppWithSlnAndXprojRefsAndUnrelatedCsproj" ) ;
2016-12-20 13:04:01 -10:00
}
[Fact]
public void WhenXprojReferencesCsprojAndSlnDoesNotItMigratesAndBuildsSln ( )
{
MigrateAndBuild (
"NonRestoredTestProjects" ,
2017-02-17 17:02:15 -08:00
"PJAppWithSlnThatDoesNotRefCsproj" ) ;
2016-12-20 13:04:01 -10:00
}
2017-01-20 12:21:04 -08:00
[Fact]
public void WhenSolutionContainsACsprojFileItGetsMovedToBackup ( )
{
var projectDirectory = TestAssets
2017-01-22 14:40:00 -08:00
. GetProjectJson ( "NonRestoredTestProjects" , "PJAppWithSlnAndOneAlreadyMigratedCsproj" )
2017-01-20 12:21:04 -08:00
. CreateInstance ( )
. WithSourceFiles ( )
2017-01-25 23:48:31 -08:00
. WithEmptyGlobalJson ( )
2017-01-22 14:40:00 -08:00
. Root ;
2017-01-20 12:21:04 -08:00
var solutionRelPath = Path . Combine ( "TestApp" , "TestApp.sln" ) ;
2017-01-22 14:40:00 -08:00
2017-01-20 12:21:04 -08:00
var cmd = new DotnetCommand ( )
. WithWorkingDirectory ( projectDirectory )
. ExecuteWithCapturedOutput ( $"migrate \" { solutionRelPath } \ "" ) ;
2017-01-22 14:40:00 -08:00
2017-01-20 12:21:04 -08:00
cmd . Should ( ) . Pass ( ) ;
2017-01-22 14:40:00 -08:00
projectDirectory
. GetDirectory ( "TestLibrary" )
. GetFile ( "TestLibrary.csproj" )
. Should ( ) . Exist ( ) ;
projectDirectory
. GetDirectory ( "TestLibrary" )
. GetFile ( "TestLibrary.csproj.migration_in_place_backup" )
. Should ( ) . NotExist ( ) ;
projectDirectory
. GetDirectory ( "backup" , "TestLibrary" )
. GetFile ( "TestLibrary.csproj" )
. Should ( ) . Exist ( ) ;
2017-01-20 12:21:04 -08:00
}
2017-01-19 11:23:01 -08:00
[Fact]
public void WhenSolutionContainsACsprojFileItDoesNotTryToAddItAgain ( )
{
var projectDirectory = TestAssets
2017-01-22 14:40:00 -08:00
. GetProjectJson ( TestAssetKinds . NonRestoredTestProjects , "PJAppWithSlnAndOneAlreadyMigratedCsproj" )
2017-01-19 11:23:01 -08:00
. CreateInstance ( )
. WithSourceFiles ( )
2017-01-25 23:48:31 -08:00
. WithEmptyGlobalJson ( )
2017-01-19 11:23:01 -08:00
. Root ;
var solutionRelPath = Path . Combine ( "TestApp" , "TestApp.sln" ) ;
2017-01-22 14:40:00 -08:00
2017-01-19 11:23:01 -08:00
var cmd = new DotnetCommand ( )
. WithWorkingDirectory ( projectDirectory )
. ExecuteWithCapturedOutput ( $"migrate \" { solutionRelPath } \ "" ) ;
2017-01-22 14:40:00 -08:00
2017-01-19 11:23:01 -08:00
cmd . Should ( ) . Pass ( ) ;
cmd . StdOut . Should ( ) . NotContain ( "already contains project" ) ;
cmd . StdErr . Should ( ) . BeEmpty ( ) ;
}
2017-01-20 17:37:11 -08:00
[Theory]
2017-01-24 10:57:07 -08:00
[InlineData("NoSolutionItemsAfterMigration.sln", false)]
[InlineData("ReadmeSolutionItemAfterMigration.sln", true)]
2017-01-20 17:37:11 -08:00
public void WhenMigratingAnSlnLinksReferencingItemsMovedToBackupAreRemoved (
string slnFileName ,
2017-01-24 10:57:07 -08:00
bool solutionItemsContainsReadme )
2017-01-20 17:37:11 -08:00
{
var projectDirectory = TestAssets
2017-01-23 13:01:58 -08:00
. GetProjectJson ( TestAssetKinds . NonRestoredTestProjects , "PJAppWithSlnAndSolutionItemsToMoveToBackup" )
2017-01-20 17:37:11 -08:00
. CreateInstance ( Path . GetFileNameWithoutExtension ( slnFileName ) )
. WithSourceFiles ( )
. Root
. FullName ;
new DotnetCommand ( )
. WithWorkingDirectory ( projectDirectory )
. Execute ( $"migrate \" { slnFileName } \ "" )
. Should ( ) . Pass ( ) ;
2017-01-24 10:57:07 -08:00
var slnFile = SlnFile . Read ( Path . Combine ( projectDirectory , slnFileName ) ) ;
var solutionFolders = slnFile . Projects . Where ( p = > p . TypeGuid = = ProjectTypeGuids . SolutionFolderGuid ) ;
if ( solutionItemsContainsReadme )
{
solutionFolders . Count ( ) . Should ( ) . Be ( 1 ) ;
var solutionItems = solutionFolders . Single ( ) . Sections . GetSection ( "SolutionItems" ) ;
solutionItems . Should ( ) . NotBeNull ( ) ;
solutionItems . Properties . Count ( ) . Should ( ) . Be ( 1 ) ;
solutionItems . Properties [ "readme.txt" ] . Should ( ) . Be ( "readme.txt" ) ;
}
else
{
solutionFolders . Count ( ) . Should ( ) . Be ( 0 ) ;
}
2017-01-20 17:37:11 -08:00
}
2017-01-25 23:48:31 -08:00
[Fact]
public void ItMigratesSolutionInTheFolderWhenWeRunMigrationInThatFolder ( )
{
var projectDirectory = TestAssets
. Get ( "NonRestoredTestProjects" , "PJAppWithSlnAndXprojRefs" )
. CreateInstance ( )
. WithSourceFiles ( )
. WithEmptyGlobalJson ( )
. Root ;
var workingDirectory = new DirectoryInfo ( Path . Combine ( projectDirectory . FullName , "TestApp" ) ) ;
var solutionRelPath = Path . Combine ( "TestApp" , "TestApp.sln" ) ;
new DotnetCommand ( )
. WithWorkingDirectory ( workingDirectory )
. Execute ( $"migrate" )
. Should ( ) . Pass ( ) ;
SlnFile slnFile = SlnFile . Read ( Path . Combine ( projectDirectory . FullName , solutionRelPath ) ) ;
var nonSolutionFolderProjects = slnFile . Projects
. Where ( p = > p . TypeGuid ! = ProjectTypeGuids . SolutionFolderGuid ) ;
nonSolutionFolderProjects . Count ( ) . Should ( ) . Be ( 4 ) ;
var slnProject = nonSolutionFolderProjects . Where ( ( p ) = > p . Name = = "TestApp" ) . Single ( ) ;
slnProject . TypeGuid . Should ( ) . Be ( ProjectTypeGuids . CSharpProjectTypeGuid ) ;
slnProject . FilePath . Should ( ) . Be ( "TestApp.csproj" ) ;
slnProject = nonSolutionFolderProjects . Where ( ( p ) = > p . Name = = "TestLibrary" ) . Single ( ) ;
slnProject . TypeGuid . Should ( ) . Be ( ProjectTypeGuids . CSharpProjectTypeGuid ) ;
slnProject . FilePath . Should ( ) . Be ( Path . Combine ( ".." , "TestLibrary" , "TestLibrary.csproj" ) ) ;
slnProject = nonSolutionFolderProjects . Where ( ( p ) = > p . Name = = "subdir" ) . Single ( ) ;
slnProject . FilePath . Should ( ) . Be ( Path . Combine ( "src" , "subdir" , "subdir.csproj" ) ) ;
new DotnetCommand ( )
. WithWorkingDirectory ( projectDirectory )
. Execute ( $"restore \" { solutionRelPath } \ "" )
. Should ( ) . Pass ( ) ;
2017-02-17 11:13:33 -08:00
new DotnetCommand ( )
. WithWorkingDirectory ( projectDirectory )
. Execute ( $"build \" { solutionRelPath } \ "" )
. Should ( ) . Pass ( ) ;
2017-01-25 23:48:31 -08:00
}
2017-01-11 17:06:03 -08:00
private void MigrateAndBuild ( string groupName , string projectName , [ CallerMemberName ] string callingMethod = "" , string identifier = "" )
2016-12-20 13:04:01 -10:00
{
var projectDirectory = TestAssets
. Get ( groupName , projectName )
2017-01-11 17:06:03 -08:00
. CreateInstance ( callingMethod : callingMethod , identifier : identifier )
2016-12-20 13:04:01 -10:00
. WithSourceFiles ( )
2017-01-25 23:48:31 -08:00
. WithEmptyGlobalJson ( )
2016-12-20 13:04:01 -10:00
. Root ;
var solutionRelPath = Path . Combine ( "TestApp" , "TestApp.sln" ) ;
new DotnetCommand ( )
. WithWorkingDirectory ( projectDirectory )
. Execute ( $"migrate \" { solutionRelPath } \ "" )
. Should ( ) . Pass ( ) ;
new DotnetCommand ( )
. WithWorkingDirectory ( projectDirectory )
2017-01-03 11:06:51 -10:00
. Execute ( $"restore \" { solutionRelPath } \ "" )
2016-12-20 13:04:01 -10:00
. Should ( ) . Pass ( ) ;
2017-02-17 11:13:33 -08:00
new DotnetCommand ( )
. WithWorkingDirectory ( projectDirectory )
. Execute ( $"build \" { solutionRelPath } \ "" )
. Should ( ) . Pass ( ) ;
2016-12-20 13:04:01 -10:00
SlnFile slnFile = SlnFile . Read ( Path . Combine ( projectDirectory . FullName , solutionRelPath ) ) ;
2017-01-22 14:40:00 -08:00
2017-01-04 18:32:09 -10:00
var nonSolutionFolderProjects = slnFile . Projects
. Where ( p = > p . TypeGuid ! = ProjectTypeGuids . SolutionFolderGuid ) ;
2016-12-20 13:04:01 -10:00
2017-01-04 18:32:09 -10:00
nonSolutionFolderProjects . Count ( ) . Should ( ) . Be ( 3 ) ;
var slnProject = nonSolutionFolderProjects . Where ( ( p ) = > p . Name = = "TestApp" ) . Single ( ) ;
2016-12-20 13:04:01 -10:00
slnProject . TypeGuid . Should ( ) . Be ( ProjectTypeGuids . CSharpProjectTypeGuid ) ;
slnProject . FilePath . Should ( ) . Be ( "TestApp.csproj" ) ;
2017-01-04 18:32:09 -10:00
slnProject = nonSolutionFolderProjects . Where ( ( p ) = > p . Name = = "TestLibrary" ) . Single ( ) ;
2016-12-20 13:04:01 -10:00
slnProject . TypeGuid . Should ( ) . Be ( ProjectTypeGuids . CSharpProjectTypeGuid ) ;
slnProject . FilePath . Should ( ) . Be ( Path . Combine ( ".." , "TestLibrary" , "TestLibrary.csproj" ) ) ;
2017-01-04 18:32:09 -10:00
slnProject = nonSolutionFolderProjects . Where ( ( p ) = > p . Name = = "subdir" ) . Single ( ) ;
2017-01-05 12:04:57 -10:00
//ISSUE: https://github.com/dotnet/sdk/issues/522
//Once we have that change migrate will always burn in the C# guid
//slnProject.TypeGuid.Should().Be(ProjectTypeGuids.CSharpProjectTypeGuid);
2016-12-20 13:04:01 -10:00
slnProject . FilePath . Should ( ) . Be ( Path . Combine ( "src" , "subdir" , "subdir.csproj" ) ) ;
}
}
}