2016-12-14 23:53:11 +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.
using FluentAssertions ;
using Microsoft.Build.Construction ;
using Microsoft.DotNet.Cli.Sln.Internal ;
using Microsoft.DotNet.Tools.Test.Utilities ;
using System ;
using System.IO ;
using System.Linq ;
using Xunit ;
2017-01-30 15:39:28 +00:00
using Xunit.Abstractions ;
2016-12-14 23:53:11 +00:00
2017-01-06 20:58:23 +00:00
namespace Microsoft.DotNet.Cli.Sln.Add.Tests
2016-12-14 23:53:11 +00:00
{
2017-01-06 20:58:23 +00:00
public class GivenDotnetSlnAdd : TestBase
2016-12-14 23:53:11 +00:00
{
2017-01-06 20:58:23 +00:00
private string HelpText = @ ".NET Add project(s) to a solution file Command
2016-12-16 09:04:09 +00:00
2017-03-14 17:33:58 +00:00
Usage : dotnet sln < SLN_FILE > add [ options ] < args >
2016-12-16 09:04:09 +00:00
Arguments :
2017-03-22 22:26:58 +00:00
< SLN_FILE > Solution file to operate on . If not specified , the command will search the current directory for one .
< args > Add one or more specified projects to the solution .
2016-12-16 09:04:09 +00:00
Options :
2017-05-10 04:05:09 +00:00
- h , - - help Show help information .
2016-12-16 09:04:09 +00:00
";
2017-05-03 23:01:35 +00:00
private const string SlnCommandHelpText = @ ".NET modify solution file command
Usage : dotnet sln [ options ] < SLN_FILE > [ command ]
Arguments :
< SLN_FILE > Solution file to operate on . If not specified , the command will search the current directory for one .
Options :
2017-05-10 04:05:09 +00:00
- h , - - help Show help information .
2017-05-03 23:01:35 +00:00
Commands :
add < args > . NET Add project ( s ) to a solution file Command
list . NET List project ( s ) in a solution file Command
remove < args > . NET Remove project ( s ) from a solution file Command
";
2017-01-30 15:39:28 +00:00
private ITestOutputHelper _output ;
public GivenDotnetSlnAdd ( ITestOutputHelper output )
{
_output = output ;
}
2016-12-16 09:04:09 +00:00
2017-01-03 17:18:45 +00:00
private const string ExpectedSlnFileAfterAddingLibProj = @ "
Microsoft Visual Studio Solution File , Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0 . 26006.2
MinimumVisualStudioVersion = 10.0 . 40219.1
Project ( "" { 9 A19103F - 16F 7 - 4668 - BE54 - 9 A1E7A4F7556 } "" ) = "" App "" , "" App \ App . csproj "" , "" { 7072 A694 - 548F - 4 CAE - A58F - 12D 257D 5F 486 } ""
EndProject
2017-02-14 22:57:04 +00:00
Project ( "" { FAE04EC0 - 301F - 11D 3 - BF4B - 00 C04F79EFBC } "" ) = "" Lib "" , "" Lib \ Lib . csproj "" , "" __LIB_PROJECT_GUID__ ""
2017-01-03 17:18:45 +00:00
EndProject
Global
GlobalSection ( SolutionConfigurationPlatforms ) = preSolution
Debug | Any CPU = Debug | Any CPU
Debug | x64 = Debug | x64
Debug | x86 = Debug | x86
Release | Any CPU = Release | Any CPU
Release | x64 = Release | x64
Release | x86 = Release | x86
EndGlobalSection
GlobalSection ( ProjectConfigurationPlatforms ) = postSolution
{ 7072 A694 - 548F - 4 CAE - A58F - 12D 257D 5F 486 } . Debug | Any CPU . ActiveCfg = Debug | Any CPU
{ 7072 A694 - 548F - 4 CAE - A58F - 12D 257D 5F 486 } . Debug | Any CPU . Build . 0 = Debug | Any CPU
{ 7072 A694 - 548F - 4 CAE - A58F - 12D 257D 5F 486 } . Debug | x64 . ActiveCfg = Debug | x64
{ 7072 A694 - 548F - 4 CAE - A58F - 12D 257D 5F 486 } . Debug | x64 . Build . 0 = Debug | x64
{ 7072 A694 - 548F - 4 CAE - A58F - 12D 257D 5F 486 } . Debug | x86 . ActiveCfg = Debug | x86
{ 7072 A694 - 548F - 4 CAE - A58F - 12D 257D 5F 486 } . Debug | x86 . Build . 0 = Debug | x86
{ 7072 A694 - 548F - 4 CAE - A58F - 12D 257D 5F 486 } . Release | Any CPU . ActiveCfg = Release | Any CPU
{ 7072 A694 - 548F - 4 CAE - A58F - 12D 257D 5F 486 } . Release | Any CPU . Build . 0 = Release | Any CPU
{ 7072 A694 - 548F - 4 CAE - A58F - 12D 257D 5F 486 } . Release | x64 . ActiveCfg = Release | x64
{ 7072 A694 - 548F - 4 CAE - A58F - 12D 257D 5F 486 } . Release | x64 . Build . 0 = Release | x64
{ 7072 A694 - 548F - 4 CAE - A58F - 12D 257D 5F 486 } . Release | x86 . ActiveCfg = Release | x86
{ 7072 A694 - 548F - 4 CAE - A58F - 12D 257D 5F 486 } . Release | x86 . Build . 0 = Release | x86
2017-01-05 04:32:09 +00:00
__LIB_PROJECT_GUID__ . Debug | Any CPU . ActiveCfg = Debug | Any CPU
__LIB_PROJECT_GUID__ . Debug | Any CPU . Build . 0 = Debug | Any CPU
__LIB_PROJECT_GUID__ . Debug | x64 . ActiveCfg = Debug | x64
__LIB_PROJECT_GUID__ . Debug | x64 . Build . 0 = Debug | x64
__LIB_PROJECT_GUID__ . Debug | x86 . ActiveCfg = Debug | x86
__LIB_PROJECT_GUID__ . Debug | x86 . Build . 0 = Debug | x86
__LIB_PROJECT_GUID__ . Release | Any CPU . ActiveCfg = Release | Any CPU
__LIB_PROJECT_GUID__ . Release | Any CPU . Build . 0 = Release | Any CPU
__LIB_PROJECT_GUID__ . Release | x64 . ActiveCfg = Release | x64
__LIB_PROJECT_GUID__ . Release | x64 . Build . 0 = Release | x64
__LIB_PROJECT_GUID__ . Release | x86 . ActiveCfg = Release | x86
__LIB_PROJECT_GUID__ . Release | x86 . Build . 0 = Release | x86
2017-01-03 17:18:45 +00:00
EndGlobalSection
GlobalSection ( SolutionProperties ) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
";
private const string ExpectedSlnFileAfterAddingLibProjToEmptySln = @ "
Microsoft Visual Studio Solution File , Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0 . 26006.2
MinimumVisualStudioVersion = 10.0 . 40219.1
2017-02-14 22:57:04 +00:00
Project ( "" { FAE04EC0 - 301F - 11D 3 - BF4B - 00 C04F79EFBC } "" ) = "" Lib "" , "" Lib \ Lib . csproj "" , "" __LIB_PROJECT_GUID__ ""
2017-01-03 17:18:45 +00:00
EndProject
Global
GlobalSection ( SolutionConfigurationPlatforms ) = preSolution
Debug | Any CPU = Debug | Any CPU
Debug | x64 = Debug | x64
Debug | x86 = Debug | x86
Release | Any CPU = Release | Any CPU
Release | x64 = Release | x64
Release | x86 = Release | x86
EndGlobalSection
GlobalSection ( ProjectConfigurationPlatforms ) = postSolution
2017-01-05 04:32:09 +00:00
__LIB_PROJECT_GUID__ . Debug | Any CPU . ActiveCfg = Debug | Any CPU
__LIB_PROJECT_GUID__ . Debug | Any CPU . Build . 0 = Debug | Any CPU
__LIB_PROJECT_GUID__ . Debug | x64 . ActiveCfg = Debug | x64
__LIB_PROJECT_GUID__ . Debug | x64 . Build . 0 = Debug | x64
__LIB_PROJECT_GUID__ . Debug | x86 . ActiveCfg = Debug | x86
__LIB_PROJECT_GUID__ . Debug | x86 . Build . 0 = Debug | x86
__LIB_PROJECT_GUID__ . Release | Any CPU . ActiveCfg = Release | Any CPU
__LIB_PROJECT_GUID__ . Release | Any CPU . Build . 0 = Release | Any CPU
__LIB_PROJECT_GUID__ . Release | x64 . ActiveCfg = Release | x64
__LIB_PROJECT_GUID__ . Release | x64 . Build . 0 = Release | x64
__LIB_PROJECT_GUID__ . Release | x86 . ActiveCfg = Release | x86
__LIB_PROJECT_GUID__ . Release | x86 . Build . 0 = Release | x86
EndGlobalSection
EndGlobal
";
private const string ExpectedSlnFileAfterAddingNestedProj = @ "
Microsoft Visual Studio Solution File , Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0 . 26006.2
MinimumVisualStudioVersion = 10.0 . 40219.1
Project ( "" { 9 A19103F - 16F 7 - 4668 - BE54 - 9 A1E7A4F7556 } "" ) = "" App "" , "" App . csproj "" , "" { 7072 A694 - 548F - 4 CAE - A58F - 12D 257D 5F 486 } ""
EndProject
Project ( "" { 2150E333 - 8F DC - 42 A3 - 9474 - 1 A3956D46DE8 } "" ) = "" src "" , "" src "" , "" __SRC_FOLDER_GUID__ ""
EndProject
2017-02-14 22:57:04 +00:00
Project ( "" { FAE04EC0 - 301F - 11D 3 - BF4B - 00 C04F79EFBC } "" ) = "" Lib "" , "" src \ Lib \ Lib . csproj "" , "" __LIB_PROJECT_GUID__ ""
2017-01-05 04:32:09 +00:00
EndProject
Global
GlobalSection ( SolutionConfigurationPlatforms ) = preSolution
Debug | Any CPU = Debug | Any CPU
Debug | x64 = Debug | x64
Debug | x86 = Debug | x86
Release | Any CPU = Release | Any CPU
Release | x64 = Release | x64
Release | x86 = Release | x86
EndGlobalSection
GlobalSection ( ProjectConfigurationPlatforms ) = postSolution
{ 7072 A694 - 548F - 4 CAE - A58F - 12D 257D 5F 486 } . Debug | Any CPU . ActiveCfg = Debug | Any CPU
{ 7072 A694 - 548F - 4 CAE - A58F - 12D 257D 5F 486 } . Debug | Any CPU . Build . 0 = Debug | Any CPU
{ 7072 A694 - 548F - 4 CAE - A58F - 12D 257D 5F 486 } . Debug | x64 . ActiveCfg = Debug | x64
{ 7072 A694 - 548F - 4 CAE - A58F - 12D 257D 5F 486 } . Debug | x64 . Build . 0 = Debug | x64
{ 7072 A694 - 548F - 4 CAE - A58F - 12D 257D 5F 486 } . Debug | x86 . ActiveCfg = Debug | x86
{ 7072 A694 - 548F - 4 CAE - A58F - 12D 257D 5F 486 } . Debug | x86 . Build . 0 = Debug | x86
{ 7072 A694 - 548F - 4 CAE - A58F - 12D 257D 5F 486 } . Release | Any CPU . ActiveCfg = Release | Any CPU
{ 7072 A694 - 548F - 4 CAE - A58F - 12D 257D 5F 486 } . Release | Any CPU . Build . 0 = Release | Any CPU
{ 7072 A694 - 548F - 4 CAE - A58F - 12D 257D 5F 486 } . Release | x64 . ActiveCfg = Release | x64
{ 7072 A694 - 548F - 4 CAE - A58F - 12D 257D 5F 486 } . Release | x64 . Build . 0 = Release | x64
{ 7072 A694 - 548F - 4 CAE - A58F - 12D 257D 5F 486 } . Release | x86 . ActiveCfg = Release | x86
{ 7072 A694 - 548F - 4 CAE - A58F - 12D 257D 5F 486 } . Release | x86 . Build . 0 = Release | x86
__LIB_PROJECT_GUID__ . Debug | Any CPU . ActiveCfg = Debug | Any CPU
__LIB_PROJECT_GUID__ . Debug | Any CPU . Build . 0 = Debug | Any CPU
__LIB_PROJECT_GUID__ . Debug | x64 . ActiveCfg = Debug | x64
__LIB_PROJECT_GUID__ . Debug | x64 . Build . 0 = Debug | x64
__LIB_PROJECT_GUID__ . Debug | x86 . ActiveCfg = Debug | x86
__LIB_PROJECT_GUID__ . Debug | x86 . Build . 0 = Debug | x86
__LIB_PROJECT_GUID__ . Release | Any CPU . ActiveCfg = Release | Any CPU
__LIB_PROJECT_GUID__ . Release | Any CPU . Build . 0 = Release | Any CPU
__LIB_PROJECT_GUID__ . Release | x64 . ActiveCfg = Release | x64
__LIB_PROJECT_GUID__ . Release | x64 . Build . 0 = Release | x64
__LIB_PROJECT_GUID__ . Release | x86 . ActiveCfg = Release | x86
__LIB_PROJECT_GUID__ . Release | x86 . Build . 0 = Release | x86
EndGlobalSection
GlobalSection ( SolutionProperties ) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection ( NestedProjects ) = preSolution
2017-01-21 02:34:37 +00:00
__LIB_PROJECT_GUID__ = __SRC_FOLDER_GUID__
2017-01-03 17:18:45 +00:00
EndGlobalSection
EndGlobal
";
2016-12-14 23:53:11 +00:00
[Theory]
[InlineData("--help")]
[InlineData("-h")]
2017-01-13 09:24:12 +00:00
[InlineData("-?")]
[InlineData("/?")]
2016-12-14 23:53:11 +00:00
public void WhenHelpOptionIsPassedItPrintsUsage ( string helpArg )
{
var cmd = new DotnetCommand ( )
2017-01-06 20:58:23 +00:00
. ExecuteWithCapturedOutput ( $"sln add {helpArg}" ) ;
2016-12-14 23:53:11 +00:00
cmd . Should ( ) . Pass ( ) ;
2016-12-28 22:50:34 +00:00
cmd . StdOut . Should ( ) . BeVisuallyEquivalentTo ( HelpText ) ;
2016-12-16 09:04:09 +00:00
}
2016-12-16 18:23:26 +00:00
[Theory]
[InlineData("")]
[InlineData("unknownCommandName")]
public void WhenNoCommandIsPassedItPrintsError ( string commandName )
2016-12-16 09:04:09 +00:00
{
var cmd = new DotnetCommand ( )
2017-01-06 20:58:23 +00:00
. ExecuteWithCapturedOutput ( $"sln {commandName}" ) ;
2016-12-16 09:04:09 +00:00
cmd . Should ( ) . Fail ( ) ;
2016-12-16 18:23:26 +00:00
cmd . StdErr . Should ( ) . Be ( "Required command was not provided." ) ;
2017-05-03 23:01:35 +00:00
cmd . StdOut . Should ( ) . BeVisuallyEquivalentTo ( SlnCommandHelpText ) ;
2016-12-14 23:53:11 +00:00
}
2016-12-16 16:41:47 +00:00
[Fact]
public void WhenTooManyArgumentsArePassedItPrintsError ( )
{
var cmd = new DotnetCommand ( )
2017-01-06 20:58:23 +00:00
. ExecuteWithCapturedOutput ( "sln one.sln two.sln three.sln add" ) ;
2016-12-16 16:41:47 +00:00
cmd . Should ( ) . Fail ( ) ;
2017-03-16 20:34:12 +00:00
cmd . StdErr . Should ( ) . BeVisuallyEquivalentTo ( "Unrecognized command or argument 'two.sln'\r\nUnrecognized command or argument 'three.sln'\r\nYou must specify at least one project to add." ) ;
2016-12-16 16:41:47 +00:00
}
2016-12-14 23:53:11 +00:00
[Theory]
[InlineData("idontexist.sln")]
[InlineData("ihave?invalidcharacters")]
[InlineData("ihaveinv@lidcharacters")]
[InlineData("ihaveinvalid/characters")]
[InlineData("ihaveinvalidchar\\acters")]
public void WhenNonExistingSolutionIsPassedItPrintsErrorAndUsage ( string solutionName )
{
var cmd = new DotnetCommand ( )
2017-01-06 20:58:23 +00:00
. ExecuteWithCapturedOutput ( $"sln {solutionName} add p.csproj" ) ;
2016-12-14 23:53:11 +00:00
cmd . Should ( ) . Fail ( ) ;
2016-12-16 09:04:09 +00:00
cmd . StdErr . Should ( ) . Be ( $"Could not find solution or directory `{solutionName}`." ) ;
2016-12-28 22:50:34 +00:00
cmd . StdOut . Should ( ) . BeVisuallyEquivalentTo ( HelpText ) ;
2016-12-14 23:53:11 +00:00
}
[Fact]
public void WhenInvalidSolutionIsPassedItPrintsErrorAndUsage ( )
{
2016-12-16 09:04:09 +00:00
var projectDirectory = TestAssets
. Get ( "InvalidSolution" )
. CreateInstance ( )
. WithSourceFiles ( )
. Root
. FullName ;
2016-12-14 23:53:11 +00:00
var projectToAdd = Path . Combine ( "Lib" , "Lib.csproj" ) ;
var cmd = new DotnetCommand ( )
. WithWorkingDirectory ( projectDirectory )
2017-01-06 20:58:23 +00:00
. ExecuteWithCapturedOutput ( $"sln InvalidSolution.sln add {projectToAdd}" ) ;
2016-12-14 23:53:11 +00:00
cmd . Should ( ) . Fail ( ) ;
2017-05-14 21:29:28 +00:00
cmd . StdErr . Should ( ) . Be ( "Invalid solution `InvalidSolution.sln`. Expected file header not found." ) ;
2016-12-28 22:50:34 +00:00
cmd . StdOut . Should ( ) . BeVisuallyEquivalentTo ( HelpText ) ;
2016-12-14 23:53:11 +00:00
}
[Fact]
public void WhenInvalidSolutionIsFoundItPrintsErrorAndUsage ( )
{
2016-12-16 09:04:09 +00:00
var projectDirectory = TestAssets
. Get ( "InvalidSolution" )
. CreateInstance ( )
. WithSourceFiles ( )
. Root
. FullName ;
var solutionPath = Path . Combine ( projectDirectory , "InvalidSolution.sln" ) ;
2016-12-14 23:53:11 +00:00
var projectToAdd = Path . Combine ( "Lib" , "Lib.csproj" ) ;
var cmd = new DotnetCommand ( )
. WithWorkingDirectory ( projectDirectory )
2017-01-06 20:58:23 +00:00
. ExecuteWithCapturedOutput ( $"sln add {projectToAdd}" ) ;
2016-12-14 23:53:11 +00:00
cmd . Should ( ) . Fail ( ) ;
2017-05-14 21:29:28 +00:00
cmd . StdErr . Should ( ) . Be ( $"Invalid solution `{solutionPath}`. Expected file header not found." ) ;
2016-12-28 22:50:34 +00:00
cmd . StdOut . Should ( ) . BeVisuallyEquivalentTo ( HelpText ) ;
2016-12-14 23:53:11 +00:00
}
[Fact]
public void WhenNoProjectIsPassedItPrintsErrorAndUsage ( )
{
2016-12-16 09:04:09 +00:00
var projectDirectory = TestAssets
. Get ( "TestAppWithSlnAndCsprojFiles" )
. CreateInstance ( )
. WithSourceFiles ( )
. Root
. FullName ;
2016-12-14 23:53:11 +00:00
var cmd = new DotnetCommand ( )
. WithWorkingDirectory ( projectDirectory )
2017-01-06 20:58:23 +00:00
. ExecuteWithCapturedOutput ( @"sln App.sln add" ) ;
2016-12-14 23:53:11 +00:00
cmd . Should ( ) . Fail ( ) ;
2016-12-16 09:04:09 +00:00
cmd . StdErr . Should ( ) . Be ( "You must specify at least one project to add." ) ;
2017-01-30 15:39:28 +00:00
_output . WriteLine ( "[STD OUT]" ) ;
_output . WriteLine ( cmd . StdOut ) ;
_output . WriteLine ( "[HelpText]" ) ;
_output . WriteLine ( HelpText ) ;
2016-12-28 22:50:34 +00:00
cmd . StdOut . Should ( ) . BeVisuallyEquivalentTo ( HelpText ) ;
2016-12-14 23:53:11 +00:00
}
[Fact]
public void WhenNoSolutionExistsInTheDirectoryItPrintsErrorAndUsage ( )
{
2016-12-16 09:04:09 +00:00
var projectDirectory = TestAssets
. Get ( "TestAppWithSlnAndCsprojFiles" )
. CreateInstance ( )
. WithSourceFiles ( )
. Root
. FullName ;
var solutionPath = Path . Combine ( projectDirectory , "App" ) ;
2016-12-14 23:53:11 +00:00
var cmd = new DotnetCommand ( )
2016-12-16 09:04:09 +00:00
. WithWorkingDirectory ( solutionPath )
2017-01-06 20:58:23 +00:00
. ExecuteWithCapturedOutput ( @"sln add App.csproj" ) ;
2016-12-14 23:53:11 +00:00
cmd . Should ( ) . Fail ( ) ;
2016-12-16 09:04:09 +00:00
cmd . StdErr . Should ( ) . Be ( $"Specified solution file {solutionPath + Path.DirectorySeparatorChar} does not exist, or there is no solution file in the directory." ) ;
2016-12-28 22:50:34 +00:00
cmd . StdOut . Should ( ) . BeVisuallyEquivalentTo ( HelpText ) ;
2016-12-14 23:53:11 +00:00
}
[Fact]
public void WhenMoreThanOneSolutionExistsInTheDirectoryItPrintsErrorAndUsage ( )
{
2016-12-16 09:04:09 +00:00
var projectDirectory = TestAssets
. Get ( "TestAppWithMultipleSlnFiles" )
. CreateInstance ( )
. WithSourceFiles ( )
. Root
. FullName ;
2016-12-14 23:53:11 +00:00
var projectToAdd = Path . Combine ( "Lib" , "Lib.csproj" ) ;
var cmd = new DotnetCommand ( )
. WithWorkingDirectory ( projectDirectory )
2017-01-06 20:58:23 +00:00
. ExecuteWithCapturedOutput ( $"sln add {projectToAdd}" ) ;
2016-12-14 23:53:11 +00:00
cmd . Should ( ) . Fail ( ) ;
2016-12-16 09:04:09 +00:00
cmd . StdErr . Should ( ) . Be ( $"Found more than one solution file in {projectDirectory + Path.DirectorySeparatorChar}. Please specify which one to use." ) ;
2016-12-28 22:50:34 +00:00
cmd . StdOut . Should ( ) . BeVisuallyEquivalentTo ( HelpText ) ;
2016-12-14 23:53:11 +00:00
}
2017-01-05 04:32:09 +00:00
[Fact]
public void WhenNestedProjectIsAddedSolutionFoldersAreCreated ( )
{
var projectDirectory = TestAssets
. Get ( "TestAppWithSlnAndCsprojInSubDir" )
. CreateInstance ( )
. WithSourceFiles ( )
. Root
. FullName ;
var projectToAdd = Path . Combine ( "src" , "Lib" , "Lib.csproj" ) ;
var cmd = new DotnetCommand ( )
. WithWorkingDirectory ( projectDirectory )
2017-01-06 20:58:23 +00:00
. ExecuteWithCapturedOutput ( $"sln App.sln add {projectToAdd}" ) ;
2017-01-05 04:32:09 +00:00
cmd . Should ( ) . Pass ( ) ;
var slnPath = Path . Combine ( projectDirectory , "App.sln" ) ;
var expectedSlnContents = GetExpectedSlnContents ( slnPath , ExpectedSlnFileAfterAddingNestedProj ) ;
File . ReadAllText ( slnPath )
. Should ( ) . BeVisuallyEquivalentTo ( expectedSlnContents ) ;
}
2017-01-21 02:34:37 +00:00
[Fact]
public void WhenProjectDirectoryIsAddedSolutionFoldersAreNotCreated ( )
{
var projectDirectory = TestAssets
. Get ( "TestAppWithSlnAndCsprojFiles" )
. CreateInstance ( )
. WithSourceFiles ( )
. Root
. FullName ;
var projectToAdd = Path . Combine ( "Lib" , "Lib.csproj" ) ;
var cmd = new DotnetCommand ( )
. WithWorkingDirectory ( projectDirectory )
. ExecuteWithCapturedOutput ( $"sln App.sln add {projectToAdd}" ) ;
cmd . Should ( ) . Pass ( ) ;
var slnFile = SlnFile . Read ( Path . Combine ( projectDirectory , "App.sln" ) ) ;
var solutionFolderProjects = slnFile . Projects . Where (
p = > p . TypeGuid = = ProjectTypeGuids . SolutionFolderGuid ) ;
solutionFolderProjects . Count ( ) . Should ( ) . Be ( 0 ) ;
slnFile . Sections . GetSection ( "NestedProjects" ) . Should ( ) . BeNull ( ) ;
}
[Theory]
[InlineData(".")]
[InlineData("")]
public void WhenSolutionFolderExistsItDoesNotGetAdded ( string firstComponent )
{
var projectDirectory = TestAssets
. Get ( "TestAppWithSlnAndSolutionFolders" )
. CreateInstance ( )
. WithSourceFiles ( )
. Root
. FullName ;
var projectToAdd = Path . Combine ( $"{firstComponent}" , "src" , "src" , "Lib" , "Lib.csproj" ) ;
var cmd = new DotnetCommand ( )
. WithWorkingDirectory ( projectDirectory )
. ExecuteWithCapturedOutput ( $"sln App.sln add {projectToAdd}" ) ;
cmd . Should ( ) . Pass ( ) ;
var slnFile = SlnFile . Read ( Path . Combine ( projectDirectory , "App.sln" ) ) ;
slnFile . Projects . Count ( ) . Should ( ) . Be ( 4 ) ;
var solutionFolderProjects = slnFile . Projects . Where (
p = > p . TypeGuid = = ProjectTypeGuids . SolutionFolderGuid ) ;
solutionFolderProjects . Count ( ) . Should ( ) . Be ( 2 ) ;
var solutionFolders = slnFile . Sections . GetSection ( "NestedProjects" ) . Properties ;
solutionFolders . Count . Should ( ) . Be ( 3 ) ;
solutionFolders [ "{DDF3765C-59FB-4AA6-BE83-779ED13AA64A}" ]
. Should ( ) . Be ( "{72BFCA87-B033-4721-8712-4D12166B4A39}" ) ;
var newlyAddedSrcFolder = solutionFolderProjects . Where (
p = > p . Id ! = "{72BFCA87-B033-4721-8712-4D12166B4A39}" ) . Single ( ) ;
solutionFolders [ newlyAddedSrcFolder . Id ]
. Should ( ) . Be ( "{72BFCA87-B033-4721-8712-4D12166B4A39}" ) ;
var libProject = slnFile . Projects . Where ( p = > p . Name = = "Lib" ) . Single ( ) ;
solutionFolders [ libProject . Id ]
. Should ( ) . Be ( newlyAddedSrcFolder . Id ) ;
}
2016-12-14 23:53:11 +00:00
[Theory]
2017-01-03 17:18:45 +00:00
[InlineData("TestAppWithSlnAndCsprojFiles", ExpectedSlnFileAfterAddingLibProj, "")]
[InlineData("TestAppWithSlnAndCsprojProjectGuidFiles", ExpectedSlnFileAfterAddingLibProj, "{84A45D44-B677-492D-A6DA-B3A71135AB8E}")]
[InlineData("TestAppWithEmptySln", ExpectedSlnFileAfterAddingLibProjToEmptySln, "")]
public void WhenValidProjectIsPassedBuildConfigsAreAdded (
2016-12-14 23:53:11 +00:00
string testAsset ,
2017-01-03 17:18:45 +00:00
string expectedSlnContentsTemplate ,
string expectedProjectGuid )
{
var projectDirectory = TestAssets
. Get ( testAsset )
. CreateInstance ( )
. WithSourceFiles ( )
. Root
. FullName ;
var projectToAdd = "Lib/Lib.csproj" ;
var cmd = new DotnetCommand ( )
. WithWorkingDirectory ( projectDirectory )
2017-01-06 20:58:23 +00:00
. ExecuteWithCapturedOutput ( $"sln App.sln add {projectToAdd}" ) ;
2017-01-03 17:18:45 +00:00
cmd . Should ( ) . Pass ( ) ;
var slnPath = Path . Combine ( projectDirectory , "App.sln" ) ;
2017-01-05 04:32:09 +00:00
var expectedSlnContents = GetExpectedSlnContents (
slnPath ,
expectedSlnContentsTemplate ,
expectedProjectGuid ) ;
2017-01-03 17:18:45 +00:00
File . ReadAllText ( slnPath )
. Should ( ) . BeVisuallyEquivalentTo ( expectedSlnContents ) ;
}
[Theory]
[InlineData("TestAppWithSlnAndCsprojFiles")]
[InlineData("TestAppWithSlnAndCsprojProjectGuidFiles")]
[InlineData("TestAppWithEmptySln")]
public void WhenValidProjectIsPassedItGetsAdded ( string testAsset )
2016-12-14 23:53:11 +00:00
{
2016-12-16 09:04:09 +00:00
var projectDirectory = TestAssets
. Get ( testAsset )
. CreateInstance ( )
. WithSourceFiles ( )
. Root
. FullName ;
2016-12-14 23:53:11 +00:00
var projectToAdd = "Lib/Lib.csproj" ;
2016-12-20 23:04:01 +00:00
var projectPath = Path . Combine ( "Lib" , "Lib.csproj" ) ;
2016-12-14 23:53:11 +00:00
var cmd = new DotnetCommand ( )
. WithWorkingDirectory ( projectDirectory )
2017-01-06 20:58:23 +00:00
. ExecuteWithCapturedOutput ( $"sln App.sln add {projectToAdd}" ) ;
2016-12-14 23:53:11 +00:00
cmd . Should ( ) . Pass ( ) ;
2016-12-20 23:04:01 +00:00
cmd . StdOut . Should ( ) . Be ( $"Project `{projectPath}` added to the solution." ) ;
2016-12-14 23:53:11 +00:00
cmd . StdErr . Should ( ) . BeEmpty ( ) ;
2017-01-03 17:18:45 +00:00
}
2017-03-08 19:33:27 +00:00
[Theory]
[InlineData("TestAppWithSlnAndCsprojFiles")]
[InlineData("TestAppWithSlnAndCsprojProjectGuidFiles")]
2017-05-06 00:08:00 +00:00
[InlineData("TestAppWithEmptySln")]
public void WhenInvalidProjectIsPassedItDoesNotGetAdded ( string testAsset )
{
var projectDirectory = TestAssets
. Get ( testAsset )
. CreateInstance ( )
. WithSourceFiles ( )
. Root
. FullName ;
var projectToAdd = "Lib/Library.cs" ;
var projectPath = Path . Combine ( "Lib" , "Library.cs" ) ;
var slnFile = SlnFile . Read ( Path . Combine ( projectDirectory , "App.sln" ) ) ;
var expectedNumberOfProjects = slnFile . Projects . Count ( ) ;
var cmd = new DotnetCommand ( )
. WithWorkingDirectory ( projectDirectory )
. ExecuteWithCapturedOutput ( $"sln App.sln add {projectToAdd}" ) ;
cmd . Should ( ) . Pass ( ) ;
cmd . StdOut . Should ( ) . BeEmpty ( ) ;
cmd . StdErr . Should ( ) . Match ( "Invalid project `*`. The project file could not be loaded.*" ) ;
slnFile = SlnFile . Read ( Path . Combine ( projectDirectory , "App.sln" ) ) ;
slnFile . Projects . Count ( ) . Should ( ) . Be ( expectedNumberOfProjects ) ;
}
[Theory]
[InlineData("TestAppWithSlnAndCsprojFiles")]
[InlineData("TestAppWithSlnAndCsprojProjectGuidFiles")]
2017-03-08 19:33:27 +00:00
[InlineData("TestAppWithEmptySln")]
2017-01-03 17:18:45 +00:00
public void WhenValidProjectIsPassedTheSlnBuilds ( string testAsset )
{
var projectDirectory = TestAssets
. Get ( testAsset )
. CreateInstance ( )
. WithSourceFiles ( )
. Root
. FullName ;
2016-12-14 23:53:11 +00:00
2017-01-03 17:18:45 +00:00
var cmd = new DotnetCommand ( )
. WithWorkingDirectory ( projectDirectory )
2017-01-06 20:58:23 +00:00
. ExecuteWithCapturedOutput ( @"sln App.sln add App/App.csproj Lib/Lib.csproj" ) ;
2017-01-03 17:18:45 +00:00
cmd . Should ( ) . Pass ( ) ;
2016-12-14 23:53:11 +00:00
2017-01-03 17:18:45 +00:00
var slnPath = Path . Combine ( projectDirectory , "App.sln" ) ;
2016-12-14 23:53:11 +00:00
2017-01-03 17:18:45 +00:00
new DotnetCommand ( )
2016-12-14 23:53:11 +00:00
. WithWorkingDirectory ( projectDirectory )
2017-01-03 17:18:45 +00:00
. Execute ( $"restore App.sln" )
. Should ( ) . Pass ( ) ;
2016-12-14 23:53:11 +00:00
2017-01-03 17:18:45 +00:00
new DotnetCommand ( )
2016-12-14 23:53:11 +00:00
. WithWorkingDirectory ( projectDirectory )
2017-01-03 17:18:45 +00:00
. Execute ( "build App.sln --configuration Release" )
. Should ( ) . Pass ( ) ;
var reasonString = "should be built in release mode, otherwise it means build configurations are missing from the sln file" ;
var appReleaseDirectory = Directory . EnumerateDirectories (
Path . Combine ( projectDirectory , "App" , "bin" ) ,
"Release" ,
SearchOption . AllDirectories ) ;
appReleaseDirectory . Count ( ) . Should ( ) . Be ( 1 , $"App {reasonString}" ) ;
Directory . EnumerateFiles ( appReleaseDirectory . Single ( ) , "App.dll" , SearchOption . AllDirectories )
. Count ( ) . Should ( ) . Be ( 1 , $"App {reasonString}" ) ;
var libReleaseDirectory = Directory . EnumerateDirectories (
Path . Combine ( projectDirectory , "Lib" , "bin" ) ,
"Release" ,
SearchOption . AllDirectories ) ;
libReleaseDirectory . Count ( ) . Should ( ) . Be ( 1 , $"Lib {reasonString}" ) ;
Directory . EnumerateFiles ( libReleaseDirectory . Single ( ) , "Lib.dll" , SearchOption . AllDirectories )
. Count ( ) . Should ( ) . Be ( 1 , $"Lib {reasonString}" ) ;
2016-12-14 23:53:11 +00:00
}
2017-02-14 23:47:06 +00:00
[Theory]
[InlineData("TestAppWithSlnAndExistingCsprojReferences")]
[InlineData("TestAppWithSlnAndExistingCsprojReferencesWithEscapedDirSep")]
public void WhenSolutionAlreadyContainsProjectItDoesntDuplicate ( string testAsset )
2016-12-14 23:53:11 +00:00
{
2016-12-16 09:04:09 +00:00
var projectDirectory = TestAssets
2017-02-14 23:47:06 +00:00
. Get ( testAsset )
2016-12-16 09:04:09 +00:00
. CreateInstance ( )
. WithSourceFiles ( )
. Root
. FullName ;
var solutionPath = Path . Combine ( projectDirectory , "App.sln" ) ;
2016-12-14 23:53:11 +00:00
var projectToAdd = Path . Combine ( "Lib" , "Lib.csproj" ) ;
var cmd = new DotnetCommand ( )
. WithWorkingDirectory ( projectDirectory )
2017-01-06 20:58:23 +00:00
. ExecuteWithCapturedOutput ( $"sln App.sln add {projectToAdd}" ) ;
2016-12-14 23:53:11 +00:00
cmd . Should ( ) . Pass ( ) ;
2016-12-16 09:04:09 +00:00
cmd . StdOut . Should ( ) . Be ( $"Solution {solutionPath} already contains project {projectToAdd}." ) ;
2016-12-14 23:53:11 +00:00
cmd . StdErr . Should ( ) . BeEmpty ( ) ;
}
[Fact]
public void WhenPassedMultipleProjectsAndOneOfthemDoesNotExistItCancelsWholeOperation ( )
{
2016-12-16 09:04:09 +00:00
var projectDirectory = TestAssets
. Get ( "TestAppWithSlnAndCsprojFiles" )
. CreateInstance ( )
. WithSourceFiles ( )
. Root
. FullName ;
2016-12-14 23:53:11 +00:00
var slnFullPath = Path . Combine ( projectDirectory , "App.sln" ) ;
var contentBefore = File . ReadAllText ( slnFullPath ) ;
var projectToAdd = Path . Combine ( "Lib" , "Lib.csproj" ) ;
var cmd = new DotnetCommand ( )
. WithWorkingDirectory ( projectDirectory )
2017-01-06 20:58:23 +00:00
. ExecuteWithCapturedOutput ( $"sln App.sln add {projectToAdd} idonotexist.csproj" ) ;
2016-12-14 23:53:11 +00:00
cmd . Should ( ) . Fail ( ) ;
2016-12-16 09:04:09 +00:00
cmd . StdErr . Should ( ) . Be ( "Project `idonotexist.csproj` does not exist." ) ;
2016-12-14 23:53:11 +00:00
File . ReadAllText ( slnFullPath )
2017-01-03 17:18:45 +00:00
. Should ( ) . BeVisuallyEquivalentTo ( contentBefore ) ;
2016-12-14 23:53:11 +00:00
}
2017-01-05 04:32:09 +00:00
2017-01-05 22:04:57 +00:00
//ISSUE: https://github.com/dotnet/sdk/issues/522
//[Fact]
public void WhenPassedAnUnknownProjectTypeItFails ( )
{
var projectDirectory = TestAssets
. Get ( "SlnFileWithNoProjectReferencesAndUnknownProject" )
. CreateInstance ( )
. WithSourceFiles ( )
. Root
. FullName ;
var slnFullPath = Path . Combine ( projectDirectory , "App.sln" ) ;
var contentBefore = File . ReadAllText ( slnFullPath ) ;
var projectToAdd = Path . Combine ( "UnknownProject" , "UnknownProject.unknownproj" ) ;
var cmd = new DotnetCommand ( )
. WithWorkingDirectory ( projectDirectory )
2017-01-06 20:58:23 +00:00
. ExecuteWithCapturedOutput ( $"sln App.sln add {projectToAdd}" ) ;
2017-01-05 22:04:57 +00:00
cmd . Should ( ) . Fail ( ) ;
cmd . StdErr . Should ( ) . BeVisuallyEquivalentTo ( "Unsupported project type. Please check with your sdk provider." ) ;
File . ReadAllText ( slnFullPath )
. Should ( ) . BeVisuallyEquivalentTo ( contentBefore ) ;
}
[Theory]
//ISSUE: https://github.com/dotnet/sdk/issues/522
//[InlineData("SlnFileWithNoProjectReferencesAndCSharpProject", "CSharpProject", "CSharpProject.csproj", ProjectTypeGuids.CSharpProjectTypeGuid)]
//[InlineData("SlnFileWithNoProjectReferencesAndFSharpProject", "FSharpProject", "FSharpProject.fsproj", "{F2A71F9B-5D33-465A-A702-920D77279786}")]
//[InlineData("SlnFileWithNoProjectReferencesAndVBProject", "VBProject", "VBProject.vbproj", "{F184B08F-C81C-45F6-A57F-5ABD9991F28F}")]
[InlineData("SlnFileWithNoProjectReferencesAndUnknownProjectWithSingleProjectTypeGuid", "UnknownProject", "UnknownProject.unknownproj", "{130159A9-F047-44B3-88CF-0CF7F02ED50F}")]
[InlineData("SlnFileWithNoProjectReferencesAndUnknownProjectWithMultipleProjectTypeGuids", "UnknownProject", "UnknownProject.unknownproj", "{130159A9-F047-44B3-88CF-0CF7F02ED50F}")]
public void WhenPassedAProjectItAddsCorrectProjectTypeGuid (
string testAsset ,
string projectDir ,
string projectName ,
string expectedTypeGuid )
{
var projectDirectory = TestAssets
. Get ( testAsset )
. CreateInstance ( )
. WithSourceFiles ( )
. Root
. FullName ;
var projectToAdd = Path . Combine ( projectDir , projectName ) ;
var cmd = new DotnetCommand ( )
. WithWorkingDirectory ( projectDirectory )
2017-01-06 20:58:23 +00:00
. ExecuteWithCapturedOutput ( $"sln App.sln add {projectToAdd}" ) ;
2017-01-05 22:04:57 +00:00
cmd . Should ( ) . Pass ( ) ;
cmd . StdOut . Should ( ) . Be ( $"Project `{projectToAdd}` added to the solution." ) ;
cmd . StdErr . Should ( ) . BeEmpty ( ) ;
var slnFile = SlnFile . Read ( Path . Combine ( projectDirectory , "App.sln" ) ) ;
var nonSolutionFolderProjects = slnFile . Projects . Where (
p = > p . TypeGuid ! = ProjectTypeGuids . SolutionFolderGuid ) ;
nonSolutionFolderProjects . Count ( ) . Should ( ) . Be ( 1 ) ;
nonSolutionFolderProjects . Single ( ) . TypeGuid . Should ( ) . Be ( expectedTypeGuid ) ;
}
2017-02-14 23:47:06 +00:00
[Fact]
private void WhenSlnContainsSolutionFolderWithDifferentCasingItDoesNotCreateDuplicate ( )
{
var projectDirectory = TestAssets
. Get ( "TestAppWithSlnAndCaseSensitiveSolutionFolders" )
. CreateInstance ( )
. WithSourceFiles ( )
. Root
. FullName ;
var projectToAdd = Path . Combine ( "src" , "Lib" , "Lib.csproj" ) ;
var cmd = new DotnetCommand ( )
. WithWorkingDirectory ( projectDirectory )
. Execute ( $"sln App.sln add {projectToAdd}" ) ;
cmd . Should ( ) . Pass ( ) ;
var slnFile = SlnFile . Read ( Path . Combine ( projectDirectory , "App.sln" ) ) ;
var solutionFolderProjects = slnFile . Projects . Where (
p = > p . TypeGuid = = ProjectTypeGuids . SolutionFolderGuid ) ;
solutionFolderProjects . Count ( ) . Should ( ) . Be ( 1 ) ;
}
2017-01-05 04:32:09 +00:00
private string GetExpectedSlnContents (
string slnPath ,
string slnTemplate ,
string expectedLibProjectGuid = null )
{
var slnFile = SlnFile . Read ( slnPath ) ;
if ( string . IsNullOrEmpty ( expectedLibProjectGuid ) )
{
var matchingProjects = slnFile . Projects
. Where ( ( p ) = > p . FilePath . EndsWith ( "Lib.csproj" ) )
. ToList ( ) ;
matchingProjects . Count . Should ( ) . Be ( 1 ) ;
var slnProject = matchingProjects [ 0 ] ;
expectedLibProjectGuid = slnProject . Id ;
}
var slnContents = slnTemplate . Replace ( "__LIB_PROJECT_GUID__" , expectedLibProjectGuid ) ;
var matchingSrcFolder = slnFile . Projects
. Where ( ( p ) = > p . FilePath = = "src" )
. ToList ( ) ;
if ( matchingSrcFolder . Count = = 1 )
{
slnContents = slnContents . Replace ( "__SRC_FOLDER_GUID__" , matchingSrcFolder [ 0 ] . Id ) ;
}
return slnContents ;
}
2016-12-14 23:53:11 +00:00
}
}