diff --git a/Directory.Packages.props b/Directory.Packages.props index 1d941c1212fd..dc9e43222cf0 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -1,5 +1,5 @@ - + $(NoWarn);NU1507 @@ -12,7 +12,7 @@ - + @@ -42,7 +42,7 @@ - + @@ -66,6 +66,7 @@ + @@ -94,11 +95,11 @@ - - - - - + + + + + @@ -118,7 +119,7 @@ - + - + https://github.com/dotnet/source-build-externals - b11ed370b79aa475535a5803856b7c7d0977235e + 1ffe36b3379a0b7ced63d134e5daf30948c03306 diff --git a/src/Cli/dotnet/commands/dotnet-sln/LocalizableStrings.resx b/src/Cli/dotnet/commands/dotnet-sln/LocalizableStrings.resx index 37c35e84400d..4748d3d4504b 100644 --- a/src/Cli/dotnet/commands/dotnet-sln/LocalizableStrings.resx +++ b/src/Cli/dotnet/commands/dotnet-sln/LocalizableStrings.resx @@ -177,4 +177,16 @@ Solution Folder(s) - + + Generate a .slnx file from a .sln file. + + + .slnx file {0} generated. + + + Only .sln files can be migrated to .slnx format. + + + Could not read solution file {0}. Supported files are .sln and .slnx valid solutions. + + \ No newline at end of file diff --git a/src/Cli/dotnet/commands/dotnet-sln/SlnCommandParser.cs b/src/Cli/dotnet/commands/dotnet-sln/SlnCommandParser.cs index dc5693470b86..b2a2f685b752 100644 --- a/src/Cli/dotnet/commands/dotnet-sln/SlnCommandParser.cs +++ b/src/Cli/dotnet/commands/dotnet-sln/SlnCommandParser.cs @@ -2,6 +2,10 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.CommandLine; +using Microsoft.DotNet.Cli.Utils; +using Microsoft.DotNet.Tools; +using Microsoft.VisualStudio.SolutionPersistence; +using Microsoft.VisualStudio.SolutionPersistence.Serializer; using NuGet.Packaging; using LocalizableStrings = Microsoft.DotNet.Tools.Sln.LocalizableStrings; @@ -37,10 +41,45 @@ private static CliCommand ConstructCommand() command.Subcommands.Add(SlnAddParser.GetCommand()); command.Subcommands.Add(SlnListParser.GetCommand()); command.Subcommands.Add(SlnRemoveParser.GetCommand()); + command.Subcommands.Add(SlnMigrateCommandParser.GetCommand()); command.SetAction((parseResult) => parseResult.HandleMissingCommand()); return command; } + + internal static string GetSlnFileFullPath(string slnFileOrDirectory) + { + if (File.Exists(slnFileOrDirectory)) + { + return Path.GetFullPath(slnFileOrDirectory); + } + if (Directory.Exists(slnFileOrDirectory)) + { + string[] files = [ + ..Directory.GetFiles(slnFileOrDirectory, "*.sln", SearchOption.TopDirectoryOnly), + ..Directory.GetFiles(slnFileOrDirectory, "*.slnx", SearchOption.TopDirectoryOnly)]; + if (files.Length == 0) + { + throw new GracefulException(CommonLocalizableStrings.CouldNotFindSolutionIn, slnFileOrDirectory); + } + if (files.Length > 1) + { + throw new GracefulException(CommonLocalizableStrings.MoreThanOneSolutionInDirectory, slnFileOrDirectory); + } + return Path.GetFullPath(files.Single()); + } + throw new GracefulException(CommonLocalizableStrings.CouldNotFindSolutionOrDirectory, slnFileOrDirectory); + } + + internal static ISolutionSerializer GetSolutionSerializer(string solutionFilePath) + { + ISolutionSerializer? serializer = SolutionSerializers.GetSerializerByMoniker(solutionFilePath); + if (serializer is null) + { + throw new GracefulException(LocalizableStrings.SerializerNotFound, solutionFilePath); + } + return serializer; + } } } diff --git a/src/Cli/dotnet/commands/dotnet-sln/add/Program.cs b/src/Cli/dotnet/commands/dotnet-sln/add/Program.cs index ded4c5fc3968..e7c7d39e1291 100644 --- a/src/Cli/dotnet/commands/dotnet-sln/add/Program.cs +++ b/src/Cli/dotnet/commands/dotnet-sln/add/Program.cs @@ -1,144 +1,180 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System; using System.CommandLine; +using Microsoft.Build.Construction; +using Microsoft.Build.Exceptions; +using Microsoft.Build.Execution; using Microsoft.DotNet.Cli; -using Microsoft.DotNet.Cli.Sln.Internal; using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.Tools.Common; +using Microsoft.VisualStudio.SolutionPersistence; +using Microsoft.VisualStudio.SolutionPersistence.Model; +using Microsoft.VisualStudio.SolutionPersistence.Serializer.SlnV12; namespace Microsoft.DotNet.Tools.Sln.Add { internal class AddProjectToSolutionCommand : CommandBase { + private static string[] _defaultPlatforms = new[] { "Any CPU", "x64", "x86" }; + private static string[] _defaultBuildTypes = new[] { "Debug", "Release" }; private readonly string _fileOrDirectory; private readonly bool _inRoot; - private readonly IList _relativeRootSolutionFolders; - private readonly IReadOnlyCollection _arguments; + private readonly IReadOnlyCollection _projects; + private readonly string? _solutionFolderPath; + + private static string GetSolutionFolderPathWithForwardSlashes(string path) + { + // SolutionModel::AddFolder expects paths to have leading, trailing and inner forward slashes + // https://github.com/microsoft/vs-solutionpersistence/blob/87ee8ea069662d55c336a9bd68fe4851d0384fa5/src/Microsoft.VisualStudio.SolutionPersistence/Model/SolutionModel.cs#L171C1-L172C1 + return "/" + string.Join("/", PathUtility.GetPathWithDirectorySeparator(path).Split(Path.DirectorySeparatorChar, StringSplitOptions.RemoveEmptyEntries)) + "/"; + } public AddProjectToSolutionCommand(ParseResult parseResult) : base(parseResult) { _fileOrDirectory = parseResult.GetValue(SlnCommandParser.SlnArgument); - - _arguments = parseResult.GetValue(SlnAddParser.ProjectPathArgument)?.ToArray() ?? (IReadOnlyCollection)Array.Empty(); - + _projects = (IReadOnlyCollection)(parseResult.GetValue(SlnAddParser.ProjectPathArgument) ?? []); _inRoot = parseResult.GetValue(SlnAddParser.InRootOption); - string relativeRoot = parseResult.GetValue(SlnAddParser.SolutionFolderOption); - - SlnArgumentValidator.ParseAndValidateArguments(_fileOrDirectory, _arguments, SlnArgumentValidator.CommandType.Add, _inRoot, relativeRoot); - - bool hasRelativeRoot = !string.IsNullOrEmpty(relativeRoot); - - if (hasRelativeRoot) - { - relativeRoot = PathUtility.GetPathWithDirectorySeparator(relativeRoot); - _relativeRootSolutionFolders = relativeRoot.Split(Path.DirectorySeparatorChar, StringSplitOptions.RemoveEmptyEntries); - } - else - { - _relativeRootSolutionFolders = null; - } + _solutionFolderPath = parseResult.GetValue(SlnAddParser.SolutionFolderOption); + SlnArgumentValidator.ParseAndValidateArguments(_fileOrDirectory, _projects, SlnArgumentValidator.CommandType.Add, _inRoot, _solutionFolderPath); } public override int Execute() { - SlnFile slnFile = SlnFileFactory.CreateFromFileOrDirectory(_fileOrDirectory); - - var arguments = (_parseResult.GetValue>(SlnAddParser.ProjectPathArgument) ?? Array.Empty()).ToList().AsReadOnly(); - if (arguments.Count == 0) + if (_projects.Count == 0) { throw new GracefulException(CommonLocalizableStrings.SpecifyAtLeastOneProjectToAdd); } + string solutionFileFullPath = SlnCommandParser.GetSlnFileFullPath(_fileOrDirectory); - PathUtility.EnsureAllPathsExist(arguments, CommonLocalizableStrings.CouldNotFindProjectOrDirectory, true); - - var fullProjectPaths = _arguments.Select(p => - { - var fullPath = Path.GetFullPath(p); - return Directory.Exists(fullPath) ? - MsbuildProject.GetProjectFileFromDirectory(fullPath).FullName : - fullPath; - }).ToList(); - - var preAddProjectCount = slnFile.Projects.Count; - - foreach (var fullProjectPath in fullProjectPaths) + try { - // Identify the intended solution folders - var solutionFolders = DetermineSolutionFolder(slnFile, fullProjectPath); - - slnFile.AddProject(fullProjectPath, solutionFolders); + PathUtility.EnsureAllPathsExist(_projects, CommonLocalizableStrings.CouldNotFindProjectOrDirectory, true); + IEnumerable fullProjectPaths = _projects.Select(project => + { + var fullPath = Path.GetFullPath(project); + return Directory.Exists(fullPath) ? MsbuildProject.GetProjectFileFromDirectory(fullPath).FullName : fullPath; + }); + AddProjectsToSolutionAsync(solutionFileFullPath, fullProjectPaths, CancellationToken.None).GetAwaiter().GetResult(); + return 0; } - - if (slnFile.Projects.Count > preAddProjectCount) + catch (Exception ex) when (ex is not GracefulException) { - slnFile.Write(); + { + if (ex is SolutionException || ex.InnerException is SolutionException) + { + throw new GracefulException(CommonLocalizableStrings.InvalidSolutionFormatString, solutionFileFullPath, ex.Message); + } + throw new GracefulException(ex.Message, ex); + } } - - return 0; } - private static IList GetSolutionFoldersFromProjectPath(string projectFilePath) + private async Task AddProjectsToSolutionAsync(string solutionFileFullPath, IEnumerable projectPaths, CancellationToken cancellationToken) { - var solutionFolders = new List(); - - if (!IsPathInTreeRootedAtSolutionDirectory(projectFilePath)) - return solutionFolders; - - var currentDirString = $".{Path.DirectorySeparatorChar}"; - if (projectFilePath.StartsWith(currentDirString)) + ISolutionSerializer serializer = SlnCommandParser.GetSolutionSerializer(solutionFileFullPath); + SolutionModel solution = await serializer.OpenAsync(solutionFileFullPath, cancellationToken); + // set UTF8 BOM encoding for .sln + if (serializer is ISolutionSerializer v12Serializer) { - projectFilePath = projectFilePath.Substring(currentDirString.Length); + solution.SerializerExtension = v12Serializer.CreateModelExtension(new() + { + Encoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: true) + }); + } + // Set default configurations and platforms for sln file + foreach (var platform in _defaultPlatforms) + { + solution.AddPlatform(platform); + } + foreach (var buildType in _defaultBuildTypes) + { + solution.AddBuildType(buildType); } - var projectDirectoryPath = TrimProject(projectFilePath); - if (string.IsNullOrEmpty(projectDirectoryPath)) - return solutionFolders; - - var solutionFoldersPath = TrimProjectDirectory(projectDirectoryPath); - if (string.IsNullOrEmpty(solutionFoldersPath)) - return solutionFolders; - - solutionFolders.AddRange(solutionFoldersPath.Split(Path.DirectorySeparatorChar)); + SolutionFolderModel? solutionFolder = (!_inRoot && !string.IsNullOrEmpty(_solutionFolderPath)) + ? solution.AddFolder(GetSolutionFolderPathWithForwardSlashes(_solutionFolderPath)) + : null; - return solutionFolders; + foreach (var projectPath in projectPaths) + { + string relativePath = Path.GetRelativePath(Path.GetDirectoryName(solutionFileFullPath), projectPath); + // Add fallback solution folder + string relativeSolutionFolder = Path.GetDirectoryName(relativePath); + if (!_inRoot && solutionFolder is null && !string.IsNullOrEmpty(relativeSolutionFolder)) + { + if (relativeSolutionFolder.Split(Path.DirectorySeparatorChar).LastOrDefault() == Path.GetFileNameWithoutExtension(relativePath)) + { + relativeSolutionFolder = Path.Combine(relativeSolutionFolder.Split(Path.DirectorySeparatorChar).SkipLast(1).ToArray()); + } + if (!string.IsNullOrEmpty(relativeSolutionFolder)) + { + solutionFolder = solution.AddFolder(GetSolutionFolderPathWithForwardSlashes(relativeSolutionFolder)); + } + } + + try + { + AddProject(solution, relativePath, projectPath, solutionFolder, serializer); + } + catch (InvalidProjectFileException ex) + { + Reporter.Error.WriteLine(string.Format(CommonLocalizableStrings.InvalidProjectWithExceptionMessage, projectPath, ex.Message)); + } + catch (SolutionArgumentException ex) when (solution.FindProject(relativePath) != null || ex.Type == SolutionErrorType.DuplicateProjectName) + { + Reporter.Output.WriteLine(CommonLocalizableStrings.SolutionAlreadyContainsProject, solutionFileFullPath, relativePath); + } + } + await serializer.SaveAsync(solutionFileFullPath, solution, cancellationToken); } - private IList DetermineSolutionFolder(SlnFile slnFile, string fullProjectPath) + private void AddProject(SolutionModel solution, string solutionRelativeProjectPath, string fullPath, SolutionFolderModel? solutionFolder, ISolutionSerializer serializer = null) { - if (_inRoot) + // Open project instance to see if it is a valid project + ProjectRootElement projectRootElement = ProjectRootElement.Open(fullPath); + SolutionProjectModel project; + try { - // The user requested all projects go to the root folder - return null; + project = solution.AddProject(solutionRelativeProjectPath, null, solutionFolder); } - - if (_relativeRootSolutionFolders != null) + catch (SolutionArgumentException ex) when (ex.ParamName == "projectTypeName") { - // The user has specified an explicit root - return _relativeRootSolutionFolders; + // If guid is not identified by vs-solutionpersistence, check in project element itself + var guid = projectRootElement.GetProjectTypeGuid(); + if (string.IsNullOrEmpty(guid)) + { + Reporter.Error.WriteLine(CommonLocalizableStrings.UnsupportedProjectType, fullPath); + return; + } + project = solution.AddProject(solutionRelativeProjectPath, guid, solutionFolder); + } + // Add settings based on existing project instance + ProjectInstance projectInstance = new ProjectInstance(projectRootElement); + string projectInstanceId = projectInstance.GetProjectId(); + if (!string.IsNullOrEmpty(projectInstanceId) && serializer is ISolutionSerializer) + { + project.Id = new Guid(projectInstanceId); } - // We determine the root for each individual project - var relativeProjectPath = Path.GetRelativePath( - PathUtility.EnsureTrailingSlash(slnFile.BaseDirectory), - fullProjectPath); - - return GetSolutionFoldersFromProjectPath(relativeProjectPath); - } - - private static bool IsPathInTreeRootedAtSolutionDirectory(string path) - { - return !path.StartsWith(".."); - } + var projectInstanceBuildTypes = projectInstance.GetConfigurations(); + var projectInstancePlatforms = projectInstance.GetPlatforms(); - private static string TrimProject(string path) - { - return Path.GetDirectoryName(path); - } + foreach (var solutionPlatform in solution.Platforms) + { + var projectPlatform = projectInstancePlatforms.FirstOrDefault( + platform => platform.Replace(" ", string.Empty) == solutionPlatform.Replace(" ", string.Empty), projectInstancePlatforms.FirstOrDefault()); + project.AddProjectConfigurationRule(new ConfigurationRule(BuildDimension.Platform, "*", solutionPlatform, projectPlatform)); + } - private static string TrimProjectDirectory(string path) - { - return Path.GetDirectoryName(path); + foreach (var solutionBuildType in solution.BuildTypes) + { + var projectBuildType = projectInstanceBuildTypes.FirstOrDefault( + buildType => buildType.Replace(" ", string.Empty) == solutionBuildType.Replace(" ", string.Empty), projectInstanceBuildTypes.FirstOrDefault()); + project.AddProjectConfigurationRule(new ConfigurationRule(BuildDimension.BuildType, solutionBuildType, "*", projectBuildType)); + } + Reporter.Output.WriteLine(CommonLocalizableStrings.ProjectAddedToTheSolution, solutionRelativeProjectPath); } } } diff --git a/src/Cli/dotnet/commands/dotnet-sln/list/Program.cs b/src/Cli/dotnet/commands/dotnet-sln/list/Program.cs index a46642c421b4..99b948207011 100644 --- a/src/Cli/dotnet/commands/dotnet-sln/list/Program.cs +++ b/src/Cli/dotnet/commands/dotnet-sln/list/Program.cs @@ -5,7 +5,9 @@ using Microsoft.DotNet.Cli; using Microsoft.DotNet.Cli.Sln.Internal; using Microsoft.DotNet.Cli.Utils; -using Microsoft.DotNet.Tools.Common; +using Microsoft.VisualStudio.SolutionPersistence; +using Microsoft.VisualStudio.SolutionPersistence.Model; +using CommandLocalizableStrings = Microsoft.DotNet.Tools.CommonLocalizableStrings; namespace Microsoft.DotNet.Tools.Sln.List { @@ -23,25 +25,36 @@ public ListProjectsInSolutionCommand( public override int Execute() { - var slnFile = SlnFileFactory.CreateFromFileOrDirectory(_fileOrDirectory); + string solutionFileFullPath = SlnCommandParser.GetSlnFileFullPath(_fileOrDirectory); + try + { + ListAllProjectsAsync(solutionFileFullPath, CancellationToken.None).Wait(); + return 0; + } + catch (Exception ex) + { + throw new GracefulException(CommandLocalizableStrings.InvalidSolutionFormatString, solutionFileFullPath, ex.Message); + } + } + private async Task ListAllProjectsAsync(string solutionFileFullPath, CancellationToken cancellationToken) + { + ISolutionSerializer serializer = SlnCommandParser.GetSolutionSerializer(solutionFileFullPath); + SolutionModel solution = await serializer.OpenAsync(solutionFileFullPath, cancellationToken); string[] paths; - if (_displaySolutionFolders) { - paths = slnFile.Projects - .GetProjectsByType(ProjectTypeGuids.SolutionFolderGuid) - .Select(folder => folder.GetFullSolutionFolderPath()) + paths = solution.SolutionFolders + // VS-SolutionPersistence does not return a path object, so there might be issues with forward/backward slashes on different platforms + .Select(folder => Path.GetDirectoryName(folder.Path.TrimStart('/'))) .ToArray(); } else { - paths = slnFile.Projects - .GetProjectsNotOfType(ProjectTypeGuids.SolutionFolderGuid) + paths = solution.SolutionProjects .Select(project => project.FilePath) .ToArray(); } - if (paths.Length == 0) { Reporter.Output.WriteLine(CommonLocalizableStrings.NoProjectsFound); @@ -51,14 +64,14 @@ public override int Execute() Array.Sort(paths); string header = _displaySolutionFolders ? LocalizableStrings.SolutionFolderHeader : LocalizableStrings.ProjectsHeader; - Reporter.Output.WriteLine($"{header}"); + Reporter.Output.WriteLine(header); Reporter.Output.WriteLine(new string('-', header.Length)); foreach (string slnProject in paths) { Reporter.Output.WriteLine(slnProject); } } - return 0; + } } } diff --git a/src/Cli/dotnet/commands/dotnet-sln/migrate/SlnMigrateCommand.cs b/src/Cli/dotnet/commands/dotnet-sln/migrate/SlnMigrateCommand.cs new file mode 100644 index 000000000000..1ac8dde1468e --- /dev/null +++ b/src/Cli/dotnet/commands/dotnet-sln/migrate/SlnMigrateCommand.cs @@ -0,0 +1,59 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.CommandLine; +using System.Linq; +using System.Text; +using System.IO; +using System.Threading.Tasks; +using Microsoft.DotNet.Cli.Utils; +using Microsoft.DotNet.Tools; +using Microsoft.VisualStudio.SolutionPersistence; +using Microsoft.VisualStudio.SolutionPersistence.Model; +using Microsoft.VisualStudio.SolutionPersistence.Serializer; +using LocalizableStrings = Microsoft.DotNet.Tools.Sln.LocalizableStrings; +using Microsoft.DotNet.Tools.Common; + +namespace Microsoft.DotNet.Cli +{ + internal class SlnMigrateCommand : CommandBase + { + private readonly string _slnFileOrDirectory; + private readonly IReporter _reporter; + public SlnMigrateCommand( + ParseResult parseResult, + IReporter reporter = null) + : base(parseResult) + { + _slnFileOrDirectory = parseResult.GetValue(SlnCommandParser.SlnArgument); + _reporter = reporter ?? Reporter.Output; + } + + public override int Execute() + { + string slnFileFullPath = SlnCommandParser.GetSlnFileFullPath(_slnFileOrDirectory); + if (slnFileFullPath.HasExtension(".slnx")) + { + throw new GracefulException(LocalizableStrings.CannotMigrateSlnx); + } + string slnxFileFullPath = Path.ChangeExtension(slnFileFullPath, "slnx"); + try + { + ConvertToSlnxAsync(slnFileFullPath, slnxFileFullPath, CancellationToken.None).Wait(); + return 0; + } catch (Exception ex) { + throw new GracefulException(ex.Message, ex); + } + } + + private async Task ConvertToSlnxAsync(string filePath, string slnxFilePath, CancellationToken cancellationToken) + { + ISolutionSerializer serializer = SlnCommandParser.GetSolutionSerializer(filePath); + SolutionModel solution = await serializer.OpenAsync(filePath, cancellationToken); + await SolutionSerializers.SlnXml.SaveAsync(slnxFilePath, solution, cancellationToken); + _reporter.WriteLine(LocalizableStrings.SlnxGenerated, slnxFilePath); + } + } +} diff --git a/src/Cli/dotnet/commands/dotnet-sln/migrate/SlnMigrateCommandParser.cs b/src/Cli/dotnet/commands/dotnet-sln/migrate/SlnMigrateCommandParser.cs new file mode 100644 index 000000000000..90b6a9dac7f3 --- /dev/null +++ b/src/Cli/dotnet/commands/dotnet-sln/migrate/SlnMigrateCommandParser.cs @@ -0,0 +1,30 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.CommandLine; +using Microsoft.DotNet.Tools.Sln.Add; +using LocalizableStrings = Microsoft.DotNet.Tools.Sln.LocalizableStrings; + +namespace Microsoft.DotNet.Cli +{ + public static class SlnMigrateCommandParser + { + private static readonly CliCommand Command = ConstructCommand(); + + public static CliCommand GetCommand() + { + return Command; + } + + private static CliCommand ConstructCommand() + { + CliCommand command = new("migrate", LocalizableStrings.MigrateAppFullName); + + command.Arguments.Add(SlnCommandParser.SlnArgument); + + command.SetAction((parseResult) => new SlnMigrateCommand(parseResult).Execute()); + + return command; + } + } +} diff --git a/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.cs.xlf b/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.cs.xlf index 3474723c6369..f5b32233e7d0 100644 --- a/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.cs.xlf +++ b/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.cs.xlf @@ -27,6 +27,11 @@ Přidá do souboru řešení jeden nebo více projektů. + + Only .sln files can be migrated to .slnx format. + Only .sln files can be migrated to .slnx format. + + Place project in root of the solution, rather than creating a solution folder. Umístěte projekt do kořene řešení, není potřeba vytvářet složku řešení. @@ -37,6 +42,11 @@ Zobrazí cesty ke složkám řešení. + + Generate a .slnx file from a .sln file. + Generate a .slnx file from a .sln file. + + Remove one or more projects from a solution file. Odebere ze souboru řešení jeden nebo více projektů. @@ -57,6 +67,16 @@ Vypíše seznam všech projektů v řešení. + + Could not read solution file {0}. Supported files are .sln and .slnx valid solutions. + Could not read solution file {0}. Supported files are .sln and .slnx valid solutions. + + + + .slnx file {0} generated. + .slnx file {0} generated. + + SLN_FILE SLN_FILE diff --git a/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.de.xlf b/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.de.xlf index af20cd64a8f8..f8eb231f7950 100644 --- a/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.de.xlf +++ b/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.de.xlf @@ -27,6 +27,11 @@ Fügt einer Projektmappendatei ein oder mehrere Projekte hinzu. + + Only .sln files can be migrated to .slnx format. + Only .sln files can be migrated to .slnx format. + + Place project in root of the solution, rather than creating a solution folder. Platzieren Sie das Projekt im Stamm der Projektmappe, statt einen Projektmappenordner zu erstellen. @@ -37,6 +42,11 @@ Projektmappenordnerpfade anzeigen. + + Generate a .slnx file from a .sln file. + Generate a .slnx file from a .sln file. + + Remove one or more projects from a solution file. Entfernt ein oder mehrere Projekte von einer Projektmappendatei. @@ -57,6 +67,16 @@ Listet alle Projekte in der Projektmappe auf. + + Could not read solution file {0}. Supported files are .sln and .slnx valid solutions. + Could not read solution file {0}. Supported files are .sln and .slnx valid solutions. + + + + .slnx file {0} generated. + .slnx file {0} generated. + + SLN_FILE SLN_FILE diff --git a/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.es.xlf b/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.es.xlf index cd81bc54d050..6ed23a5e39fe 100644 --- a/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.es.xlf +++ b/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.es.xlf @@ -27,6 +27,11 @@ Agrega uno o varios proyectos a un archivo de solución. + + Only .sln files can be migrated to .slnx format. + Only .sln files can be migrated to .slnx format. + + Place project in root of the solution, rather than creating a solution folder. Coloque el proyecto en la raíz de la solución, en lugar de crear una carpeta de soluciones. @@ -37,6 +42,11 @@ Muestra las rutas de acceso de la carpeta de la solución. + + Generate a .slnx file from a .sln file. + Generate a .slnx file from a .sln file. + + Remove one or more projects from a solution file. Quita uno o varios proyectos de un archivo de solución. @@ -57,6 +67,16 @@ Enumere todos los proyectos de la solución. + + Could not read solution file {0}. Supported files are .sln and .slnx valid solutions. + Could not read solution file {0}. Supported files are .sln and .slnx valid solutions. + + + + .slnx file {0} generated. + .slnx file {0} generated. + + SLN_FILE SLN_FILE diff --git a/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.fr.xlf b/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.fr.xlf index 37e3ed9e5521..b1d8c5880aff 100644 --- a/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.fr.xlf +++ b/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.fr.xlf @@ -27,6 +27,11 @@ Ajoutez un ou plusieurs projets à un fichier solution. + + Only .sln files can be migrated to .slnx format. + Only .sln files can be migrated to .slnx format. + + Place project in root of the solution, rather than creating a solution folder. Place le projet à la racine de la solution, au lieu de créer un dossier solution. @@ -37,6 +42,11 @@ Afficher les chemins d'accès aux dossiers de solutions. + + Generate a .slnx file from a .sln file. + Generate a .slnx file from a .sln file. + + Remove one or more projects from a solution file. Supprimez un ou plusieurs projets d'un fichier solution. @@ -57,6 +67,16 @@ Répertoriez tous les projets de la solution. + + Could not read solution file {0}. Supported files are .sln and .slnx valid solutions. + Could not read solution file {0}. Supported files are .sln and .slnx valid solutions. + + + + .slnx file {0} generated. + .slnx file {0} generated. + + SLN_FILE SLN_FILE diff --git a/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.it.xlf b/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.it.xlf index 97fadd88b17a..989a4f33844e 100644 --- a/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.it.xlf +++ b/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.it.xlf @@ -27,6 +27,11 @@ Consente di aggiungere uno o più progetti a un file di soluzione. + + Only .sln files can be migrated to .slnx format. + Only .sln files can be migrated to .slnx format. + + Place project in root of the solution, rather than creating a solution folder. Inserisce il progetto nella radice della soluzione invece di creare una cartella soluzione. @@ -37,6 +42,11 @@ Visualizza i percorsi della cartella della soluzione. + + Generate a .slnx file from a .sln file. + Generate a .slnx file from a .sln file. + + Remove one or more projects from a solution file. Consente di rimuovere uno o più progetti da un file di soluzione. @@ -57,6 +67,16 @@ Elenca tutti i progetti presenti nella soluzione. + + Could not read solution file {0}. Supported files are .sln and .slnx valid solutions. + Could not read solution file {0}. Supported files are .sln and .slnx valid solutions. + + + + .slnx file {0} generated. + .slnx file {0} generated. + + SLN_FILE SLN_FILE diff --git a/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.ja.xlf b/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.ja.xlf index ae3d8e470124..2683028f11aa 100644 --- a/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.ja.xlf +++ b/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.ja.xlf @@ -27,6 +27,11 @@ 1 つ以上のプロジェクトをソリューション ファイルに追加します。 + + Only .sln files can be migrated to .slnx format. + Only .sln files can be migrated to .slnx format. + + Place project in root of the solution, rather than creating a solution folder. ソリューション フォルダーを作成するのではなく、プロジェクトをソリューションのルートに配置します。 @@ -37,6 +42,11 @@ ソリューション フォルダーのパスを表示します。 + + Generate a .slnx file from a .sln file. + Generate a .slnx file from a .sln file. + + Remove one or more projects from a solution file. 1 つ以上のプロジェクトをソリューション ファイルから削除します。 @@ -57,6 +67,16 @@ ソリューション内のすべてのプロジェクトを一覧表示します。 + + Could not read solution file {0}. Supported files are .sln and .slnx valid solutions. + Could not read solution file {0}. Supported files are .sln and .slnx valid solutions. + + + + .slnx file {0} generated. + .slnx file {0} generated. + + SLN_FILE SLN_FILE diff --git a/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.ko.xlf b/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.ko.xlf index 16f973145cc3..895400338f29 100644 --- a/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.ko.xlf +++ b/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.ko.xlf @@ -27,6 +27,11 @@ 솔루션 파일에 하나 이상의 프로젝트를 추가합니다. + + Only .sln files can be migrated to .slnx format. + Only .sln files can be migrated to .slnx format. + + Place project in root of the solution, rather than creating a solution folder. 솔루션 폴더를 만드는 대신, 솔루션의 루트에 프로젝트를 배치하세요. @@ -37,6 +42,11 @@ 솔루션 폴더 경로를 표시합니다. + + Generate a .slnx file from a .sln file. + Generate a .slnx file from a .sln file. + + Remove one or more projects from a solution file. 솔루션 파일에서 하나 이상의 프로젝트를 제거합니다. @@ -57,6 +67,16 @@ 솔루션의 프로젝트를 모두 나열합니다. + + Could not read solution file {0}. Supported files are .sln and .slnx valid solutions. + Could not read solution file {0}. Supported files are .sln and .slnx valid solutions. + + + + .slnx file {0} generated. + .slnx file {0} generated. + + SLN_FILE SLN_FILE diff --git a/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.pl.xlf b/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.pl.xlf index d1f6cc6cd47e..e384d5d00475 100644 --- a/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.pl.xlf +++ b/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.pl.xlf @@ -27,6 +27,11 @@ Dodaj co najmniej jeden projekt do pliku rozwiązania. + + Only .sln files can be migrated to .slnx format. + Only .sln files can be migrated to .slnx format. + + Place project in root of the solution, rather than creating a solution folder. Umieść projekt w katalogu głównym rozwiązania zamiast tworzyć folder rozwiązania. @@ -37,6 +42,11 @@ Wyświetl ścieżki folderów rozwiązania. + + Generate a .slnx file from a .sln file. + Generate a .slnx file from a .sln file. + + Remove one or more projects from a solution file. Usuń co najmniej jeden projekt z pliku rozwiązania. @@ -57,6 +67,16 @@ Wyświetl listę wszystkich projektów w rozwiązaniu. + + Could not read solution file {0}. Supported files are .sln and .slnx valid solutions. + Could not read solution file {0}. Supported files are .sln and .slnx valid solutions. + + + + .slnx file {0} generated. + .slnx file {0} generated. + + SLN_FILE SLN_FILE diff --git a/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.pt-BR.xlf b/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.pt-BR.xlf index 6d6946abf851..ba4d879b8340 100644 --- a/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.pt-BR.xlf +++ b/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.pt-BR.xlf @@ -27,6 +27,11 @@ Adicionar um ou mais projetos em um arquivo de solução. + + Only .sln files can be migrated to .slnx format. + Only .sln files can be migrated to .slnx format. + + Place project in root of the solution, rather than creating a solution folder. Coloque o projeto na raiz da solução, em vez de criar uma pasta da solução. @@ -37,6 +42,11 @@ Exibir caminhos de pasta da solução. + + Generate a .slnx file from a .sln file. + Generate a .slnx file from a .sln file. + + Remove one or more projects from a solution file. Remover um ou mais projetos de um arquivo de solução. @@ -57,6 +67,16 @@ Listar todos os projetos na solução. + + Could not read solution file {0}. Supported files are .sln and .slnx valid solutions. + Could not read solution file {0}. Supported files are .sln and .slnx valid solutions. + + + + .slnx file {0} generated. + .slnx file {0} generated. + + SLN_FILE SLN_FILE diff --git a/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.ru.xlf b/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.ru.xlf index 3570cc6746d3..c5dfbd52a60c 100644 --- a/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.ru.xlf +++ b/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.ru.xlf @@ -27,6 +27,11 @@ Добавление проектов в файл решения. + + Only .sln files can be migrated to .slnx format. + Only .sln files can be migrated to .slnx format. + + Place project in root of the solution, rather than creating a solution folder. Поместите проект в корень решения вместо создания папки решения. @@ -37,6 +42,11 @@ Отображение путей к папке решения. + + Generate a .slnx file from a .sln file. + Generate a .slnx file from a .sln file. + + Remove one or more projects from a solution file. Удаление проектов из файла решения. @@ -57,6 +67,16 @@ Перечисляет все проекты в решении. + + Could not read solution file {0}. Supported files are .sln and .slnx valid solutions. + Could not read solution file {0}. Supported files are .sln and .slnx valid solutions. + + + + .slnx file {0} generated. + .slnx file {0} generated. + + SLN_FILE SLN_FILE diff --git a/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.tr.xlf b/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.tr.xlf index 7e6c73bfc1cd..fea7bcc4ea34 100644 --- a/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.tr.xlf +++ b/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.tr.xlf @@ -27,6 +27,11 @@ Bir çözüm dosyasına bir veya daha fazla proje ekler. + + Only .sln files can be migrated to .slnx format. + Only .sln files can be migrated to .slnx format. + + Place project in root of the solution, rather than creating a solution folder. Bir çözüm klasörü oluşturmak yerine projeyi çözümün köküne yerleştirin. @@ -37,6 +42,11 @@ Çözüm klasörü yollarını görüntüleyin. + + Generate a .slnx file from a .sln file. + Generate a .slnx file from a .sln file. + + Remove one or more projects from a solution file. Bir çözüm dosyasından bir veya daha fazla projeyi kaldırır. @@ -57,6 +67,16 @@ Çözümdeki tüm projeleri listeleyin. + + Could not read solution file {0}. Supported files are .sln and .slnx valid solutions. + Could not read solution file {0}. Supported files are .sln and .slnx valid solutions. + + + + .slnx file {0} generated. + .slnx file {0} generated. + + SLN_FILE SLN_FILE diff --git a/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.zh-Hans.xlf b/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.zh-Hans.xlf index c25b28105ea3..82241d2d4a6a 100644 --- a/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.zh-Hans.xlf +++ b/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.zh-Hans.xlf @@ -27,6 +27,11 @@ 将一个或多个项目添加到解决方案文件。 + + Only .sln files can be migrated to .slnx format. + Only .sln files can be migrated to .slnx format. + + Place project in root of the solution, rather than creating a solution folder. 将项目放在解决方案的根目录下,而不是创建解决方案文件夹。 @@ -37,6 +42,11 @@ 显示解决方案文件夹路径。 + + Generate a .slnx file from a .sln file. + Generate a .slnx file from a .sln file. + + Remove one or more projects from a solution file. 从解决方案文件中删除一个或多个项目。 @@ -57,6 +67,16 @@ 列出解决方案中的所有项目。 + + Could not read solution file {0}. Supported files are .sln and .slnx valid solutions. + Could not read solution file {0}. Supported files are .sln and .slnx valid solutions. + + + + .slnx file {0} generated. + .slnx file {0} generated. + + SLN_FILE SLN_FILE diff --git a/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.zh-Hant.xlf b/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.zh-Hant.xlf index 39b4ef7588ac..5b061ec4f5f2 100644 --- a/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.zh-Hant.xlf +++ b/src/Cli/dotnet/commands/dotnet-sln/xlf/LocalizableStrings.zh-Hant.xlf @@ -27,6 +27,11 @@ 為解決方案檔新增一或多個專案。 + + Only .sln files can be migrated to .slnx format. + Only .sln files can be migrated to .slnx format. + + Place project in root of the solution, rather than creating a solution folder. 請將專案放置在解決方案的根目錄中,而非放置於建立解決方案的資料夾中。 @@ -37,6 +42,11 @@ 顯示解決方案資料夾路徑。 + + Generate a .slnx file from a .sln file. + Generate a .slnx file from a .sln file. + + Remove one or more projects from a solution file. 從解決方案檔移除一或多個專案。 @@ -57,6 +67,16 @@ 列出解決方案中的所有專案。 + + Could not read solution file {0}. Supported files are .sln and .slnx valid solutions. + Could not read solution file {0}. Supported files are .sln and .slnx valid solutions. + + + + .slnx file {0} generated. + .slnx file {0} generated. + + SLN_FILE SLN_FILE diff --git a/src/Cli/dotnet/dotnet.csproj b/src/Cli/dotnet/dotnet.csproj index 58cefd4e6ba6..7b258f8f8a0e 100644 --- a/src/Cli/dotnet/dotnet.csproj +++ b/src/Cli/dotnet/dotnet.csproj @@ -15,6 +15,8 @@ true true annotations + + $(NoWarn);CS8002 @@ -97,6 +99,8 @@ + + diff --git a/test/Microsoft.NET.TestFramework/TestAssetsManager.cs b/test/Microsoft.NET.TestFramework/TestAssetsManager.cs index 17a4fa411dab..a0b44dd6a35b 100644 --- a/test/Microsoft.NET.TestFramework/TestAssetsManager.cs +++ b/test/Microsoft.NET.TestFramework/TestAssetsManager.cs @@ -203,12 +203,16 @@ public static string GetTestDestinationDirectoryPath( #if CI_BUILD if (!allowCopyIfPresent && Directory.Exists(directoryPath)) { - //Arcade test retry reuses the machine so the directory might already be present in CI - directoryPath = Directory.Exists(directoryPath+"_1") ? directoryPath+"_2" : directoryPath+"_1"; - if (Directory.Exists(directoryPath)) + // Arcade test retry reuses the machine so the directory might already be present in CI + int suffix = 1; + string newDirectoryPath; + do { - throw new Exception($"Test dir {directoryPath} already exists"); - } + newDirectoryPath = $"{directoryPath}_{suffix}"; + suffix++; + } while (Directory.Exists(newDirectoryPath)); + + directoryPath = newDirectoryPath; } #endif diff --git a/test/TestAssets/TestProjects/InvalidSolution/InvalidSolution.slnx b/test/TestAssets/TestProjects/InvalidSolution/InvalidSolution.slnx new file mode 100644 index 000000000000..f19e25b82be9 --- /dev/null +++ b/test/TestAssets/TestProjects/InvalidSolution/InvalidSolution.slnx @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/test/TestAssets/TestProjects/InvalidSolution/Sln/InvalidSolution.sln b/test/TestAssets/TestProjects/InvalidSolution/Sln/InvalidSolution.sln new file mode 100644 index 000000000000..6527f5d32ab6 --- /dev/null +++ b/test/TestAssets/TestProjects/InvalidSolution/Sln/InvalidSolution.sln @@ -0,0 +1 @@ +This is a test of an invalid solution. diff --git a/test/TestAssets/TestProjects/InvalidSolution/Slnx/InvalidSolution.slnx b/test/TestAssets/TestProjects/InvalidSolution/Slnx/InvalidSolution.slnx new file mode 100644 index 000000000000..f19e25b82be9 --- /dev/null +++ b/test/TestAssets/TestProjects/InvalidSolution/Slnx/InvalidSolution.slnx @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/test/TestAssets/TestProjects/SlnFileWithNoProjectReferencesAndUnknownProjectType/App.slnx b/test/TestAssets/TestProjects/SlnFileWithNoProjectReferencesAndUnknownProjectType/App.slnx new file mode 100644 index 000000000000..70f4bc532c1a --- /dev/null +++ b/test/TestAssets/TestProjects/SlnFileWithNoProjectReferencesAndUnknownProjectType/App.slnx @@ -0,0 +1,7 @@ + + + + + + + diff --git a/test/TestAssets/TestProjects/SolutionFilesTemplates/ExpectedSlnFileAfterAddingLibProj.sln b/test/TestAssets/TestProjects/SolutionFilesTemplates/ExpectedSlnFileAfterAddingLibProj.sln new file mode 100644 index 000000000000..583ce967acdc --- /dev/null +++ b/test/TestAssets/TestProjects/SolutionFilesTemplates/ExpectedSlnFileAfterAddingLibProj.sln @@ -0,0 +1,47 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26006.2 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "App", "App\App.csproj", "{7072A694-548F-4CAE-A58F-12D257D5F486}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lib", "Lib\Lib.csproj", "__LIB_PROJECT_GUID__" +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 + {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x64.ActiveCfg = Debug|x64 + {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x64.Build.0 = Debug|x64 + {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x86.ActiveCfg = Debug|x86 + {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x86.Build.0 = Debug|x86 + {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|Any CPU.Build.0 = Release|Any CPU + {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x64.ActiveCfg = Release|x64 + {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x64.Build.0 = Release|x64 + {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x86.ActiveCfg = Release|x86 + {7072A694-548F-4CAE-A58F-12D257D5F486}.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|Any CPU + __LIB_PROJECT_GUID__.Debug|x64.Build.0 = Debug|Any CPU + __LIB_PROJECT_GUID__.Debug|x86.ActiveCfg = Debug|Any CPU + __LIB_PROJECT_GUID__.Debug|x86.Build.0 = Debug|Any CPU + __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|Any CPU + __LIB_PROJECT_GUID__.Release|x64.Build.0 = Release|Any CPU + __LIB_PROJECT_GUID__.Release|x86.ActiveCfg = Release|Any CPU + __LIB_PROJECT_GUID__.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal \ No newline at end of file diff --git a/test/TestAssets/TestProjects/SolutionFilesTemplates/ExpectedSlnFileAfterAddingLibProj.slnx b/test/TestAssets/TestProjects/SolutionFilesTemplates/ExpectedSlnFileAfterAddingLibProj.slnx new file mode 100644 index 000000000000..b8e10870f971 --- /dev/null +++ b/test/TestAssets/TestProjects/SolutionFilesTemplates/ExpectedSlnFileAfterAddingLibProj.slnx @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/test/TestAssets/TestProjects/SolutionFilesTemplates/ExpectedSlnFileAfterAddingLibProjToEmptySln.sln b/test/TestAssets/TestProjects/SolutionFilesTemplates/ExpectedSlnFileAfterAddingLibProjToEmptySln.sln new file mode 100644 index 000000000000..bb11b322c35d --- /dev/null +++ b/test/TestAssets/TestProjects/SolutionFilesTemplates/ExpectedSlnFileAfterAddingLibProjToEmptySln.sln @@ -0,0 +1,33 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26006.2 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lib", "Lib\Lib.csproj", "__LIB_PROJECT_GUID__" +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 + __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|Any CPU + __LIB_PROJECT_GUID__.Debug|x64.Build.0 = Debug|Any CPU + __LIB_PROJECT_GUID__.Debug|x86.ActiveCfg = Debug|Any CPU + __LIB_PROJECT_GUID__.Debug|x86.Build.0 = Debug|Any CPU + __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|Any CPU + __LIB_PROJECT_GUID__.Release|x64.Build.0 = Release|Any CPU + __LIB_PROJECT_GUID__.Release|x86.ActiveCfg = Release|Any CPU + __LIB_PROJECT_GUID__.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal \ No newline at end of file diff --git a/test/TestAssets/TestProjects/SolutionFilesTemplates/ExpectedSlnFileAfterAddingLibProjToEmptySln.slnx b/test/TestAssets/TestProjects/SolutionFilesTemplates/ExpectedSlnFileAfterAddingLibProjToEmptySln.slnx new file mode 100644 index 000000000000..e3caa7e0055a --- /dev/null +++ b/test/TestAssets/TestProjects/SolutionFilesTemplates/ExpectedSlnFileAfterAddingLibProjToEmptySln.slnx @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/TestAssets/TestProjects/SolutionFilesTemplates/ExpectedSlnFileAfterAddingNestedProj.sln b/test/TestAssets/TestProjects/SolutionFilesTemplates/ExpectedSlnFileAfterAddingNestedProj.sln new file mode 100644 index 000000000000..2f0f2f88baed --- /dev/null +++ b/test/TestAssets/TestProjects/SolutionFilesTemplates/ExpectedSlnFileAfterAddingNestedProj.sln @@ -0,0 +1,52 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26006.2 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "App", "App.csproj", "{7072A694-548F-4CAE-A58F-12D257D5F486}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "__SRC_FOLDER_GUID__" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lib", "src\Lib\Lib.csproj", "__LIB_PROJECT_GUID__" +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 + {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x64.ActiveCfg = Debug|x64 + {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x64.Build.0 = Debug|x64 + {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x86.ActiveCfg = Debug|x86 + {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x86.Build.0 = Debug|x86 + {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|Any CPU.Build.0 = Release|Any CPU + {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x64.ActiveCfg = Release|x64 + {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x64.Build.0 = Release|x64 + {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x86.ActiveCfg = Release|x86 + {7072A694-548F-4CAE-A58F-12D257D5F486}.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|Any CPU + __LIB_PROJECT_GUID__.Debug|x64.Build.0 = Debug|Any CPU + __LIB_PROJECT_GUID__.Debug|x86.ActiveCfg = Debug|Any CPU + __LIB_PROJECT_GUID__.Debug|x86.Build.0 = Debug|Any CPU + __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|Any CPU + __LIB_PROJECT_GUID__.Release|x64.Build.0 = Release|Any CPU + __LIB_PROJECT_GUID__.Release|x86.ActiveCfg = Release|Any CPU + __LIB_PROJECT_GUID__.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + __LIB_PROJECT_GUID__ = __SRC_FOLDER_GUID__ + EndGlobalSection +EndGlobal \ No newline at end of file diff --git a/test/TestAssets/TestProjects/SolutionFilesTemplates/ExpectedSlnFileAfterAddingNestedProj.slnx b/test/TestAssets/TestProjects/SolutionFilesTemplates/ExpectedSlnFileAfterAddingNestedProj.slnx new file mode 100644 index 000000000000..d79132291fc5 --- /dev/null +++ b/test/TestAssets/TestProjects/SolutionFilesTemplates/ExpectedSlnFileAfterAddingNestedProj.slnx @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/test/TestAssets/TestProjects/SolutionFilesTemplates/ExpectedSlnFileAfterAddingProjectWithInRootOption.sln b/test/TestAssets/TestProjects/SolutionFilesTemplates/ExpectedSlnFileAfterAddingProjectWithInRootOption.sln new file mode 100644 index 000000000000..ea60a2243d15 --- /dev/null +++ b/test/TestAssets/TestProjects/SolutionFilesTemplates/ExpectedSlnFileAfterAddingProjectWithInRootOption.sln @@ -0,0 +1,47 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26006.2 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "App", "App.csproj", "{7072A694-548F-4CAE-A58F-12D257D5F486}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lib", "src\Lib\Lib.csproj", "__LIB_PROJECT_GUID__" +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 + {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x64.ActiveCfg = Debug|x64 + {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x64.Build.0 = Debug|x64 + {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x86.ActiveCfg = Debug|x86 + {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x86.Build.0 = Debug|x86 + {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|Any CPU.Build.0 = Release|Any CPU + {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x64.ActiveCfg = Release|x64 + {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x64.Build.0 = Release|x64 + {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x86.ActiveCfg = Release|x86 + {7072A694-548F-4CAE-A58F-12D257D5F486}.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|Any CPU + "__LIB_PROJECT_GUID__".Debug|x64.Build.0 = Debug|Any CPU + "__LIB_PROJECT_GUID__".Debug|x86.ActiveCfg = Debug|Any CPU + "__LIB_PROJECT_GUID__".Debug|x86.Build.0 = Debug|Any CPU + "__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|Any CPU + "__LIB_PROJECT_GUID__".Release|x64.Build.0 = Release|Any CPU + "__LIB_PROJECT_GUID__".Release|x86.ActiveCfg = Release|Any CPU + "__LIB_PROJECT_GUID__".Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal \ No newline at end of file diff --git a/test/TestAssets/TestProjects/SolutionFilesTemplates/ExpectedSlnFileAfterAddingProjectWithInRootOption.slnx b/test/TestAssets/TestProjects/SolutionFilesTemplates/ExpectedSlnFileAfterAddingProjectWithInRootOption.slnx new file mode 100644 index 000000000000..4b18efe59dab --- /dev/null +++ b/test/TestAssets/TestProjects/SolutionFilesTemplates/ExpectedSlnFileAfterAddingProjectWithInRootOption.slnx @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/test/TestAssets/TestProjects/SolutionFilesTemplates/ExpectedSlnFileAfterAddingProjectWithSolutionFolderOption.sln b/test/TestAssets/TestProjects/SolutionFilesTemplates/ExpectedSlnFileAfterAddingProjectWithSolutionFolderOption.sln new file mode 100644 index 000000000000..64c7db347050 --- /dev/null +++ b/test/TestAssets/TestProjects/SolutionFilesTemplates/ExpectedSlnFileAfterAddingProjectWithSolutionFolderOption.sln @@ -0,0 +1,52 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26006.2 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "App", "App.csproj", "{7072A694-548F-4CAE-A58F-12D257D5F486}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TestFolder", "TestFolder", "__SOLUTION_FOLDER_GUID__" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lib", "src\Lib\Lib.csproj", "__LIB_PROJECT_GUID__" +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 + {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x64.ActiveCfg = Debug|x64 + {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x64.Build.0 = Debug|x64 + {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x86.ActiveCfg = Debug|x86 + {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x86.Build.0 = Debug|x86 + {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|Any CPU.Build.0 = Release|Any CPU + {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x64.ActiveCfg = Release|x64 + {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x64.Build.0 = Release|x64 + {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x86.ActiveCfg = Release|x86 + {7072A694-548F-4CAE-A58F-12D257D5F486}.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|Any CPU + __LIB_PROJECT_GUID__.Debug|x64.Build.0 = Debug|Any CPU + __LIB_PROJECT_GUID__.Debug|x86.ActiveCfg = Debug|Any CPU + __LIB_PROJECT_GUID__.Debug|x86.Build.0 = Debug|Any CPU + __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|Any CPU + __LIB_PROJECT_GUID__.Release|x64.Build.0 = Release|Any CPU + __LIB_PROJECT_GUID__.Release|x86.ActiveCfg = Release|Any CPU + __LIB_PROJECT_GUID__.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + __LIB_PROJECT_GUID__ = __SOLUTION_FOLDER_GUID__ + EndGlobalSection +EndGlobal \ No newline at end of file diff --git a/test/TestAssets/TestProjects/SolutionFilesTemplates/ExpectedSlnFileAfterAddingProjectWithSolutionFolderOption.slnx b/test/TestAssets/TestProjects/SolutionFilesTemplates/ExpectedSlnFileAfterAddingProjectWithSolutionFolderOption.slnx new file mode 100644 index 000000000000..72b17f549402 --- /dev/null +++ b/test/TestAssets/TestProjects/SolutionFilesTemplates/ExpectedSlnFileAfterAddingProjectWithSolutionFolderOption.slnx @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/test/TestAssets/TestProjects/TestAppWithEmptySln/App.slnx b/test/TestAssets/TestProjects/TestAppWithEmptySln/App.slnx new file mode 100644 index 000000000000..4e2253ddceed --- /dev/null +++ b/test/TestAssets/TestProjects/TestAppWithEmptySln/App.slnx @@ -0,0 +1 @@ + diff --git a/test/TestAssets/TestProjects/TestAppWithMultipleSlnFiles/App.slnx b/test/TestAssets/TestProjects/TestAppWithMultipleSlnFiles/App.slnx new file mode 100644 index 000000000000..9d9f6a7f5faa --- /dev/null +++ b/test/TestAssets/TestProjects/TestAppWithMultipleSlnFiles/App.slnx @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/test/TestAssets/TestProjects/TestAppWithMultipleSlnFiles/App2.slnx b/test/TestAssets/TestProjects/TestAppWithMultipleSlnFiles/App2.slnx new file mode 100644 index 000000000000..9d9f6a7f5faa --- /dev/null +++ b/test/TestAssets/TestProjects/TestAppWithMultipleSlnFiles/App2.slnx @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/test/TestAssets/TestProjects/TestAppWithSlnAnd472CsprojFiles/App.slnx b/test/TestAssets/TestProjects/TestAppWithSlnAnd472CsprojFiles/App.slnx new file mode 100644 index 000000000000..9d9f6a7f5faa --- /dev/null +++ b/test/TestAssets/TestProjects/TestAppWithSlnAnd472CsprojFiles/App.slnx @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/test/TestAssets/TestProjects/TestAppWithSlnAndCaseSensitiveSolutionFolders/App.slnx b/test/TestAssets/TestProjects/TestAppWithSlnAndCaseSensitiveSolutionFolders/App.slnx new file mode 100644 index 000000000000..3704c0910c8f --- /dev/null +++ b/test/TestAssets/TestProjects/TestAppWithSlnAndCaseSensitiveSolutionFolders/App.slnx @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/test/TestAssets/TestProjects/TestAppWithSlnAndCsprojFiles/App.slnx b/test/TestAssets/TestProjects/TestAppWithSlnAndCsprojFiles/App.slnx new file mode 100644 index 000000000000..9d9f6a7f5faa --- /dev/null +++ b/test/TestAssets/TestProjects/TestAppWithSlnAndCsprojFiles/App.slnx @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/test/TestAssets/TestProjects/TestAppWithSlnAndCsprojInSubDir/App.slnx b/test/TestAssets/TestProjects/TestAppWithSlnAndCsprojInSubDir/App.slnx new file mode 100644 index 000000000000..1d64de45b461 --- /dev/null +++ b/test/TestAssets/TestProjects/TestAppWithSlnAndCsprojInSubDir/App.slnx @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/test/TestAssets/TestProjects/TestAppWithSlnAndCsprojInSubDirVS/App.slnx b/test/TestAssets/TestProjects/TestAppWithSlnAndCsprojInSubDirVS/App.slnx new file mode 100644 index 000000000000..70f4bc532c1a --- /dev/null +++ b/test/TestAssets/TestProjects/TestAppWithSlnAndCsprojInSubDirVS/App.slnx @@ -0,0 +1,7 @@ + + + + + + + diff --git a/test/TestAssets/TestProjects/TestAppWithSlnAndCsprojProjectGuidFiles/App.slnx b/test/TestAssets/TestProjects/TestAppWithSlnAndCsprojProjectGuidFiles/App.slnx new file mode 100644 index 000000000000..9d9f6a7f5faa --- /dev/null +++ b/test/TestAssets/TestProjects/TestAppWithSlnAndCsprojProjectGuidFiles/App.slnx @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/test/TestAssets/TestProjects/TestAppWithSlnAndExistingCsprojReferences/App.slnx b/test/TestAssets/TestProjects/TestAppWithSlnAndExistingCsprojReferences/App.slnx new file mode 100644 index 000000000000..d44674932ffd --- /dev/null +++ b/test/TestAssets/TestProjects/TestAppWithSlnAndExistingCsprojReferences/App.slnx @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/test/TestAssets/TestProjects/TestAppWithSlnAndExistingCsprojReferencesWithEscapedDirSep/App.slnx b/test/TestAssets/TestProjects/TestAppWithSlnAndExistingCsprojReferencesWithEscapedDirSep/App.slnx new file mode 100644 index 000000000000..effb93109e33 --- /dev/null +++ b/test/TestAssets/TestProjects/TestAppWithSlnAndExistingCsprojReferencesWithEscapedDirSep/App.slnx @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/test/TestAssets/TestProjects/TestAppWithSlnAndProjectConfigs/App.slnx b/test/TestAssets/TestProjects/TestAppWithSlnAndProjectConfigs/App.slnx new file mode 100644 index 000000000000..17bc938af284 --- /dev/null +++ b/test/TestAssets/TestProjects/TestAppWithSlnAndProjectConfigs/App.slnx @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/test/TestAssets/TestProjects/TestAppWithSlnAndProjectConfigs/Results/ExpectedSlnFileAfterAddingProjectWithAdditionalConfigs.sln b/test/TestAssets/TestProjects/TestAppWithSlnAndProjectConfigs/Results/ExpectedSlnFileAfterAddingProjectWithAdditionalConfigs.sln new file mode 100644 index 000000000000..e4fe8f9a3765 --- /dev/null +++ b/test/TestAssets/TestProjects/TestAppWithSlnAndProjectConfigs/Results/ExpectedSlnFileAfterAddingProjectWithAdditionalConfigs.sln @@ -0,0 +1,42 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26006.2 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProjectWithAdditionalConfigs", "ProjectWithAdditionalConfigs\ProjectWithAdditionalConfigs.csproj", "{A302325B-D680-4C0E-8680-7AE283981624}" +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 + Foo Bar|Any CPU = Foo Bar|Any CPU + Foo Bar|x64 = Foo Bar|x64 + Foo Bar|x86 = Foo Bar|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A302325B-D680-4C0E-8680-7AE283981624}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A302325B-D680-4C0E-8680-7AE283981624}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A302325B-D680-4C0E-8680-7AE283981624}.Debug|x64.ActiveCfg = Debug|x64 + {A302325B-D680-4C0E-8680-7AE283981624}.Debug|x64.Build.0 = Debug|x64 + {A302325B-D680-4C0E-8680-7AE283981624}.Debug|x86.ActiveCfg = Debug|x86 + {A302325B-D680-4C0E-8680-7AE283981624}.Debug|x86.Build.0 = Debug|x86 + {A302325B-D680-4C0E-8680-7AE283981624}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A302325B-D680-4C0E-8680-7AE283981624}.Release|Any CPU.Build.0 = Release|Any CPU + {A302325B-D680-4C0E-8680-7AE283981624}.Release|x64.ActiveCfg = Release|x64 + {A302325B-D680-4C0E-8680-7AE283981624}.Release|x64.Build.0 = Release|x64 + {A302325B-D680-4C0E-8680-7AE283981624}.Release|x86.ActiveCfg = Release|x86 + {A302325B-D680-4C0E-8680-7AE283981624}.Release|x86.Build.0 = Release|x86 + {A302325B-D680-4C0E-8680-7AE283981624}.Foo Bar|Any CPU.ActiveCfg = FooBar|Any CPU + {A302325B-D680-4C0E-8680-7AE283981624}.Foo Bar|Any CPU.Build.0 = FooBar|Any CPU + {A302325B-D680-4C0E-8680-7AE283981624}.Foo Bar|x64.ActiveCfg = FooBar|x64 + {A302325B-D680-4C0E-8680-7AE283981624}.Foo Bar|x64.Build.0 = FooBar|x64 + {A302325B-D680-4C0E-8680-7AE283981624}.Foo Bar|x86.ActiveCfg = FooBar|x86 + {A302325B-D680-4C0E-8680-7AE283981624}.Foo Bar|x86.Build.0 = FooBar|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal \ No newline at end of file diff --git a/test/TestAssets/TestProjects/TestAppWithSlnAndProjectConfigs/Results/ExpectedSlnFileAfterAddingProjectWithAdditionalConfigs.slnx b/test/TestAssets/TestProjects/TestAppWithSlnAndProjectConfigs/Results/ExpectedSlnFileAfterAddingProjectWithAdditionalConfigs.slnx new file mode 100644 index 000000000000..339ed04dc998 --- /dev/null +++ b/test/TestAssets/TestProjects/TestAppWithSlnAndProjectConfigs/Results/ExpectedSlnFileAfterAddingProjectWithAdditionalConfigs.slnx @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/test/TestAssets/TestProjects/TestAppWithSlnAndProjectConfigs/Results/ExpectedSlnFileAfterAddingProjectWithMatchingConfigs.sln b/test/TestAssets/TestProjects/TestAppWithSlnAndProjectConfigs/Results/ExpectedSlnFileAfterAddingProjectWithMatchingConfigs.sln new file mode 100644 index 000000000000..4b5fbb90532f --- /dev/null +++ b/test/TestAssets/TestProjects/TestAppWithSlnAndProjectConfigs/Results/ExpectedSlnFileAfterAddingProjectWithMatchingConfigs.sln @@ -0,0 +1,42 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26006.2 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProjectWithMatchingConfigs", "ProjectWithMatchingConfigs\ProjectWithMatchingConfigs.csproj", "{C9601CA2-DB64-4FB6-B463-368C7764BF0D}" +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 + Foo Bar|Any CPU = Foo Bar|Any CPU + Foo Bar|x64 = Foo Bar|x64 + Foo Bar|x86 = Foo Bar|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C9601CA2-DB64-4FB6-B463-368C7764BF0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C9601CA2-DB64-4FB6-B463-368C7764BF0D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C9601CA2-DB64-4FB6-B463-368C7764BF0D}.Debug|x64.ActiveCfg = Debug|x64 + {C9601CA2-DB64-4FB6-B463-368C7764BF0D}.Debug|x64.Build.0 = Debug|x64 + {C9601CA2-DB64-4FB6-B463-368C7764BF0D}.Debug|x86.ActiveCfg = Debug|x86 + {C9601CA2-DB64-4FB6-B463-368C7764BF0D}.Debug|x86.Build.0 = Debug|x86 + {C9601CA2-DB64-4FB6-B463-368C7764BF0D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C9601CA2-DB64-4FB6-B463-368C7764BF0D}.Release|Any CPU.Build.0 = Release|Any CPU + {C9601CA2-DB64-4FB6-B463-368C7764BF0D}.Release|x64.ActiveCfg = Release|x64 + {C9601CA2-DB64-4FB6-B463-368C7764BF0D}.Release|x64.Build.0 = Release|x64 + {C9601CA2-DB64-4FB6-B463-368C7764BF0D}.Release|x86.ActiveCfg = Release|x86 + {C9601CA2-DB64-4FB6-B463-368C7764BF0D}.Release|x86.Build.0 = Release|x86 + {C9601CA2-DB64-4FB6-B463-368C7764BF0D}.Foo Bar|Any CPU.ActiveCfg = FooBar|Any CPU + {C9601CA2-DB64-4FB6-B463-368C7764BF0D}.Foo Bar|Any CPU.Build.0 = FooBar|Any CPU + {C9601CA2-DB64-4FB6-B463-368C7764BF0D}.Foo Bar|x64.ActiveCfg = FooBar|x64 + {C9601CA2-DB64-4FB6-B463-368C7764BF0D}.Foo Bar|x64.Build.0 = FooBar|x64 + {C9601CA2-DB64-4FB6-B463-368C7764BF0D}.Foo Bar|x86.ActiveCfg = FooBar|x86 + {C9601CA2-DB64-4FB6-B463-368C7764BF0D}.Foo Bar|x86.Build.0 = FooBar|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal \ No newline at end of file diff --git a/test/TestAssets/TestProjects/TestAppWithSlnAndProjectConfigs/Results/ExpectedSlnFileAfterAddingProjectWithMatchingConfigs.slnx b/test/TestAssets/TestProjects/TestAppWithSlnAndProjectConfigs/Results/ExpectedSlnFileAfterAddingProjectWithMatchingConfigs.slnx new file mode 100644 index 000000000000..22585769d919 --- /dev/null +++ b/test/TestAssets/TestProjects/TestAppWithSlnAndProjectConfigs/Results/ExpectedSlnFileAfterAddingProjectWithMatchingConfigs.slnx @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/test/TestAssets/TestProjects/TestAppWithSlnAndProjectConfigs/Results/ExpectedSlnFileAfterAddingProjectWithoutMatchingConfigs.sln b/test/TestAssets/TestProjects/TestAppWithSlnAndProjectConfigs/Results/ExpectedSlnFileAfterAddingProjectWithoutMatchingConfigs.sln new file mode 100644 index 000000000000..e9cc5227b137 --- /dev/null +++ b/test/TestAssets/TestProjects/TestAppWithSlnAndProjectConfigs/Results/ExpectedSlnFileAfterAddingProjectWithoutMatchingConfigs.sln @@ -0,0 +1,42 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26006.2 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProjectWithoutMatchingConfigs", "ProjectWithoutMatchingConfigs\ProjectWithoutMatchingConfigs.csproj", "{C49B64DE-4401-4825-8A88-10DCB5950E57}" +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 + Foo Bar|Any CPU = Foo Bar|Any CPU + Foo Bar|x64 = Foo Bar|x64 + Foo Bar|x86 = Foo Bar|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C49B64DE-4401-4825-8A88-10DCB5950E57}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C49B64DE-4401-4825-8A88-10DCB5950E57}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C49B64DE-4401-4825-8A88-10DCB5950E57}.Debug|x64.ActiveCfg = Debug|Any CPU + {C49B64DE-4401-4825-8A88-10DCB5950E57}.Debug|x64.Build.0 = Debug|Any CPU + {C49B64DE-4401-4825-8A88-10DCB5950E57}.Debug|x86.ActiveCfg = Debug|Any CPU + {C49B64DE-4401-4825-8A88-10DCB5950E57}.Debug|x86.Build.0 = Debug|Any CPU + {C49B64DE-4401-4825-8A88-10DCB5950E57}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C49B64DE-4401-4825-8A88-10DCB5950E57}.Release|Any CPU.Build.0 = Release|Any CPU + {C49B64DE-4401-4825-8A88-10DCB5950E57}.Release|x64.ActiveCfg = Release|Any CPU + {C49B64DE-4401-4825-8A88-10DCB5950E57}.Release|x64.Build.0 = Release|Any CPU + {C49B64DE-4401-4825-8A88-10DCB5950E57}.Release|x86.ActiveCfg = Release|Any CPU + {C49B64DE-4401-4825-8A88-10DCB5950E57}.Release|x86.Build.0 = Release|Any CPU + {C49B64DE-4401-4825-8A88-10DCB5950E57}.Foo Bar|Any CPU.ActiveCfg = Debug|Any CPU + {C49B64DE-4401-4825-8A88-10DCB5950E57}.Foo Bar|Any CPU.Build.0 = Debug|Any CPU + {C49B64DE-4401-4825-8A88-10DCB5950E57}.Foo Bar|x64.ActiveCfg = Debug|Any CPU + {C49B64DE-4401-4825-8A88-10DCB5950E57}.Foo Bar|x64.Build.0 = Debug|Any CPU + {C49B64DE-4401-4825-8A88-10DCB5950E57}.Foo Bar|x86.ActiveCfg = Debug|Any CPU + {C49B64DE-4401-4825-8A88-10DCB5950E57}.Foo Bar|x86.Build.0 = Debug|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal \ No newline at end of file diff --git a/test/TestAssets/TestProjects/TestAppWithSlnAndProjectConfigs/Results/ExpectedSlnFileAfterAddingProjectWithoutMatchingConfigs.slnx b/test/TestAssets/TestProjects/TestAppWithSlnAndProjectConfigs/Results/ExpectedSlnFileAfterAddingProjectWithoutMatchingConfigs.slnx new file mode 100644 index 000000000000..0a705d1431fb --- /dev/null +++ b/test/TestAssets/TestProjects/TestAppWithSlnAndProjectConfigs/Results/ExpectedSlnFileAfterAddingProjectWithoutMatchingConfigs.slnx @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/test/TestAssets/TestProjects/TestAppWithSlnAndSolutionFolders/App.slnx b/test/TestAssets/TestProjects/TestAppWithSlnAndSolutionFolders/App.slnx new file mode 100644 index 000000000000..4bda18e4f194 --- /dev/null +++ b/test/TestAssets/TestProjects/TestAppWithSlnAndSolutionFolders/App.slnx @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/test/TestAssets/TestProjects/TestAppsWithSlnAndMultitargetedProjects/TestAppsWithSlnAndMultitargetedProjects.slnx b/test/TestAssets/TestProjects/TestAppsWithSlnAndMultitargetedProjects/TestAppsWithSlnAndMultitargetedProjects.slnx new file mode 100644 index 000000000000..70f4bc532c1a --- /dev/null +++ b/test/TestAssets/TestProjects/TestAppsWithSlnAndMultitargetedProjects/TestAppsWithSlnAndMultitargetedProjects.slnx @@ -0,0 +1,7 @@ + + + + + + + diff --git a/test/dotnet-restore.Tests/GivenThatIWantToRestoreApp.cs b/test/dotnet-restore.Tests/GivenThatIWantToRestoreApp.cs index a2ade77e8345..ff195897c56d 100644 --- a/test/dotnet-restore.Tests/GivenThatIWantToRestoreApp.cs +++ b/test/dotnet-restore.Tests/GivenThatIWantToRestoreApp.cs @@ -27,7 +27,7 @@ public void ItRestoresAppToSpecificDirectory(bool useStaticGraphEvaluation) .WithSource() .Path; - string[] args = new[] { "--packages", fullPath }; + string[] args = new[] { "App.sln", "--packages", fullPath }; args = HandleStaticGraphEvaluation(useStaticGraphEvaluation, args); new DotnetRestoreCommand(Log) .WithWorkingDirectory(projectDirectory) diff --git a/test/dotnet-sln.Tests/GivenDotnetSlnAdd.cs b/test/dotnet-sln.Tests/GivenDotnetSlnAdd.cs index 8c13d746f746..42061903efaa 100644 --- a/test/dotnet-sln.Tests/GivenDotnetSlnAdd.cs +++ b/test/dotnet-sln.Tests/GivenDotnetSlnAdd.cs @@ -5,6 +5,10 @@ using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.Tools; using Microsoft.DotNet.Tools.Common; +using Microsoft.VisualStudio.SolutionPersistence.Serializer; +using Microsoft.VisualStudio.SolutionPersistence; +using Microsoft.VisualStudio.SolutionPersistence.Model; +using Microsoft.VisualStudio.SolutionPersistence.Serializer.SlnV12; namespace Microsoft.DotNet.Cli.Sln.Add.Tests { @@ -29,384 +33,6 @@ public GivenDotnetSlnAdd(ITestOutputHelper log) : base(log) { } - 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(""{9A19103F-16F7-4668-BE54-9A1E7A4F7556}"") = ""App"", ""App\App.csproj"", ""{7072A694-548F-4CAE-A58F-12D257D5F486}"" -EndProject -Project(""{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"") = ""Lib"", ""Lib\Lib.csproj"", ""__LIB_PROJECT_GUID__"" -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 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x64.ActiveCfg = Debug|x64 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x64.Build.0 = Debug|x64 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x86.ActiveCfg = Debug|x86 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x86.Build.0 = Debug|x86 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|Any CPU.Build.0 = Release|Any CPU - {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x64.ActiveCfg = Release|x64 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x64.Build.0 = Release|x64 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x86.ActiveCfg = Release|x86 - {7072A694-548F-4CAE-A58F-12D257D5F486}.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|Any CPU - __LIB_PROJECT_GUID__.Debug|x64.Build.0 = Debug|Any CPU - __LIB_PROJECT_GUID__.Debug|x86.ActiveCfg = Debug|Any CPU - __LIB_PROJECT_GUID__.Debug|x86.Build.0 = Debug|Any CPU - __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|Any CPU - __LIB_PROJECT_GUID__.Release|x64.Build.0 = Release|Any CPU - __LIB_PROJECT_GUID__.Release|x86.ActiveCfg = Release|Any CPU - __LIB_PROJECT_GUID__.Release|x86.Build.0 = Release|Any CPU - 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 -Project(""{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"") = ""Lib"", ""Lib\Lib.csproj"", ""__LIB_PROJECT_GUID__"" -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 - __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|Any CPU - __LIB_PROJECT_GUID__.Debug|x64.Build.0 = Debug|Any CPU - __LIB_PROJECT_GUID__.Debug|x86.ActiveCfg = Debug|Any CPU - __LIB_PROJECT_GUID__.Debug|x86.Build.0 = Debug|Any CPU - __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|Any CPU - __LIB_PROJECT_GUID__.Release|x64.Build.0 = Release|Any CPU - __LIB_PROJECT_GUID__.Release|x86.ActiveCfg = Release|Any CPU - __LIB_PROJECT_GUID__.Release|x86.Build.0 = Release|Any CPU - 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(""{9A19103F-16F7-4668-BE54-9A1E7A4F7556}"") = ""App"", ""App.csproj"", ""{7072A694-548F-4CAE-A58F-12D257D5F486}"" -EndProject -Project(""{2150E333-8FDC-42A3-9474-1A3956D46DE8}"") = ""src"", ""src"", ""__SRC_FOLDER_GUID__"" -EndProject -Project(""{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"") = ""Lib"", ""src\Lib\Lib.csproj"", ""__LIB_PROJECT_GUID__"" -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 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x64.ActiveCfg = Debug|x64 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x64.Build.0 = Debug|x64 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x86.ActiveCfg = Debug|x86 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x86.Build.0 = Debug|x86 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|Any CPU.Build.0 = Release|Any CPU - {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x64.ActiveCfg = Release|x64 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x64.Build.0 = Release|x64 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x86.ActiveCfg = Release|x86 - {7072A694-548F-4CAE-A58F-12D257D5F486}.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|Any CPU - __LIB_PROJECT_GUID__.Debug|x64.Build.0 = Debug|Any CPU - __LIB_PROJECT_GUID__.Debug|x86.ActiveCfg = Debug|Any CPU - __LIB_PROJECT_GUID__.Debug|x86.Build.0 = Debug|Any CPU - __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|Any CPU - __LIB_PROJECT_GUID__.Release|x64.Build.0 = Release|Any CPU - __LIB_PROJECT_GUID__.Release|x86.ActiveCfg = Release|Any CPU - __LIB_PROJECT_GUID__.Release|x86.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - __LIB_PROJECT_GUID__ = __SRC_FOLDER_GUID__ - EndGlobalSection -EndGlobal -"; - - private const string ExpectedSlnFileAfterAddingProjectWithoutMatchingConfigs = @" -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26006.2 -MinimumVisualStudioVersion = 10.0.40219.1 -Project(""{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"") = ""ProjectWithoutMatchingConfigs"", ""ProjectWithoutMatchingConfigs\ProjectWithoutMatchingConfigs.csproj"", ""{C49B64DE-4401-4825-8A88-10DCB5950E57}"" -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 - Foo Bar|Any CPU = Foo Bar|Any CPU - Foo Bar|x64 = Foo Bar|x64 - Foo Bar|x86 = Foo Bar|x86 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {C49B64DE-4401-4825-8A88-10DCB5950E57}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C49B64DE-4401-4825-8A88-10DCB5950E57}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C49B64DE-4401-4825-8A88-10DCB5950E57}.Debug|x64.ActiveCfg = Debug|Any CPU - {C49B64DE-4401-4825-8A88-10DCB5950E57}.Debug|x64.Build.0 = Debug|Any CPU - {C49B64DE-4401-4825-8A88-10DCB5950E57}.Debug|x86.ActiveCfg = Debug|Any CPU - {C49B64DE-4401-4825-8A88-10DCB5950E57}.Debug|x86.Build.0 = Debug|Any CPU - {C49B64DE-4401-4825-8A88-10DCB5950E57}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C49B64DE-4401-4825-8A88-10DCB5950E57}.Release|Any CPU.Build.0 = Release|Any CPU - {C49B64DE-4401-4825-8A88-10DCB5950E57}.Release|x64.ActiveCfg = Release|Any CPU - {C49B64DE-4401-4825-8A88-10DCB5950E57}.Release|x64.Build.0 = Release|Any CPU - {C49B64DE-4401-4825-8A88-10DCB5950E57}.Release|x86.ActiveCfg = Release|Any CPU - {C49B64DE-4401-4825-8A88-10DCB5950E57}.Release|x86.Build.0 = Release|Any CPU - {C49B64DE-4401-4825-8A88-10DCB5950E57}.Foo Bar|Any CPU.ActiveCfg = Debug|Any CPU - {C49B64DE-4401-4825-8A88-10DCB5950E57}.Foo Bar|Any CPU.Build.0 = Debug|Any CPU - {C49B64DE-4401-4825-8A88-10DCB5950E57}.Foo Bar|x64.ActiveCfg = Debug|Any CPU - {C49B64DE-4401-4825-8A88-10DCB5950E57}.Foo Bar|x64.Build.0 = Debug|Any CPU - {C49B64DE-4401-4825-8A88-10DCB5950E57}.Foo Bar|x86.ActiveCfg = Debug|Any CPU - {C49B64DE-4401-4825-8A88-10DCB5950E57}.Foo Bar|x86.Build.0 = Debug|Any CPU - EndGlobalSection -EndGlobal -"; - - private const string ExpectedSlnFileAfterAddingProjectWithMatchingConfigs = @" -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26006.2 -MinimumVisualStudioVersion = 10.0.40219.1 -Project(""{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"") = ""ProjectWithMatchingConfigs"", ""ProjectWithMatchingConfigs\ProjectWithMatchingConfigs.csproj"", ""{C9601CA2-DB64-4FB6-B463-368C7764BF0D}"" -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 - Foo Bar|Any CPU = Foo Bar|Any CPU - Foo Bar|x64 = Foo Bar|x64 - Foo Bar|x86 = Foo Bar|x86 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {C9601CA2-DB64-4FB6-B463-368C7764BF0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C9601CA2-DB64-4FB6-B463-368C7764BF0D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C9601CA2-DB64-4FB6-B463-368C7764BF0D}.Debug|x64.ActiveCfg = Debug|x64 - {C9601CA2-DB64-4FB6-B463-368C7764BF0D}.Debug|x64.Build.0 = Debug|x64 - {C9601CA2-DB64-4FB6-B463-368C7764BF0D}.Debug|x86.ActiveCfg = Debug|x86 - {C9601CA2-DB64-4FB6-B463-368C7764BF0D}.Debug|x86.Build.0 = Debug|x86 - {C9601CA2-DB64-4FB6-B463-368C7764BF0D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C9601CA2-DB64-4FB6-B463-368C7764BF0D}.Release|Any CPU.Build.0 = Release|Any CPU - {C9601CA2-DB64-4FB6-B463-368C7764BF0D}.Release|x64.ActiveCfg = Release|x64 - {C9601CA2-DB64-4FB6-B463-368C7764BF0D}.Release|x64.Build.0 = Release|x64 - {C9601CA2-DB64-4FB6-B463-368C7764BF0D}.Release|x86.ActiveCfg = Release|x86 - {C9601CA2-DB64-4FB6-B463-368C7764BF0D}.Release|x86.Build.0 = Release|x86 - {C9601CA2-DB64-4FB6-B463-368C7764BF0D}.Foo Bar|Any CPU.ActiveCfg = FooBar|Any CPU - {C9601CA2-DB64-4FB6-B463-368C7764BF0D}.Foo Bar|Any CPU.Build.0 = FooBar|Any CPU - {C9601CA2-DB64-4FB6-B463-368C7764BF0D}.Foo Bar|x64.ActiveCfg = FooBar|x64 - {C9601CA2-DB64-4FB6-B463-368C7764BF0D}.Foo Bar|x64.Build.0 = FooBar|x64 - {C9601CA2-DB64-4FB6-B463-368C7764BF0D}.Foo Bar|x86.ActiveCfg = FooBar|x86 - {C9601CA2-DB64-4FB6-B463-368C7764BF0D}.Foo Bar|x86.Build.0 = FooBar|x86 - EndGlobalSection -EndGlobal -"; - - private const string ExpectedSlnFileAfterAddingProjectWithAdditionalConfigs = @" -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26006.2 -MinimumVisualStudioVersion = 10.0.40219.1 -Project(""{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"") = ""ProjectWithAdditionalConfigs"", ""ProjectWithAdditionalConfigs\ProjectWithAdditionalConfigs.csproj"", ""{A302325B-D680-4C0E-8680-7AE283981624}"" -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 - Foo Bar|Any CPU = Foo Bar|Any CPU - Foo Bar|x64 = Foo Bar|x64 - Foo Bar|x86 = Foo Bar|x86 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {A302325B-D680-4C0E-8680-7AE283981624}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A302325B-D680-4C0E-8680-7AE283981624}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A302325B-D680-4C0E-8680-7AE283981624}.Debug|x64.ActiveCfg = Debug|x64 - {A302325B-D680-4C0E-8680-7AE283981624}.Debug|x64.Build.0 = Debug|x64 - {A302325B-D680-4C0E-8680-7AE283981624}.Debug|x86.ActiveCfg = Debug|x86 - {A302325B-D680-4C0E-8680-7AE283981624}.Debug|x86.Build.0 = Debug|x86 - {A302325B-D680-4C0E-8680-7AE283981624}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A302325B-D680-4C0E-8680-7AE283981624}.Release|Any CPU.Build.0 = Release|Any CPU - {A302325B-D680-4C0E-8680-7AE283981624}.Release|x64.ActiveCfg = Release|x64 - {A302325B-D680-4C0E-8680-7AE283981624}.Release|x64.Build.0 = Release|x64 - {A302325B-D680-4C0E-8680-7AE283981624}.Release|x86.ActiveCfg = Release|x86 - {A302325B-D680-4C0E-8680-7AE283981624}.Release|x86.Build.0 = Release|x86 - {A302325B-D680-4C0E-8680-7AE283981624}.Foo Bar|Any CPU.ActiveCfg = FooBar|Any CPU - {A302325B-D680-4C0E-8680-7AE283981624}.Foo Bar|Any CPU.Build.0 = FooBar|Any CPU - {A302325B-D680-4C0E-8680-7AE283981624}.Foo Bar|x64.ActiveCfg = FooBar|x64 - {A302325B-D680-4C0E-8680-7AE283981624}.Foo Bar|x64.Build.0 = FooBar|x64 - {A302325B-D680-4C0E-8680-7AE283981624}.Foo Bar|x86.ActiveCfg = FooBar|x86 - {A302325B-D680-4C0E-8680-7AE283981624}.Foo Bar|x86.Build.0 = FooBar|x86 - EndGlobalSection -EndGlobal -"; - - private const string ExpectedSlnFileAfterAddingProjectWithInRootOption = @" -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26006.2 -MinimumVisualStudioVersion = 10.0.40219.1 -Project(""{9A19103F-16F7-4668-BE54-9A1E7A4F7556}"") = ""App"", ""App.csproj"", ""{7072A694-548F-4CAE-A58F-12D257D5F486}"" -EndProject -Project(""{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"") = ""Lib"", ""src\Lib\Lib.csproj"", ""{84A45D44-B677-492D-A6DA-B3A71135AB8E}"" -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 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x64.ActiveCfg = Debug|x64 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x64.Build.0 = Debug|x64 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x86.ActiveCfg = Debug|x86 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x86.Build.0 = Debug|x86 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|Any CPU.Build.0 = Release|Any CPU - {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x64.ActiveCfg = Release|x64 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x64.Build.0 = Release|x64 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x86.ActiveCfg = Release|x86 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x86.Build.0 = Release|x86 - {84A45D44-B677-492D-A6DA-B3A71135AB8E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {84A45D44-B677-492D-A6DA-B3A71135AB8E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {84A45D44-B677-492D-A6DA-B3A71135AB8E}.Debug|x64.ActiveCfg = Debug|Any CPU - {84A45D44-B677-492D-A6DA-B3A71135AB8E}.Debug|x64.Build.0 = Debug|Any CPU - {84A45D44-B677-492D-A6DA-B3A71135AB8E}.Debug|x86.ActiveCfg = Debug|Any CPU - {84A45D44-B677-492D-A6DA-B3A71135AB8E}.Debug|x86.Build.0 = Debug|Any CPU - {84A45D44-B677-492D-A6DA-B3A71135AB8E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {84A45D44-B677-492D-A6DA-B3A71135AB8E}.Release|Any CPU.Build.0 = Release|Any CPU - {84A45D44-B677-492D-A6DA-B3A71135AB8E}.Release|x64.ActiveCfg = Release|Any CPU - {84A45D44-B677-492D-A6DA-B3A71135AB8E}.Release|x64.Build.0 = Release|Any CPU - {84A45D44-B677-492D-A6DA-B3A71135AB8E}.Release|x86.ActiveCfg = Release|Any CPU - {84A45D44-B677-492D-A6DA-B3A71135AB8E}.Release|x86.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal -"; - - private const string ExpectedSlnFileAfterAddingProjectWithSolutionFolderOption = @" -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26006.2 -MinimumVisualStudioVersion = 10.0.40219.1 -Project(""{9A19103F-16F7-4668-BE54-9A1E7A4F7556}"") = ""App"", ""App.csproj"", ""{7072A694-548F-4CAE-A58F-12D257D5F486}"" -EndProject -Project(""{2150E333-8FDC-42A3-9474-1A3956D46DE8}"") = ""TestFolder"", ""TestFolder"", ""__SOLUTION_FOLDER_GUID__"" -EndProject -Project(""{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"") = ""Lib"", ""src\Lib\Lib.csproj"", ""__LIB_PROJECT_GUID__"" -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 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x64.ActiveCfg = Debug|x64 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x64.Build.0 = Debug|x64 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x86.ActiveCfg = Debug|x86 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x86.Build.0 = Debug|x86 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|Any CPU.Build.0 = Release|Any CPU - {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x64.ActiveCfg = Release|x64 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x64.Build.0 = Release|x64 - {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x86.ActiveCfg = Release|x86 - {7072A694-548F-4CAE-A58F-12D257D5F486}.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|Any CPU - __LIB_PROJECT_GUID__.Debug|x64.Build.0 = Debug|Any CPU - __LIB_PROJECT_GUID__.Debug|x86.ActiveCfg = Debug|Any CPU - __LIB_PROJECT_GUID__.Debug|x86.Build.0 = Debug|Any CPU - __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|Any CPU - __LIB_PROJECT_GUID__.Release|x64.Build.0 = Release|Any CPU - __LIB_PROJECT_GUID__.Release|x86.ActiveCfg = Release|Any CPU - __LIB_PROJECT_GUID__.Release|x86.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - __LIB_PROJECT_GUID__ = __SOLUTION_FOLDER_GUID__ - EndGlobalSection -EndGlobal -"; - [Theory] [InlineData("sln", "--help")] [InlineData("sln", "-h")] @@ -443,10 +69,10 @@ public void WhenNoCommandIsPassedItPrintsError(string solutionCommand, string co public void WhenTooManyArgumentsArePassedItPrintsError(string solutionCommand) { var cmd = new DotnetCommand(Log) - .Execute(solutionCommand, "one.sln", "two.sln", "three.sln", "add"); + .Execute(solutionCommand, "one.sln", "two.sln", "three.slnx", "add"); cmd.Should().Fail(); cmd.StdErr.Should().BeVisuallyEquivalentTo($@"{string.Format(CommandLineValidation.LocalizableStrings.UnrecognizedCommandOrArgument, "two.sln")} -{string.Format(CommandLineValidation.LocalizableStrings.UnrecognizedCommandOrArgument, "three.sln")}"); +{string.Format(CommandLineValidation.LocalizableStrings.UnrecognizedCommandOrArgument, "three.slnx")}"); } [Theory] @@ -470,57 +96,68 @@ public void WhenNonExistingSolutionIsPassedItPrintsErrorAndUsage(string solution } [Theory] - [InlineData("sln")] - [InlineData("solution")] - public void WhenInvalidSolutionIsPassedItPrintsErrorAndUsage(string solutionCommand) + [InlineData("sln", ".sln")] + [InlineData("solution", ".sln")] + [InlineData("sln", ".slnx")] + [InlineData("solution", ".slnx")] + public void WhenInvalidSolutionIsPassedItPrintsErrorAndUsage(string solutionCommand, string solutionExtension) { var projectDirectory = _testAssetsManager - .CopyTestAsset("InvalidSolution", identifier: $"{solutionCommand}") + .CopyTestAsset("InvalidSolution", identifier: $"GivenDotnetSlnAdd-{solutionCommand}{solutionExtension}") .WithSource() .Path; var projectToAdd = Path.Combine("Lib", "Lib.csproj"); var cmd = new DotnetCommand(Log) .WithWorkingDirectory(projectDirectory) - .Execute(solutionCommand, "InvalidSolution.sln", "add", projectToAdd); + .Execute(solutionCommand, $"InvalidSolution{solutionExtension}", "add", projectToAdd); cmd.Should().Fail(); - cmd.StdErr.Should().Be(string.Format(CommonLocalizableStrings.InvalidSolutionFormatString, "InvalidSolution.sln", LocalizableStrings.FileHeaderMissingError)); + cmd.StdErr.Should().Match(string.Format(CommonLocalizableStrings.InvalidSolutionFormatString, Path.Combine(projectDirectory, $"InvalidSolution{solutionExtension}"), "*")); cmd.StdOut.Should().BeVisuallyEquivalentToIfNotLocalized(""); } [Theory] - [InlineData("sln")] - [InlineData("solution")] - public void WhenInvalidSolutionIsFoundAddPrintsErrorAndUsage(string solutionCommand) + [InlineData("sln", ".sln")] + [InlineData("solution", ".sln")] + + [InlineData("sln", ".slnx")] + [InlineData("solution", ".slnx")] + public void WhenInvalidSolutionIsFoundAddPrintsErrorAndUsage(string solutionCommand, string solutionExtension) { - var projectDirectory = _testAssetsManager - .CopyTestAsset("InvalidSolution", identifier: $"{solutionCommand}") + var projectDirectoryRoot = _testAssetsManager + .CopyTestAsset("InvalidSolution", identifier: $"GivenDotnetSlnAdd-{solutionCommand}{solutionExtension}") .WithSource() .Path; - var solutionPath = Path.Combine(projectDirectory, "InvalidSolution.sln"); - var projectToAdd = Path.Combine("Lib", "Lib.csproj"); + var projectDirectory = solutionExtension == ".sln" + ? Path.Join(projectDirectoryRoot, "Sln") + : Path.Join(projectDirectoryRoot, "Slnx"); + + var solutionPath = Path.Combine(projectDirectory, $"InvalidSolution{solutionExtension}"); + var projectToAdd = Path.Combine("..", "Lib", "Lib.csproj"); var cmd = new DotnetCommand(Log) .WithWorkingDirectory(projectDirectory) .Execute(solutionCommand, "add", projectToAdd); cmd.Should().Fail(); - cmd.StdErr.Should().Be(string.Format(CommonLocalizableStrings.InvalidSolutionFormatString, solutionPath, LocalizableStrings.FileHeaderMissingError)); + cmd.StdErr.Should().Match(string.Format(CommonLocalizableStrings.InvalidSolutionFormatString, solutionPath, "*")); cmd.StdOut.Should().BeVisuallyEquivalentToIfNotLocalized(""); } [Theory] - [InlineData("sln")] - [InlineData("solution")] - public void WhenNoProjectIsPassedItPrintsErrorAndUsage(string solutionCommand) + [InlineData("sln", ".sln")] + [InlineData("solution", ".sln")] + [InlineData("sln", ".slnx")] + [InlineData("solution", ".slnx")] + public void WhenNoProjectIsPassedItPrintsErrorAndUsage(string solutionCommand, string solutionExtension) { var projectDirectory = _testAssetsManager - .CopyTestAsset("TestAppWithSlnAndCsprojFiles", identifier: $"{solutionCommand}") + .CopyTestAsset("TestAppWithSlnAndCsprojFiles", identifier: $"GivenDotnetSlnAdd-{solutionCommand}{solutionExtension}") .WithSource() .Path; var cmd = new DotnetCommand(Log) .WithWorkingDirectory(projectDirectory) - .Execute(solutionCommand, "App.sln", "add"); + .Execute(solutionCommand, $"App{solutionExtension}", "add"); cmd.Should().Fail(); cmd.StdErr.Should().Be(CommonLocalizableStrings.SpecifyAtLeastOneProjectToAdd); cmd.StdOut.Should().BeVisuallyEquivalentToIfNotLocalized(""); @@ -532,7 +169,7 @@ public void WhenNoProjectIsPassedItPrintsErrorAndUsage(string solutionCommand) public void WhenNoSolutionExistsInTheDirectoryAddPrintsErrorAndUsage(string solutionCommand) { var projectDirectory = _testAssetsManager - .CopyTestAsset("TestAppWithSlnAndCsprojFiles", identifier: $"{solutionCommand}") + .CopyTestAsset("TestAppWithSlnAndCsprojFiles", identifier: $"GivenDotnetSlnAdd-{solutionCommand}") .WithSource() .Path; @@ -551,7 +188,7 @@ public void WhenNoSolutionExistsInTheDirectoryAddPrintsErrorAndUsage(string solu public void WhenMoreThanOneSolutionExistsInTheDirectoryItPrintsErrorAndUsage(string solutionCommand) { var projectDirectory = _testAssetsManager - .CopyTestAsset("TestAppWithMultipleSlnFiles", identifier: "GivenDotnetSlnAdd") + .CopyTestAsset("TestAppWithMultipleSlnFiles", identifier: $"GivenDotnetSlnAdd-{solutionCommand}") .WithSource() .Path; @@ -565,41 +202,50 @@ public void WhenMoreThanOneSolutionExistsInTheDirectoryItPrintsErrorAndUsage(str } [Theory] - [InlineData("sln")] - [InlineData("solution")] - public void WhenNestedProjectIsAddedSolutionFoldersAreCreated(string solutionCommand) + [InlineData("sln", ".sln")] + [InlineData("solution", ".sln")] + + [InlineData("sln", ".slnx")] + [InlineData("solution", ".slnx")] + public void WhenNestedProjectIsAddedSolutionFoldersAreCreated(string solutionCommand, string solutionExtension) { var projectDirectory = _testAssetsManager - .CopyTestAsset("TestAppWithSlnAndCsprojInSubDir") + .CopyTestAsset("TestAppWithSlnAndCsprojInSubDir", identifier: $"GivenDotnetSlnAdd-{solutionCommand}{solutionExtension}") .WithSource() .Path; var projectToAdd = Path.Combine("src", "Lib", "Lib.csproj"); var cmd = new DotnetCommand(Log) .WithWorkingDirectory(projectDirectory) - .Execute(solutionCommand, "App.sln", "add", projectToAdd); + .Execute(solutionCommand, $"App{solutionExtension}", "add", projectToAdd); cmd.Should().Pass(); - var slnPath = Path.Combine(projectDirectory, "App.sln"); - var expectedSlnContents = GetExpectedSlnContents(slnPath, ExpectedSlnFileAfterAddingNestedProj); + var slnPath = Path.Combine(projectDirectory, $"App{solutionExtension}"); + var expectedSlnContents = GetExpectedSlnContents( + slnPath, + $"ExpectedSlnFileAfterAddingNestedProj{solutionExtension}", + solutionExtension: solutionExtension); + File.ReadAllText(slnPath) .Should().BeVisuallyEquivalentTo(expectedSlnContents); cmd = new DotnetCommand(Log) .WithWorkingDirectory(projectDirectory) - .Execute($"build", "App.sln"); + .Execute($"build", $"App{solutionExtension}"); cmd.Should().Pass(); } [Theory] - [InlineData("sln", true)] - [InlineData("sln", false)] - [InlineData("solution", true)] - [InlineData("solution", false)] - public void WhenNestedProjectIsAddedSolutionFoldersAreCreatedBuild(string solutionCommand, bool fooFirst) + [InlineData("sln", true, ".sln")] + [InlineData("sln", false, ".sln")] + [InlineData("solution", true, ".sln")] + [InlineData("solution", false, ".sln")] + [InlineData("sln", true, ".slnx")] + [InlineData("solution", false, ".slnx")] + public void WhenNestedProjectIsAddedSolutionFoldersAreCreatedBuild(string solutionCommand, bool fooFirst, string solutionExtension) { var projectDirectory = _testAssetsManager - .CopyTestAsset("TestAppWithSlnAndCsprojInSubDirVS", identifier: $"{solutionCommand}{fooFirst}") + .CopyTestAsset("TestAppWithSlnAndCsprojInSubDirVS", identifier: $"GivenDotnetSlnAdd{solutionCommand}{fooFirst}{solutionExtension}") .WithSource() .Path; string projectToAdd; @@ -610,14 +256,14 @@ public void WhenNestedProjectIsAddedSolutionFoldersAreCreatedBuild(string soluti projectToAdd = "foo"; cmd = new DotnetCommand(Log) .WithWorkingDirectory(projectDirectory) - .Execute(solutionCommand, "App.sln", "add", projectToAdd); + .Execute(solutionCommand, $"App{solutionExtension}", "add", projectToAdd); cmd.Should().Pass(); } projectToAdd = Path.Combine("foo", "bar"); cmd = new DotnetCommand(Log) .WithWorkingDirectory(projectDirectory) - .Execute(solutionCommand, "App.sln", "add", projectToAdd); + .Execute(solutionCommand, $"App{solutionExtension}", "add", projectToAdd); cmd.Should().Pass(); if (!fooFirst) @@ -625,24 +271,24 @@ public void WhenNestedProjectIsAddedSolutionFoldersAreCreatedBuild(string soluti projectToAdd = "foo"; cmd = new DotnetCommand(Log) .WithWorkingDirectory(projectDirectory) - .Execute(solutionCommand, "App.sln", "add", projectToAdd); + .Execute(solutionCommand, $"App{solutionExtension}", "add", projectToAdd); cmd.Should().Pass(); } cmd = new DotnetCommand(Log) .WithWorkingDirectory(projectDirectory) - .Execute($"build", "App.sln"); + .Execute($"build", $"App{solutionExtension}"); cmd.Should().Pass(); } - [Theory] + [Theory(Skip = "Having projects with the same name in different paths is allowed.")] [InlineData("sln")] [InlineData("solution")] public void WhenNestedDuplicateProjectIsAddedToASolutionFolder(string solutionCommand) { var projectDirectory = _testAssetsManager - .CopyTestAsset("TestAppWithSlnAndCsprojInSubDirVSErrors", identifier: $"{solutionCommand}") + .CopyTestAsset("TestAppWithSlnAndCsprojInSubDirVSErrors", identifier: $"GivenDotnetSlnAdd-{solutionCommand}") .WithSource() .Path; string projectToAdd; @@ -666,47 +312,54 @@ public void WhenNestedDuplicateProjectIsAddedToASolutionFolder(string solutionCo } [Theory] - [InlineData("sln", "TestAppWithSlnAndCsprojFiles")] - [InlineData("sln", "TestAppWithSlnAnd472CsprojFiles")] - [InlineData("solution", "TestAppWithSlnAndCsprojFiles")] - [InlineData("solution", "TestAppWithSlnAnd472CsprojFiles")] - public void WhenDirectoryContainingProjectIsGivenProjectIsAdded(string solutionCommand, string testAsset) + [InlineData("sln", "TestAppWithSlnAndCsprojFiles", ".sln")] + [InlineData("sln", "TestAppWithSlnAnd472CsprojFiles", ".sln")] + [InlineData("solution", "TestAppWithSlnAndCsprojFiles", ".sln")] + [InlineData("solution", "TestAppWithSlnAnd472CsprojFiles", ".sln")] + [InlineData("sln", "TestAppWithSlnAndCsprojFiles", ".slnx")] + [InlineData("solution", "TestAppWithSlnAnd472CsprojFiles", ".slnx")] + public void WhenDirectoryContainingProjectIsGivenProjectIsAdded(string solutionCommand, string testAsset, string solutionExtension) { var projectDirectory = _testAssetsManager - .CopyTestAsset(testAsset, identifier: $"{solutionCommand}{testAsset}") + .CopyTestAsset(testAsset, identifier: $"GivenDotnetSlnAdd-{solutionCommand}{testAsset}{solutionExtension}") .WithSource() .Path; var cmd = new DotnetCommand(Log) .WithWorkingDirectory(projectDirectory) - .Execute(solutionCommand, "add", "Lib"); + .Execute(solutionCommand, $"App{solutionExtension}", "add", "Lib"); cmd.Should().Pass(); - var slnPath = Path.Combine(projectDirectory, "App.sln"); - var expectedSlnContents = GetExpectedSlnContents(slnPath, ExpectedSlnFileAfterAddingLibProj); + var slnPath = Path.Combine(projectDirectory, $"App{solutionExtension}"); + + var expectedSlnContents = GetExpectedSlnContents( + slnPath, + $"ExpectedSlnFileAfterAddingLibProj{solutionExtension}", solutionExtension: solutionExtension); File.ReadAllText(slnPath) .Should().BeVisuallyEquivalentTo(expectedSlnContents); } [Theory] - [InlineData("sln")] - [InlineData("solution")] - public void WhenDirectoryContainsNoProjectsItCancelsWholeOperation(string solutionCommand) + [InlineData("sln", ".sln")] + [InlineData("solution", ".sln")] + [InlineData("sln", ".slnx")] + [InlineData("solution", ".slnx")] + public void WhenDirectoryContainsNoProjectsItCancelsWholeOperation(string solutionCommand, string solutionExtension) { var projectDirectory = _testAssetsManager - .CopyTestAsset("TestAppWithSlnAndCsprojFiles", identifier: $"{solutionCommand}") + .CopyTestAsset("TestAppWithSlnAndCsprojFiles", identifier: $"GivenDotnetSlnAdd-{solutionCommand}{solutionExtension}") .WithSource() .Path; - var slnFullPath = Path.Combine(projectDirectory, "App.sln"); + var slnFullPath = Path.Combine(projectDirectory, $"App{solutionExtension}"); var contentBefore = File.ReadAllText(slnFullPath); var directoryToAdd = "Empty"; var cmd = new DotnetCommand(Log) .WithWorkingDirectory(projectDirectory) - .Execute(solutionCommand, "add", directoryToAdd); + .Execute(solutionCommand, $"App{solutionExtension}", "add", directoryToAdd); cmd.Should().Fail(); - cmd.StdErr.Should().Be( + cmd.StdErr.Should().Contain( string.Format( CommonLocalizableStrings.CouldNotFindAnyProjectInDirectory, Path.Combine(projectDirectory, directoryToAdd))); @@ -716,24 +369,26 @@ public void WhenDirectoryContainsNoProjectsItCancelsWholeOperation(string soluti } [Theory] - [InlineData("sln")] - [InlineData("solution")] - public void WhenDirectoryContainsMultipleProjectsItCancelsWholeOperation(string solutionCommand) + [InlineData("sln", ".sln")] + [InlineData("solution", ".sln")] + [InlineData("sln", ".slnx")] + [InlineData("solution", ".slnx")] + public void WhenDirectoryContainsMultipleProjectsItCancelsWholeOperation(string solutionCommand, string solutionExtension) { var projectDirectory = _testAssetsManager - .CopyTestAsset("TestAppWithSlnAndCsprojFiles", identifier: $"{solutionCommand}") + .CopyTestAsset("TestAppWithSlnAndCsprojFiles", identifier: $"GivenDotnetSlnAdd-{solutionCommand}{solutionExtension}") .WithSource() .Path; - var slnFullPath = Path.Combine(projectDirectory, "App.sln"); + var slnFullPath = Path.Combine(projectDirectory, $"App{solutionExtension}"); var contentBefore = File.ReadAllText(slnFullPath); var directoryToAdd = "Multiple"; var cmd = new DotnetCommand(Log) .WithWorkingDirectory(projectDirectory) - .Execute(solutionCommand, "add", directoryToAdd); + .Execute(solutionCommand, $"App{solutionExtension}", "add", directoryToAdd); cmd.Should().Fail(); - cmd.StdErr.Should().Be( + cmd.StdErr.Should().Contain( string.Format( CommonLocalizableStrings.MoreThanOneProjectInDirectory, Path.Combine(projectDirectory, directoryToAdd))); @@ -743,137 +398,147 @@ public void WhenDirectoryContainsMultipleProjectsItCancelsWholeOperation(string } [Theory] - [InlineData("sln")] - [InlineData("solution")] - public void WhenProjectDirectoryIsAddedSolutionFoldersAreNotCreated(string solutionCommand) + [InlineData("sln", ".sln")] + [InlineData("solution", ".sln")] + [InlineData("sln", ".slnx")] + [InlineData("solution", ".slnx")] + public async Task WhenProjectDirectoryIsAddedSolutionFoldersAreNotCreated(string solutionCommand, string solutionExtension) { var projectDirectory = _testAssetsManager - .CopyTestAsset("TestAppWithSlnAndCsprojFiles", identifier: $"{solutionCommand}") + .CopyTestAsset("TestAppWithSlnAndCsprojFiles", identifier: $"GivenDotnetSlnAdd-{solutionCommand}{solutionExtension}") .WithSource() .Path; var projectToAdd = Path.Combine("Lib", "Lib.csproj"); var cmd = new DotnetCommand(Log) .WithWorkingDirectory(projectDirectory) - .Execute(solutionCommand, "App.sln", "add", projectToAdd); + .Execute(solutionCommand, $"App{solutionExtension}", "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(); + ISolutionSerializer serializer = SolutionSerializers.GetSerializerByMoniker(Path.Combine(projectDirectory, $"App{solutionExtension}")); + SolutionModel solution = await serializer.OpenAsync(Path.Combine(projectDirectory, $"App{solutionExtension}"), CancellationToken.None); + + solution.SolutionFolders.Count().Should().Be(0); + solution.SolutionProjects + .Where(p => p.Parent != null) + .Count() + .Should().Be(0); } [Theory] - [InlineData("sln")] - [InlineData("solution")] - public void WhenSharedProjectAddedShouldStillBuild(string solutionCommand) + [InlineData("sln", ".sln")] + [InlineData("solution", ".sln")] + [InlineData("sln", ".slnx")] + [InlineData("solution", ".slnx")] + public void WhenSharedProjectAddedShouldStillBuild(string solutionCommand, string solutionExtension) { var projectDirectory = _testAssetsManager - .CopyTestAsset("TestAppWithSlnAndCsprojFiles", $"{solutionCommand}") + .CopyTestAsset("TestAppWithSlnAndCsprojFiles", $"GivenDotnetSlnAdd-{solutionCommand}{solutionExtension}") .WithSource() .Path; var projectToAdd = Path.Combine("Shared", "Shared.shproj"); var cmd = new DotnetCommand(Log) .WithWorkingDirectory(projectDirectory) - .Execute(solutionCommand, "App.sln", "add", projectToAdd); + .Execute(solutionCommand, $"App{solutionExtension}", "add", projectToAdd); cmd.Should().Pass(); cmd.StdErr.Should().BeEmpty(); - cmd = new DotnetBuildCommand(Log) + cmd = new DotnetBuildCommand(Log, $"App{solutionExtension}") .WithWorkingDirectory(projectDirectory) .Execute(); cmd.Should().Pass(); } [Theory] - [InlineData("sln", ".")] - [InlineData("sln", "")] - [InlineData("solution", ".")] - [InlineData("solution", "")] - public void WhenSolutionFolderExistsItDoesNotGetAdded(string solutionCommand, string firstComponent) + [InlineData("sln", ".", ".sln")] + [InlineData("sln", "", ".sln")] + [InlineData("solution", ".", ".sln")] + [InlineData("solution", "", ".sln")] + [InlineData("sln", ".", ".slnx")] + [InlineData("solution", "", ".slnx")] + public async Task WhenSolutionFolderExistsItDoesNotGetAdded(string solutionCommand, string firstComponent, string solutionExtension) { var projectDirectory = _testAssetsManager - .CopyTestAsset("TestAppWithSlnAndSolutionFolders", identifier: $"{solutionCommand}{firstComponent}") + .CopyTestAsset("TestAppWithSlnAndSolutionFolders", identifier: $"GivenDotnetSlnAdd-{solutionCommand}{firstComponent}{solutionExtension}") .WithSource() .Path; var projectToAdd = Path.Combine($"{firstComponent}", "src", "src", "Lib", "Lib.csproj"); var cmd = new DotnetCommand(Log) .WithWorkingDirectory(projectDirectory) - .Execute(solutionCommand, "App.sln", "add", projectToAdd); + .Execute(solutionCommand, $"App{solutionExtension}", "add", projectToAdd); cmd.Should().Pass(); - var slnFile = SlnFile.Read(Path.Combine(projectDirectory, "App.sln")); - slnFile.Projects.Count().Should().Be(4); + ISolutionSerializer serializer = SolutionSerializers.GetSerializerByMoniker(Path.Combine(projectDirectory, $"App{solutionExtension}")); + SolutionModel solution = await serializer.OpenAsync(Path.Combine(projectDirectory, $"App{solutionExtension}"), CancellationToken.None); - var solutionFolderProjects = slnFile.Projects.Where( - p => p.TypeGuid == ProjectTypeGuids.SolutionFolderGuid); - solutionFolderProjects.Count().Should().Be(2); + solution.SolutionItems.Count().Should().Be(4); + solution.SolutionFolders.Count().Should().Be(2); - var solutionFolders = slnFile.Sections.GetSection("NestedProjects").Properties; - solutionFolders.Count.Should().Be(3); + solution.SolutionItems.Where(item => item.Parent != null).Count().Should().Be(3); - solutionFolders["{DDF3765C-59FB-4AA6-BE83-779ED13AA64A}"] - .Should().Be("{72BFCA87-B033-4721-8712-4D12166B4A39}"); + var newlyAddedSrcFolder = solution.SolutionFolders.Single(p => p.Parent != null); + newlyAddedSrcFolder.Parent.Id.Should().Be(solution.SolutionFolders.Single(p => p.Parent == null).Id); - var newlyAddedSrcFolder = solutionFolderProjects.Single(p => p.Id != "{72BFCA87-B033-4721-8712-4D12166B4A39}"); - solutionFolders[newlyAddedSrcFolder.Id] - .Should().Be("{72BFCA87-B033-4721-8712-4D12166B4A39}"); - - var libProject = slnFile.Projects.Single(p => p.Name == "Lib"); - solutionFolders[libProject.Id] - .Should().Be(newlyAddedSrcFolder.Id); + var libProject = solution.SolutionProjects.Single(p => p.ActualDisplayName.Contains("Lib")); + libProject.Parent.Id.Should().Be(newlyAddedSrcFolder.Id); } [Theory] - [InlineData("sln", "TestAppWithSlnAndCsprojFiles", ExpectedSlnFileAfterAddingLibProj, "")] - [InlineData("sln", "TestAppWithSlnAndCsprojProjectGuidFiles", ExpectedSlnFileAfterAddingLibProj, "{84A45D44-B677-492D-A6DA-B3A71135AB8E}")] - [InlineData("sln", "TestAppWithEmptySln", ExpectedSlnFileAfterAddingLibProjToEmptySln, "")] - [InlineData("solution", "TestAppWithSlnAndCsprojFiles", ExpectedSlnFileAfterAddingLibProj, "")] - [InlineData("solution", "TestAppWithSlnAndCsprojProjectGuidFiles", ExpectedSlnFileAfterAddingLibProj, "{84A45D44-B677-492D-A6DA-B3A71135AB8E}")] - [InlineData("solution", "TestAppWithEmptySln", ExpectedSlnFileAfterAddingLibProjToEmptySln, "")] + [InlineData("sln", "TestAppWithSlnAndCsprojFiles", "ExpectedSlnFileAfterAddingLibProj", "", ".sln")] + [InlineData("sln", "TestAppWithSlnAndCsprojProjectGuidFiles", "ExpectedSlnFileAfterAddingLibProj", "84a45d44-b677-492d-a6da-b3a71135ab8e", ".sln")] + [InlineData("sln", "TestAppWithEmptySln", "ExpectedSlnFileAfterAddingLibProjToEmptySln", "", ".sln")] + [InlineData("solution", "TestAppWithSlnAndCsprojFiles", "ExpectedSlnFileAfterAddingLibProj", "", ".sln")] + [InlineData("solution", "TestAppWithSlnAndCsprojProjectGuidFiles", "ExpectedSlnFileAfterAddingLibProj", "84a45d44-b677-492d-a6da-b3a71135ab8e", ".sln")] + [InlineData("solution", "TestAppWithEmptySln", "ExpectedSlnFileAfterAddingLibProjToEmptySln", "", ".sln")] + [InlineData("sln", "TestAppWithSlnAndCsprojFiles", "ExpectedSlnFileAfterAddingLibProj", "", ".slnx")] + [InlineData("solution", "TestAppWithSlnAndCsprojProjectGuidFiles", "ExpectedSlnFileAfterAddingLibProj", "84a45d44-b677-492d-a6da-b3a71135ab8e", ".slnx")] + [InlineData("solution", "TestAppWithEmptySln", "ExpectedSlnFileAfterAddingLibProjToEmptySln", "", ".slnx")] public void WhenValidProjectIsPassedBuildConfigsAreAdded( string solutionCommand, string testAsset, string expectedSlnContentsTemplate, - string expectedProjectGuid) + string expectedProjectGuid, + string solutionExtension) { var projectDirectory = _testAssetsManager - .CopyTestAsset(testAsset, $"{solutionCommand}{testAsset}") + .CopyTestAsset(testAsset, $"GivenDotnetSlnAdd-{solutionCommand}{testAsset}") .WithSource() .Path; var projectToAdd = "Lib/Lib.csproj"; var cmd = new DotnetCommand(Log) .WithWorkingDirectory(projectDirectory) - .Execute(solutionCommand, "App.sln", "add", projectToAdd); + .Execute(solutionCommand, $"App{solutionExtension}", "add", projectToAdd); cmd.Should().Pass(); - var slnPath = Path.Combine(projectDirectory, "App.sln"); + var slnPath = Path.Combine(projectDirectory, $"App{solutionExtension}"); var expectedSlnContents = GetExpectedSlnContents( slnPath, - expectedSlnContentsTemplate, - expectedProjectGuid); + $"{expectedSlnContentsTemplate}{solutionExtension}", + expectedProjectGuid, + solutionExtension: solutionExtension); File.ReadAllText(slnPath) .Should().BeVisuallyEquivalentTo(expectedSlnContents); } [Theory] - [InlineData("sln", "TestAppWithSlnAndCsprojFiles")] - [InlineData("sln", "TestAppWithSlnAndCsprojProjectGuidFiles")] - [InlineData("sln", "TestAppWithEmptySln")] - [InlineData("solution", "TestAppWithSlnAndCsprojFiles")] - [InlineData("solution", "TestAppWithSlnAndCsprojProjectGuidFiles")] - [InlineData("solution", "TestAppWithEmptySln")] - public void WhenValidProjectIsPassedItGetsAdded(string solutionCommand, string testAsset) + [InlineData("sln", "TestAppWithSlnAndCsprojFiles", ".sln")] + [InlineData("sln", "TestAppWithSlnAndCsprojProjectGuidFiles", ".sln")] + [InlineData("sln", "TestAppWithEmptySln", ".sln")] + [InlineData("solution", "TestAppWithSlnAndCsprojFiles", ".sln")] + [InlineData("solution", "TestAppWithSlnAndCsprojProjectGuidFiles", ".sln")] + [InlineData("solution", "TestAppWithEmptySln", ".sln")] + [InlineData("sln", "TestAppWithSlnAndCsprojFiles", ".slnx")] + [InlineData("solution", "TestAppWithSlnAndCsprojProjectGuidFiles", ".slnx")] + [InlineData("solution", "TestAppWithEmptySln", ".slnx")] + public void WhenValidProjectIsPassedItGetsAdded(string solutionCommand, string testAsset, string solutionExtension) { var projectDirectory = _testAssetsManager - .CopyTestAsset(testAsset, identifier: $"{solutionCommand}{testAsset}") + .CopyTestAsset(testAsset, identifier: $"GivenDotnetSlnAdd-{solutionCommand}{testAsset}{solutionExtension}") .WithSource() .Path; @@ -881,7 +546,7 @@ public void WhenValidProjectIsPassedItGetsAdded(string solutionCommand, string t var projectPath = Path.Combine("Lib", "Lib.csproj"); var cmd = new DotnetCommand(Log) .WithWorkingDirectory(projectDirectory) - .Execute(solutionCommand, "App.sln", "add", projectToAdd); + .Execute(solutionCommand, $"App{solutionExtension}", "add", projectToAdd); cmd.Should().Pass(); cmd.StdOut.Should().Be(string.Format(CommonLocalizableStrings.ProjectAddedToTheSolution, projectPath)); cmd.StdErr.Should().BeEmpty(); @@ -893,7 +558,7 @@ public void WhenValidProjectIsPassedItGetsAdded(string solutionCommand, string t public void WhenProjectIsAddedSolutionHasUTF8BOM(string solutionCommand) { var projectDirectory = _testAssetsManager - .CopyTestAsset("TestAppWithEmptySln", $"{solutionCommand}") + .CopyTestAsset("TestAppWithEmptySln", $"GivenDotnetSlnAdd-{solutionCommand}") .WithSource() .Path; @@ -916,63 +581,72 @@ public void WhenProjectIsAddedSolutionHasUTF8BOM(string solutionCommand) } [Theory] - [InlineData("sln", "TestAppWithSlnAndCsprojFiles")] - [InlineData("sln", "TestAppWithSlnAndCsprojProjectGuidFiles")] - [InlineData("sln", "TestAppWithEmptySln")] - [InlineData("solution", "TestAppWithSlnAndCsprojFiles")] - [InlineData("solution", "TestAppWithSlnAndCsprojProjectGuidFiles")] - [InlineData("solution", "TestAppWithEmptySln")] - public void WhenInvalidProjectIsPassedItDoesNotGetAdded(string solutionCommand, string testAsset) + [InlineData("sln", "TestAppWithSlnAndCsprojFiles", ".sln")] + [InlineData("sln", "TestAppWithSlnAndCsprojProjectGuidFiles", ".sln")] + [InlineData("sln", "TestAppWithEmptySln", ".sln")] + [InlineData("solution", "TestAppWithSlnAndCsprojFiles", ".sln")] + [InlineData("solution", "TestAppWithSlnAndCsprojProjectGuidFiles", ".sln")] + [InlineData("solution", "TestAppWithEmptySln", ".sln")] + [InlineData("sln", "TestAppWithSlnAndCsprojFiles", ".slnx")] + [InlineData("solution", "TestAppWithSlnAndCsprojProjectGuidFiles", ".slnx")] + [InlineData("solution", "TestAppWithEmptySln", ".slnx")] + public async Task WhenInvalidProjectIsPassedItDoesNotGetAdded(string solutionCommand, string testAsset, string solutionExtension) { var projectDirectory = _testAssetsManager - .CopyTestAsset(testAsset, $"{solutionCommand}{testAsset}") + .CopyTestAsset(testAsset, $"GivenDotnetSlnAdd-{solutionCommand}{testAsset}{solutionExtension}") .WithSource() .Path; var projectToAdd = "Lib/Library.cs"; - var slnFile = SlnFile.Read(Path.Combine(projectDirectory, "App.sln")); - var expectedNumberOfProjects = slnFile.Projects.Count(); + + ISolutionSerializer serializer = SolutionSerializers.GetSerializerByMoniker(Path.Combine(projectDirectory, $"App{solutionExtension}")); + SolutionModel solution = await serializer.OpenAsync(Path.Combine(projectDirectory, $"App{solutionExtension}"), CancellationToken.None); + + var expectedNumberOfProjects = solution.SolutionProjects.Count(); var cmd = new DotnetCommand(Log) .WithWorkingDirectory(projectDirectory) - .Execute(solutionCommand, "App.sln", "add", projectToAdd); + .Execute(solutionCommand, $"App{solutionExtension}", "add", projectToAdd); cmd.Should().Pass(); cmd.StdOut.Should().BeEmpty(); cmd.StdErr.Should().Match(string.Format(CommonLocalizableStrings.InvalidProjectWithExceptionMessage, '*', '*')); - slnFile = SlnFile.Read(Path.Combine(projectDirectory, "App.sln")); - slnFile.Projects.Count().Should().Be(expectedNumberOfProjects); + solution = await serializer.OpenAsync(Path.Combine(projectDirectory, $"App{solutionExtension}"), CancellationToken.None); + solution.SolutionProjects.Count().Should().Be(expectedNumberOfProjects); } [Theory] - [InlineData("sln", "TestAppWithSlnAndCsprojFiles")] - [InlineData("sln", "TestAppWithSlnAndCsprojProjectGuidFiles")] - [InlineData("sln", "TestAppWithEmptySln")] - [InlineData("solution", "TestAppWithSlnAndCsprojFiles")] - [InlineData("solution", "TestAppWithSlnAndCsprojProjectGuidFiles")] - [InlineData("solution", "TestAppWithEmptySln")] - public void WhenValidProjectIsPassedTheSlnBuilds(string solutionCommand, string testAsset) + [InlineData("sln", "TestAppWithSlnAndCsprojFiles", ".sln")] + [InlineData("sln", "TestAppWithSlnAndCsprojProjectGuidFiles", ".sln")] + [InlineData("sln", "TestAppWithEmptySln", ".sln")] + [InlineData("solution", "TestAppWithSlnAndCsprojFiles", ".sln")] + [InlineData("solution", "TestAppWithSlnAndCsprojProjectGuidFiles", ".sln")] + [InlineData("solution", "TestAppWithEmptySln", ".sln")] + [InlineData("sln", "TestAppWithSlnAndCsprojFiles", ".slnx")] + [InlineData("solution", "TestAppWithSlnAndCsprojProjectGuidFiles", ".slnx")] + [InlineData("solution", "TestAppWithEmptySln", ".slnx")] + public void WhenValidProjectIsPassedTheSlnBuilds(string solutionCommand, string testAsset, string solutionExtension) { var projectDirectory = _testAssetsManager - .CopyTestAsset(testAsset, identifier: $"{solutionCommand}{testAsset}") + .CopyTestAsset(testAsset, identifier: $"GivenDotnetSlnAdd-{solutionCommand}{testAsset}{solutionExtension}") .WithSource() .Path; var cmd = new DotnetCommand(Log) .WithWorkingDirectory(projectDirectory) - .Execute(solutionCommand, "App.sln", "add", "App/App.csproj", "Lib/Lib.csproj"); + .Execute(solutionCommand, $"App{solutionExtension}", "add", "App/App.csproj", "Lib/Lib.csproj"); cmd.Should().Pass(); - var slnPath = Path.Combine(projectDirectory, "App.sln"); + var slnPath = Path.Combine(projectDirectory, $"App{solutionExtension}"); new DotnetCommand(Log) .WithWorkingDirectory(projectDirectory) - .Execute($"restore", "App.sln") + .Execute($"restore", $"App{solutionExtension}") .Should().Pass(); new DotnetCommand(Log) .WithWorkingDirectory(projectDirectory) - .Execute("build", "App.sln", "--configuration", "Release") + .Execute("build", $"App{solutionExtension}", "--configuration", "Release") .Should().Pass(); var reasonString = "should be built in release mode, otherwise it means build configurations are missing from the sln file"; @@ -989,44 +663,47 @@ public void WhenValidProjectIsPassedTheSlnBuilds(string solutionCommand, string } [Theory] - [InlineData("sln", "TestAppWithSlnAndExistingCsprojReferences")] - [InlineData("sln", "TestAppWithSlnAndExistingCsprojReferencesWithEscapedDirSep")] - [InlineData("solution", "TestAppWithSlnAndExistingCsprojReferences")] - [InlineData("solution", "TestAppWithSlnAndExistingCsprojReferencesWithEscapedDirSep")] - public void WhenSolutionAlreadyContainsProjectItDoesntDuplicate(string solutionCommand, string testAsset) + [InlineData("sln", "TestAppWithSlnAndExistingCsprojReferences", ".sln")] + [InlineData("sln", "TestAppWithSlnAndExistingCsprojReferencesWithEscapedDirSep", ".sln")] + [InlineData("solution", "TestAppWithSlnAndExistingCsprojReferences", ".sln")] + [InlineData("solution", "TestAppWithSlnAndExistingCsprojReferencesWithEscapedDirSep", ".sln")] + [InlineData("sln", "TestAppWithSlnAndExistingCsprojReferences", ".slnx")] + [InlineData("solution", "TestAppWithSlnAndExistingCsprojReferencesWithEscapedDirSep", ".slnx")] + public void WhenSolutionAlreadyContainsProjectItDoesntDuplicate(string solutionCommand, string testAsset, string solutionExtension) { var projectDirectory = _testAssetsManager - .CopyTestAsset(testAsset, identifier: $"{solutionCommand}{testAsset}") + .CopyTestAsset(testAsset, identifier: $"GivenDotnetSlnAdd-{solutionCommand}{testAsset}{solutionExtension}") .WithSource() .Path; - var solutionPath = Path.Combine(projectDirectory, "App.sln"); + var solutionPath = Path.Combine(projectDirectory, $"App{solutionExtension}"); var projectToAdd = Path.Combine("Lib", "Lib.csproj"); var cmd = new DotnetCommand(Log) .WithWorkingDirectory(projectDirectory) - .Execute(solutionCommand, "App.sln", "add", projectToAdd); + .Execute(solutionCommand, $"App{solutionExtension}", "add", projectToAdd); cmd.Should().Pass(); cmd.StdOut.Should().Be(string.Format(CommonLocalizableStrings.SolutionAlreadyContainsProject, solutionPath, projectToAdd)); - cmd.StdErr.Should().BeEmpty(); } [Theory] - [InlineData("sln")] - [InlineData("solution")] - public void WhenPassedMultipleProjectsAndOneOfthemDoesNotExistItCancelsWholeOperation(string solutionCommand) + [InlineData("sln", ".sln")] + [InlineData("solution", ".sln")] + [InlineData("sln", ".slnx")] + [InlineData("solution", ".slnx")] + public void WhenPassedMultipleProjectsAndOneOfthemDoesNotExistItCancelsWholeOperation(string solutionCommand, string solutionExtension) { var projectDirectory = _testAssetsManager - .CopyTestAsset("TestAppWithSlnAndCsprojFiles", identifier: $"{solutionCommand}") + .CopyTestAsset("TestAppWithSlnAndCsprojFiles", identifier: $"GivenDotnetSlnAdd-{solutionCommand}{solutionExtension}") .WithSource() .Path; - var slnFullPath = Path.Combine(projectDirectory, "App.sln"); + var slnFullPath = Path.Combine(projectDirectory, $"App{solutionExtension}"); var contentBefore = File.ReadAllText(slnFullPath); var projectToAdd = Path.Combine("Lib", "Lib.csproj"); var cmd = new DotnetCommand(Log) .WithWorkingDirectory(projectDirectory) - .Execute(solutionCommand, "App.sln", "add", projectToAdd, "idonotexist.csproj"); + .Execute(solutionCommand, $"App{solutionExtension}", "add", projectToAdd, "idonotexist.csproj"); cmd.Should().Fail(); cmd.StdErr.Should().Be(string.Format(CommonLocalizableStrings.CouldNotFindProjectOrDirectory, "idonotexist.csproj")); @@ -1040,7 +717,7 @@ public void WhenPassedMultipleProjectsAndOneOfthemDoesNotExistItCancelsWholeOper public void WhenPassedAnUnknownProjectTypeItFails(string solutionCommand) { var projectDirectory = _testAssetsManager - .CopyTestAsset("SlnFileWithNoProjectReferencesAndUnknownProject", identifier: $"{solutionCommand}") + .CopyTestAsset("SlnFileWithNoProjectReferencesAndUnknownProject", identifier: $"GivenDotnetSlnAdd-{solutionCommand}") .WithSource() .Path; @@ -1058,6 +735,7 @@ public void WhenPassedAnUnknownProjectTypeItFails(string solutionCommand) .Should().BeVisuallyEquivalentTo(contentBefore); } + // SLN ONLY [Theory] [InlineData("sln", "SlnFileWithNoProjectReferencesAndCSharpProject", "CSharpProject", "CSharpProject.csproj", ProjectTypeGuids.CSharpProjectTypeGuid)] [InlineData("sln", "SlnFileWithNoProjectReferencesAndFSharpProject", "FSharpProject", "FSharpProject.fsproj", ProjectTypeGuids.FSharpProjectTypeGuid)] @@ -1069,7 +747,7 @@ public void WhenPassedAnUnknownProjectTypeItFails(string solutionCommand) [InlineData("solution", "SlnFileWithNoProjectReferencesAndVBProject", "VBProject", "VBProject.vbproj", ProjectTypeGuids.VBProjectTypeGuid)] [InlineData("solution", "SlnFileWithNoProjectReferencesAndUnknownProjectWithSingleProjectTypeGuid", "UnknownProject", "UnknownProject.unknownproj", "{130159A9-F047-44B3-88CF-0CF7F02ED50F}")] [InlineData("solution", "SlnFileWithNoProjectReferencesAndUnknownProjectWithMultipleProjectTypeGuids", "UnknownProject", "UnknownProject.unknownproj", "{130159A9-F047-44B3-88CF-0CF7F02ED50F}")] - public void WhenPassedAProjectItAddsCorrectProjectTypeGuid( + public async Task WhenPassedAProjectItAddsCorrectProjectTypeGuid( string solutionCommand, string testAsset, string projectDir, @@ -1077,7 +755,7 @@ public void WhenPassedAProjectItAddsCorrectProjectTypeGuid( string expectedTypeGuid) { var projectDirectory = _testAssetsManager - .CopyTestAsset(testAsset, identifier: $"{solutionCommand}{testAsset}") + .CopyTestAsset(testAsset, identifier: $"GivenDotnetSlnAdd-{solutionCommand}{testAsset}") .WithSource() .Path; @@ -1089,30 +767,32 @@ public void WhenPassedAProjectItAddsCorrectProjectTypeGuid( cmd.StdErr.Should().BeEmpty(); cmd.StdOut.Should().Be(string.Format(CommonLocalizableStrings.ProjectAddedToTheSolution, projectToAdd)); - var slnFile = SlnFile.Read(Path.Combine(projectDirectory, "App.sln")); - var nonSolutionFolderProjects = slnFile.Projects.Where( - p => p.TypeGuid != ProjectTypeGuids.SolutionFolderGuid); + ISolutionSerializer serializer = SolutionSerializers.GetSerializerByMoniker(Path.Combine(projectDirectory, "App.sln")); + SolutionModel solution = await serializer.OpenAsync(Path.Combine(projectDirectory, "App.sln"), CancellationToken.None); + var nonSolutionFolderProjects = solution.SolutionProjects; nonSolutionFolderProjects.Count().Should().Be(1); - nonSolutionFolderProjects.Single().TypeGuid.Should().Be(expectedTypeGuid); + nonSolutionFolderProjects.Single().TypeId.Should().Be(new Guid(expectedTypeGuid)); } [Theory] - [InlineData("sln")] - [InlineData("solution")] - public void WhenPassedAProjectWithoutATypeGuidItErrors(string solutionCommand) + [InlineData("sln", ".sln")] + [InlineData("solution", ".sln")] + [InlineData("sln", ".slnx")] + [InlineData("solution", ".slnx")] + public void WhenPassedAProjectWithoutATypeGuidItErrors(string solutionCommand, string solutionExtension) { var solutionDirectory = _testAssetsManager - .CopyTestAsset("SlnFileWithNoProjectReferencesAndUnknownProjectType", identifier: $"{solutionCommand}") + .CopyTestAsset("SlnFileWithNoProjectReferencesAndUnknownProjectType", identifier: $"GivenDotnetSlnAdd-{solutionCommand}{solutionExtension}") .WithSource() .Path; - var solutionPath = Path.Combine(solutionDirectory, "App.sln"); + var solutionPath = Path.Combine(solutionDirectory, $"App{solutionExtension}"); var contentBefore = File.ReadAllText(solutionPath); var projectToAdd = Path.Combine("UnknownProject", "UnknownProject.unknownproj"); var cmd = new DotnetCommand(Log) .WithWorkingDirectory(solutionDirectory) - .Execute(solutionCommand, "add", projectToAdd); + .Execute(solutionCommand, $"App{solutionExtension}", "add", projectToAdd); cmd.Should().Pass(); cmd.StdErr.Should().Be( string.Format( @@ -1126,97 +806,112 @@ public void WhenPassedAProjectWithoutATypeGuidItErrors(string solutionCommand) } [Theory] - [InlineData("sln")] - [InlineData("solution")] - private void WhenSlnContainsSolutionFolderWithDifferentCasingItDoesNotCreateDuplicate(string solutionCommand) + [InlineData("sln", ".sln")] + [InlineData("solution", ".sln")] + [InlineData("sln", ".slnx")] + [InlineData("solution", ".slnx")] + private async Task WhenSlnContainsSolutionFolderWithDifferentCasingItDoesNotCreateDuplicate(string solutionCommand, string solutionExtension) { var projectDirectory = _testAssetsManager - .CopyTestAsset("TestAppWithSlnAndCaseSensitiveSolutionFolders", identifier: $"{solutionCommand}") + .CopyTestAsset("TestAppWithSlnAndCaseSensitiveSolutionFolders", identifier: $"GivenDotnetSlnAdd-{solutionCommand}{solutionExtension}") .WithSource() .Path; var projectToAdd = Path.Combine("src", "Lib", "Lib.csproj"); var cmd = new DotnetCommand(Log) .WithWorkingDirectory(projectDirectory) - .Execute(solutionCommand, "App.sln", "add", projectToAdd); + .Execute(solutionCommand, $"App{solutionExtension}", "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); + ISolutionSerializer serializer = SolutionSerializers.GetSerializerByMoniker(Path.Combine(projectDirectory, $"App{solutionExtension}")); + SolutionModel solution = await serializer.OpenAsync(Path.Combine(projectDirectory, $"App{solutionExtension}"), CancellationToken.None); + solution.SolutionFolders.Count().Should().Be(1); } [Theory] - [InlineData("sln")] - [InlineData("solution")] - public void WhenProjectWithoutMatchingConfigurationsIsAddedSolutionMapsToFirstAvailable(string solutionCommand) + [InlineData("sln", ".sln")] + [InlineData("solution", ".sln")] + [InlineData("sln", ".slnx")] + [InlineData("solution", ".slnx")] + public void WhenProjectWithoutMatchingConfigurationsIsAddedSolutionMapsToFirstAvailable(string solutionCommand, string solutionExtension) { var slnDirectory = _testAssetsManager - .CopyTestAsset("TestAppWithSlnAndProjectConfigs", identifier: $"{solutionCommand}") + .CopyTestAsset("TestAppWithSlnAndProjectConfigs", identifier: $"GivenDotnetSlnAdd-{solutionCommand}{solutionExtension}") .WithSource() .Path; - var slnFullPath = Path.Combine(slnDirectory, "App.sln"); + var slnFullPath = Path.Combine(slnDirectory, $"App{solutionExtension}"); var result = new DotnetCommand(Log) .WithWorkingDirectory(slnDirectory) - .Execute(solutionCommand, "add", "ProjectWithoutMatchingConfigs"); + .Execute(solutionCommand, $"App{solutionExtension}", "add", "ProjectWithoutMatchingConfigs"); result.Should().Pass(); + var expectedResult = File.ReadAllText(Path.Combine(slnDirectory, "Results", $"ExpectedSlnFileAfterAddingProjectWithoutMatchingConfigs{solutionExtension}")); + File.ReadAllText(slnFullPath) - .Should().BeVisuallyEquivalentTo(ExpectedSlnFileAfterAddingProjectWithoutMatchingConfigs); + .Should().BeVisuallyEquivalentTo(expectedResult); } [Theory] - [InlineData("sln")] - [InlineData("solution")] - public void WhenProjectWithMatchingConfigurationsIsAddedSolutionMapsAll(string solutionCommand) + [InlineData("sln", ".sln")] + [InlineData("solution", ".sln")] + [InlineData("sln", ".slnx")] + [InlineData("solution", ".slnx")] + public void WhenProjectWithMatchingConfigurationsIsAddedSolutionMapsAll(string solutionCommand, string solutionExtension) { var slnDirectory = _testAssetsManager - .CopyTestAsset("TestAppWithSlnAndProjectConfigs", identifier: $"{solutionCommand}") + .CopyTestAsset("TestAppWithSlnAndProjectConfigs", identifier: $"GivenDotnetSlnAdd-{solutionCommand}{solutionExtension}") .WithSource() .Path; - var slnFullPath = Path.Combine(slnDirectory, "App.sln"); + var slnFullPath = Path.Combine(slnDirectory, $"App{solutionExtension}"); var result = new DotnetCommand(Log) .WithWorkingDirectory(slnDirectory) - .Execute(solutionCommand, "add", "ProjectWithMatchingConfigs"); + .Execute(solutionCommand, $"App{solutionExtension}", "add", "ProjectWithMatchingConfigs"); result.Should().Pass(); + var expectedResult = File.ReadAllText(Path.Combine(slnDirectory, "Results", $"ExpectedSlnFileAfterAddingProjectWithMatchingConfigs{solutionExtension}")); + File.ReadAllText(slnFullPath) - .Should().BeVisuallyEquivalentTo(ExpectedSlnFileAfterAddingProjectWithMatchingConfigs); + .Should().BeVisuallyEquivalentTo(expectedResult); } [Theory] - [InlineData("sln")] - [InlineData("solution")] - public void WhenProjectWithAdditionalConfigurationsIsAddedSolutionDoesNotMapThem(string solutionCommand) + [InlineData("sln", ".sln")] + [InlineData("solution", ".sln")] + [InlineData("sln", ".slnx")] + [InlineData("solution", ".slnx")] + public void WhenProjectWithAdditionalConfigurationsIsAddedSolutionDoesNotMapThem(string solutionCommand, string solutionExtension) { var slnDirectory = _testAssetsManager - .CopyTestAsset("TestAppWithSlnAndProjectConfigs", identifier: $"{solutionCommand}") + .CopyTestAsset("TestAppWithSlnAndProjectConfigs", identifier: $"GivenDotnetSlnAdd-{solutionCommand}{solutionExtension}") .WithSource() .Path; - var slnFullPath = Path.Combine(slnDirectory, "App.sln"); + var slnFullPath = Path.Combine(slnDirectory, $"App{solutionExtension}"); var result = new DotnetCommand(Log) .WithWorkingDirectory(slnDirectory) - .Execute(solutionCommand, "add", "ProjectWithAdditionalConfigs"); + .Execute(solutionCommand, $"App{solutionExtension}", "add", "ProjectWithAdditionalConfigs"); result.Should().Pass(); + var expectedResult = File.ReadAllText(Path.Combine(slnDirectory, "Results", $"ExpectedSlnFileAfterAddingProjectWithAdditionalConfigs{solutionExtension}")); + File.ReadAllText(slnFullPath) - .Should().BeVisuallyEquivalentTo(ExpectedSlnFileAfterAddingProjectWithAdditionalConfigs); + .Should().BeVisuallyEquivalentTo(expectedResult); } [Theory] - [InlineData("sln")] - [InlineData("solution")] - public void ItAddsACSharpProjectThatIsMultitargeted(string solutionCommand) + [InlineData("sln", ".sln")] + [InlineData("solution", ".sln")] + [InlineData("sln", ".slnx")] + [InlineData("solution", ".slnx")] + public void ItAddsACSharpProjectThatIsMultitargeted(string solutionCommand, string solutionExtension) { var solutionDirectory = _testAssetsManager - .CopyTestAsset("TestAppsWithSlnAndMultitargetedProjects", identifier: $"{solutionCommand}") + .CopyTestAsset("TestAppsWithSlnAndMultitargetedProjects", identifier: $"GivenDotnetSlnAdd-{solutionCommand}{solutionExtension}") .WithSource() .Path; @@ -1224,7 +919,7 @@ public void ItAddsACSharpProjectThatIsMultitargeted(string solutionCommand) new DotnetCommand(Log) .WithWorkingDirectory(solutionDirectory) - .Execute(solutionCommand, "add", projectToAdd) + .Execute(solutionCommand, $"TestAppsWithSlnAndMultitargetedProjects{solutionExtension}", "add", projectToAdd) .Should() .Pass() .And @@ -1232,12 +927,14 @@ public void ItAddsACSharpProjectThatIsMultitargeted(string solutionCommand) } [Theory] - [InlineData("sln")] - [InlineData("solution")] - public void ItAddsAVisualBasicProjectThatIsMultitargeted(string solutionCommand) + [InlineData("sln", ".sln")] + [InlineData("solution", ".sln")] + [InlineData("sln", ".slnx")] + [InlineData("solution", ".slnx")] + public void ItAddsAVisualBasicProjectThatIsMultitargeted(string solutionCommand, string solutionExtension) { var solutionDirectory = _testAssetsManager - .CopyTestAsset("TestAppsWithSlnAndMultitargetedProjects", identifier: $"{solutionCommand}") + .CopyTestAsset("TestAppsWithSlnAndMultitargetedProjects", identifier: $"GivenDotnetSlnAdd-{solutionCommand}{solutionExtension}") .WithSource() .Path; @@ -1245,7 +942,7 @@ public void ItAddsAVisualBasicProjectThatIsMultitargeted(string solutionCommand) new DotnetCommand(Log) .WithWorkingDirectory(solutionDirectory) - .Execute(solutionCommand, "add", projectToAdd) + .Execute(solutionCommand, $"TestAppsWithSlnAndMultitargetedProjects{solutionExtension}", "add", projectToAdd) .Should() .Pass() .And @@ -1253,12 +950,14 @@ public void ItAddsAVisualBasicProjectThatIsMultitargeted(string solutionCommand) } [Theory] - [InlineData("sln")] - [InlineData("solution")] - public void ItAddsAnFSharpProjectThatIsMultitargeted(string solutionCommand) + [InlineData("sln", ".sln")] + [InlineData("solution", ".sln")] + [InlineData("sln", ".slnx")] + [InlineData("solution", ".slnx")] + public void ItAddsAnFSharpProjectThatIsMultitargeted(string solutionCommand, string solutionExtension) { var solutionDirectory = _testAssetsManager - .CopyTestAsset("TestAppsWithSlnAndMultitargetedProjects", identifier: $"{solutionCommand}") + .CopyTestAsset("TestAppsWithSlnAndMultitargetedProjects", identifier: $"GivenDotnetSlnAdd-{solutionCommand}{solutionExtension}") .WithSource() .Path; @@ -1267,7 +966,7 @@ public void ItAddsAnFSharpProjectThatIsMultitargeted(string solutionCommand) new DotnetCommand(Log) .WithWorkingDirectory(solutionDirectory) - .Execute(solutionCommand, "add", projectToAdd) + .Execute(solutionCommand, $"TestAppsWithSlnAndMultitargetedProjects{solutionExtension}", "add", projectToAdd) .Should() .Pass() .And @@ -1275,66 +974,79 @@ public void ItAddsAnFSharpProjectThatIsMultitargeted(string solutionCommand) } [Theory] - [InlineData("sln")] - [InlineData("solution")] - public void WhenNestedProjectIsAddedAndInRootOptionIsPassedNoSolutionFoldersAreCreated(string solutionCommand) + [InlineData("sln", ".sln")] + [InlineData("solution", ".sln")] + [InlineData("sln", ".slnx")] + [InlineData("solution", ".slnx")] + public void WhenNestedProjectIsAddedAndInRootOptionIsPassedNoSolutionFoldersAreCreated(string solutionCommand, string solutionExtension) { var projectDirectory = _testAssetsManager - .CopyTestAsset("TestAppWithSlnAndCsprojInSubDir", identifier: $"{solutionCommand}") + .CopyTestAsset("TestAppWithSlnAndCsprojInSubDir", identifier: $"GivenDotnetSlnAdd-{solutionCommand}{solutionExtension}") .WithSource() .Path; - var projectToAdd = Path.Combine("src", "Lib", "Lib.csproj"); var cmd = new DotnetCommand(Log) .WithWorkingDirectory(projectDirectory) - .Execute(solutionCommand, "App.sln", "add", "--in-root", projectToAdd); + .Execute(solutionCommand, $"App{solutionExtension}", "add", "--in-root", projectToAdd); cmd.Should().Pass(); - var slnPath = Path.Combine(projectDirectory, "App.sln"); - var expectedSlnContents = GetExpectedSlnContents(slnPath, ExpectedSlnFileAfterAddingProjectWithInRootOption); + var slnPath = Path.Combine(projectDirectory, $"App{solutionExtension}"); + + var expectedSlnContents = GetExpectedSlnContents( + slnPath, + $"ExpectedSlnFileAfterAddingProjectWithInRootOption{solutionExtension}", + solutionExtension: solutionExtension); File.ReadAllText(slnPath) .Should().BeVisuallyEquivalentTo(expectedSlnContents); } [Theory] - [InlineData("sln")] - [InlineData("solution")] - public void WhenSolutionFolderIsPassedProjectsAreAddedThere(string solutionCommand) + [InlineData("sln", ".sln")] + [InlineData("solution", ".sln")] + [InlineData("sln", ".slnx")] + [InlineData("solution", ".slnx")] + public void WhenSolutionFolderIsPassedProjectsAreAddedThere(string solutionCommand, string solutionExtension) { var projectDirectory = _testAssetsManager - .CopyTestAsset("TestAppWithSlnAndCsprojInSubDir", identifier: $"{solutionCommand}") + .CopyTestAsset("TestAppWithSlnAndCsprojInSubDir", identifier: $"GivenDotnetSlnAdd-{solutionCommand}{solutionExtension}") .WithSource() .Path; var projectToAdd = Path.Combine("src", "Lib", "Lib.csproj"); var cmd = new DotnetCommand(Log) .WithWorkingDirectory(projectDirectory) - .Execute(solutionCommand, "App.sln", "add", "--solution-folder", "TestFolder", projectToAdd); + .Execute(solutionCommand, $"App{solutionExtension}", "add", "--solution-folder", "TestFolder", projectToAdd); cmd.Should().Pass(); - var slnPath = Path.Combine(projectDirectory, "App.sln"); - var expectedSlnContents = GetExpectedSlnContents(slnPath, ExpectedSlnFileAfterAddingProjectWithSolutionFolderOption); + var slnPath = Path.Combine(projectDirectory, $"App{solutionExtension}"); + + var expectedSlnContents = GetExpectedSlnContents( + slnPath, + $"ExpectedSlnFileAfterAddingProjectWithSolutionFolderOption{solutionExtension}", + solutionExtension: solutionExtension); File.ReadAllText(slnPath) .Should().BeVisuallyEquivalentTo(expectedSlnContents); } [Theory] - [InlineData("sln")] - [InlineData("solution")] - public void WhenSolutionFolderAndInRootIsPassedItFails(string solutionCommand) + [InlineData("sln", ".sln")] + [InlineData("solution", ".sln")] + [InlineData("sln", ".slnx")] + [InlineData("solution", ".slnx")] + public void WhenSolutionFolderAndInRootIsPassedItFails(string solutionCommand, string solutionExtension) { var solutionDirectory = _testAssetsManager - .CopyTestAsset("TestAppWithSlnAndCsprojInSubDir", identifier: $"{solutionCommand}") + .CopyTestAsset("TestAppWithSlnAndCsprojInSubDir", identifier: $"GivenDotnetSlnAdd-{solutionCommand}{solutionExtension}") .WithSource() .Path; - var solutionPath = Path.Combine(solutionDirectory, "App.sln"); + var solutionPath = Path.Combine(solutionDirectory, $"App{solutionExtension}"); var contentBefore = File.ReadAllText(solutionPath); var projectToAdd = Path.Combine("src", "Lib", "Lib.csproj"); var cmd = new DotnetCommand(Log) .WithWorkingDirectory(solutionDirectory) - .Execute(solutionCommand, "App.sln", "add", "--solution-folder", "blah", "--in-root", projectToAdd); + .Execute(solutionCommand, $"App{solutionExtension}", "add", "--solution-folder", "blah", "--in-root", projectToAdd); cmd.Should().Fail(); cmd.StdOut.Should().BeVisuallyEquivalentToIfNotLocalized(""); cmd.StdErr.Should().Be(Tools.Sln.LocalizableStrings.SolutionFolderAndInRootMutuallyExclusive); @@ -1346,108 +1058,150 @@ public void WhenSolutionFolderAndInRootIsPassedItFails(string solutionCommand) } [Theory] - [InlineData("sln", "/TestFolder//", "ForwardSlash")] - [InlineData("sln", "\\TestFolder\\\\", "BackwardSlash")] - [InlineData("solution", "/TestFolder//", "ForwardSlash")] - [InlineData("solution", "\\TestFolder\\\\", "BackwardSlash")] - public void WhenSolutionFolderIsPassedWithDirectorySeparatorFolderStructureIsCorrect(string solutionCommand, string solutionFolder, string testIdentifier) + [InlineData("sln", "/TestFolder//", "ForwardSlash", ".sln")] + [InlineData("sln", "\\TestFolder\\\\", "BackwardSlash", ".sln")] + [InlineData("solution", "/TestFolder//", "ForwardSlash", ".sln")] + [InlineData("solution", "\\TestFolder\\\\", "BackwardSlash", ".sln")] + + [InlineData("sln", "/TestFolder//", "ForwardSlash", ".slnx")] + [InlineData("solution", "\\TestFolder\\\\", "BackwardSlash", ".slnx")] + public void WhenSolutionFolderIsPassedWithDirectorySeparatorFolderStructureIsCorrect(string solutionCommand, string solutionFolder, string testIdentifier, string solutionExtension) { var projectDirectory = _testAssetsManager - .CopyTestAsset("TestAppWithSlnAndCsprojInSubDir", identifier: $"{solutionCommand}{testIdentifier}") + .CopyTestAsset("TestAppWithSlnAndCsprojInSubDir", identifier: $"GivenDotnetSlnAdd-{solutionCommand}{testIdentifier}{solutionExtension}") .WithSource() .Path; var projectToAdd = Path.Combine("src", "Lib", "Lib.csproj"); var cmd = new DotnetCommand(Log) .WithWorkingDirectory(projectDirectory) - .Execute(solutionCommand, "App.sln", "add", "--solution-folder", solutionFolder, projectToAdd); + .Execute(solutionCommand, $"App{solutionExtension}", "add", "--solution-folder", solutionFolder, projectToAdd); cmd.Should().Pass(); - var slnPath = Path.Combine(projectDirectory, "App.sln"); - var expectedSlnContents = GetExpectedSlnContents(slnPath, ExpectedSlnFileAfterAddingProjectWithSolutionFolderOption); + var slnPath = Path.Combine(projectDirectory, $"App{solutionExtension}"); + + var expectedSlnContents = GetExpectedSlnContents( + slnPath, + $"ExpectedSlnFileAfterAddingProjectWithSolutionFolderOption{solutionExtension}", + solutionExtension: solutionExtension); File.ReadAllText(slnPath) .Should().BeVisuallyEquivalentTo(expectedSlnContents); } private string GetExpectedSlnContents( string slnPath, - string slnTemplate, - string expectedLibProjectGuid = null) + string slnTemplateName, + string expectedLibProjectGuid = null, + string solutionExtension = ".sln") { - var slnFile = SlnFile.Read(slnPath); + var slnTemplate = GetSolutionFileTemplateContents(slnTemplateName); + ISolutionSerializer serializer = SolutionSerializers.GetSerializerByMoniker(slnPath); + SolutionModel solution = serializer.OpenAsync(slnPath, CancellationToken.None).Result; if (string.IsNullOrEmpty(expectedLibProjectGuid)) { - var matchingProjects = slnFile.Projects - .Where((p) => p.FilePath.EndsWith("Lib.csproj")) + var matchingProjects = solution.SolutionProjects + .Where(p => p.FilePath.EndsWith("Lib.csproj")) .ToList(); matchingProjects.Count.Should().Be(1); var slnProject = matchingProjects[0]; - expectedLibProjectGuid = slnProject.Id; + expectedLibProjectGuid = slnProject.Id.ToString(); } - var slnContents = slnTemplate.Replace("__LIB_PROJECT_GUID__", expectedLibProjectGuid); - var matchingSrcFolder = slnFile.Projects - .Where((p) => p.FilePath == "src") - .ToList(); + var slnContents = slnTemplate.Replace( + "__LIB_PROJECT_GUID__", + solutionExtension == ".sln" + ? $"{{{expectedLibProjectGuid.ToUpper()}}}" + : expectedLibProjectGuid); + + var matchingSrcFolder = solution.SolutionFolders + .Where(p => p.Path.Contains("src")) + .ToList(); if (matchingSrcFolder.Count == 1) { - slnContents = slnContents.Replace("__SRC_FOLDER_GUID__", matchingSrcFolder[0].Id); + slnContents = slnContents.Replace( + "__SRC_FOLDER_GUID__", + solutionExtension == ".sln" + ? $"{{{matchingSrcFolder[0].Id.ToString().ToUpper()}}}" + : matchingSrcFolder[0].Id.ToString()); } - var matchingSolutionFolder = slnFile.Projects - .Where((p) => p.FilePath == "TestFolder") - .ToList(); + var matchingSolutionFolder = solution.SolutionFolders + .Where(p => p.Path.Contains("TestFolder")) + .ToList(); if (matchingSolutionFolder.Count == 1) { - slnContents = slnContents.Replace("__SOLUTION_FOLDER_GUID__", matchingSolutionFolder[0].Id); + slnContents = slnContents.Replace( + "_SOLUTION_FOLDER_GUID__", + solutionExtension == ".sln" + ? $"{{{matchingSolutionFolder[0].Id.ToString().ToUpper()}}}" + : matchingSolutionFolder[0].Id.ToString()); } return slnContents; } [Theory] - [InlineData("sln")] - [InlineData("solution")] - public void WhenSolutionIsPassedAsProjectItPrintsSuggestionAndUsage(string solutionCommand) + [InlineData("sln", ".sln")] + [InlineData("solution", ".sln")] + public void WhenSolutionIsPassedAsProjectItPrintsSuggestionAndUsage(string solutionCommand, string solutionExtension) { - VerifySuggestionAndUsage(solutionCommand, ""); + VerifySuggestionAndUsage(solutionCommand, "", solutionExtension); } [Theory] - [InlineData("sln")] - [InlineData("solution")] - public void WhenSolutionIsPassedAsProjectWithInRootItPrintsSuggestionAndUsage(string solutionCommand) + [InlineData("sln", ".sln")] + [InlineData("solution", ".sln")] + public void WhenSolutionIsPassedAsProjectWithInRootItPrintsSuggestionAndUsage(string solutionCommand, string solutionExtension) { - VerifySuggestionAndUsage(solutionCommand, "--in-root"); + VerifySuggestionAndUsage(solutionCommand, "--in-root", solutionExtension); } [Theory] - [InlineData("sln")] - [InlineData("solution")] - public void WhenSolutionIsPassedAsProjectWithSolutionFolderItPrintsSuggestionAndUsage(string solutionCommand) + [InlineData("sln", ".sln")] + [InlineData("solution", ".sln")] + public void WhenSolutionIsPassedAsProjectWithSolutionFolderItPrintsSuggestionAndUsage(string solutionCommand, string solutionExtension) { - VerifySuggestionAndUsage(solutionCommand, "--solution-folder"); + VerifySuggestionAndUsage(solutionCommand, "--solution-folder", solutionExtension); } - private void VerifySuggestionAndUsage(string solutionCommand, string arguments) + private void VerifySuggestionAndUsage(string solutionCommand, string arguments, string solutionExtension) { var projectDirectory = _testAssetsManager - .CopyTestAsset("TestAppWithSlnAndCsprojFiles", identifier: $"{solutionCommand}{arguments}") + .CopyTestAsset("TestAppWithSlnAndCsprojFiles", identifier: $"{solutionCommand}{arguments}{solutionExtension}") .WithSource() .Path; + // TODO: Move to different location + if (solutionExtension == ".sln") + { + File.Delete(Path.Join(projectDirectory, "App.slnx")); + } + else if (solutionExtension == ".slnx") + { + File.Delete(Path.Join(projectDirectory, "App.sln")); + } + var projectArg = Path.Combine("Lib", "Lib.csproj"); var cmd = new DotnetCommand(Log) .WithWorkingDirectory(projectDirectory) - .Execute(solutionCommand, "add", arguments, "Lib", "App.sln", projectArg); + .Execute(solutionCommand, "add", arguments, "Lib", $"App{solutionExtension}", projectArg); cmd.Should().Fail(); cmd.StdErr.Should().BeVisuallyEquivalentTo( - string.Format(CommonLocalizableStrings.SolutionArgumentMisplaced, "App.sln") + Environment.NewLine + string.Format(CommonLocalizableStrings.SolutionArgumentMisplaced, $"App{solutionExtension}") + Environment.NewLine + CommonLocalizableStrings.DidYouMean + Environment.NewLine - + $" dotnet solution App.sln add {arguments} Lib {projectArg}" + + $" dotnet solution App{solutionExtension} add {arguments} Lib {projectArg}" ); cmd.StdOut.Should().BeVisuallyEquivalentToIfNotLocalized(""); } + + private string GetSolutionFileTemplateContents(string templateFileName) + { + var templateContentDirectory = _testAssetsManager + .CopyTestAsset("SolutionFilesTemplates", identifier: "SolutionFilesTemplates") + .WithSource() + .Path; + return File.ReadAllText(Path.Join(templateContentDirectory, templateFileName)); + } } } diff --git a/test/dotnet-sln.Tests/GivenDotnetSlnList.cs b/test/dotnet-sln.Tests/GivenDotnetSlnList.cs index 77670963b1ad..682a1e45c495 100644 --- a/test/dotnet-sln.Tests/GivenDotnetSlnList.cs +++ b/test/dotnet-sln.Tests/GivenDotnetSlnList.cs @@ -92,7 +92,7 @@ public void WhenNonExistingSolutionIsPassedItPrintsErrorAndUsage(string solution public void WhenInvalidSolutionIsPassedItPrintsErrorAndUsage(string solutionCommand) { var projectDirectory = _testAssetsManager - .CopyTestAsset("InvalidSolution", identifier: "GivenDotnetSlnList") + .CopyTestAsset("InvalidSolution", identifier: $"GivenDotnetSlnList-InvalidSolutionPassed-{solutionCommand}") .WithSource() .Path; @@ -100,26 +100,34 @@ public void WhenInvalidSolutionIsPassedItPrintsErrorAndUsage(string solutionComm .WithWorkingDirectory(projectDirectory) .Execute(solutionCommand, "InvalidSolution.sln", "list"); cmd.Should().Fail(); - cmd.StdErr.Should().Be(string.Format(CommonLocalizableStrings.InvalidSolutionFormatString, "InvalidSolution.sln", LocalizableStrings.FileHeaderMissingError)); + cmd.StdErr.Should().Contain( + string.Format(CommonLocalizableStrings.InvalidSolutionFormatString, Path.Combine(projectDirectory, "InvalidSolution.sln"), "").TrimEnd('.')); cmd.StdOut.Should().BeVisuallyEquivalentToIfNotLocalized(""); } [Theory] - [InlineData("sln")] - [InlineData("solution")] - public void WhenInvalidSolutionIsFoundListPrintsErrorAndUsage(string solutionCommand) + [InlineData("sln", ".sln")] + [InlineData("solution", ".sln")] + [InlineData("sln", ".slnx")] + [InlineData("solution", ".slnx")] + public void WhenInvalidSolutionIsFoundListPrintsErrorAndUsage(string solutionCommand, string solutionExtension) { - var projectDirectory = _testAssetsManager - .CopyTestAsset("InvalidSolution") + var projectRootDirectory = _testAssetsManager + .CopyTestAsset("InvalidSolution", identifier: $"GivenDotnetSlnList-InvalidSolutionFound-{solutionCommand}{solutionExtension}") .WithSource() .Path; - var solutionFullPath = Path.Combine(projectDirectory, "InvalidSolution.sln"); + var projectDirectory = solutionExtension == ".sln" + ? Path.Join(projectRootDirectory, "Sln") + : Path.Join(projectRootDirectory, "Slnx"); + + var solutionFullPath = Path.Combine(projectDirectory, $"InvalidSolution{solutionExtension}"); var cmd = new DotnetCommand(Log) .WithWorkingDirectory(projectDirectory) .Execute(solutionCommand, "list"); cmd.Should().Fail(); - cmd.StdErr.Should().Be(string.Format(CommonLocalizableStrings.InvalidSolutionFormatString, solutionFullPath, LocalizableStrings.FileHeaderMissingError)); + cmd.StdErr.Should().Contain( + string.Format(CommonLocalizableStrings.InvalidSolutionFormatString, solutionFullPath, "").TrimEnd('.')); cmd.StdOut.Should().BeVisuallyEquivalentToIfNotLocalized(""); } @@ -129,7 +137,7 @@ public void WhenInvalidSolutionIsFoundListPrintsErrorAndUsage(string solutionCom public void WhenNoSolutionExistsInTheDirectoryListPrintsErrorAndUsage(string solutionCommand) { var projectDirectory = _testAssetsManager - .CopyTestAsset("TestAppWithSlnAndCsprojFiles") + .CopyTestAsset("TestAppWithSlnAndCsprojFiles", identifier: $"GivenDotnetSlnList-{solutionCommand}") .WithSource() .Path; @@ -148,7 +156,7 @@ public void WhenNoSolutionExistsInTheDirectoryListPrintsErrorAndUsage(string sol public void WhenMoreThanOneSolutionExistsInTheDirectoryItPrintsErrorAndUsage(string solutionCommand) { var projectDirectory = _testAssetsManager - .CopyTestAsset("TestAppWithMultipleSlnFiles", identifier: "GivenDotnetSlnList") + .CopyTestAsset("TestAppWithMultipleSlnFiles", identifier: $"GivenDotnetSlnList-{solutionCommand}") .WithSource() .Path; @@ -161,26 +169,30 @@ public void WhenMoreThanOneSolutionExistsInTheDirectoryItPrintsErrorAndUsage(str } [Theory] - [InlineData("sln")] - [InlineData("solution")] - public void WhenNoProjectsArePresentInTheSolutionItPrintsANoProjectMessage(string solutionCommand) + [InlineData("sln", ".sln")] + [InlineData("solution", ".sln")] + [InlineData("sln", ".slnx")] + [InlineData("solution", ".slnx")] + public void WhenNoProjectsArePresentInTheSolutionItPrintsANoProjectMessage(string solutionCommand, string solutionExtension) { var projectDirectory = _testAssetsManager - .CopyTestAsset("TestAppWithEmptySln") + .CopyTestAsset("TestAppWithEmptySln", identifier: $"GivenDotnetSlnList-{solutionCommand}{solutionExtension}") .WithSource() .Path; var cmd = new DotnetCommand(Log) .WithWorkingDirectory(projectDirectory) - .Execute(solutionCommand, "list"); + .Execute(solutionCommand, $"App{solutionExtension}", "list"); cmd.Should().Pass(); cmd.StdOut.Should().Be(CommonLocalizableStrings.NoProjectsFound); } [Theory] - [InlineData("sln")] - [InlineData("solution")] - public void WhenProjectsPresentInTheSolutionItListsThem(string solutionCommand) + [InlineData("sln", ".sln")] + [InlineData("solution", ".sln")] + [InlineData("sln", ".slnx")] + [InlineData("solution", ".slnx")] + public void WhenProjectsPresentInTheSolutionItListsThem(string solutionCommand, string solutionExtension) { var expectedOutput = $@"{CommandLocalizableStrings.ProjectsHeader} {new string('-', CommandLocalizableStrings.ProjectsHeader.Length)} @@ -188,21 +200,23 @@ public void WhenProjectsPresentInTheSolutionItListsThem(string solutionCommand) {Path.Combine("Lib", "Lib.csproj")}"; var projectDirectory = _testAssetsManager - .CopyTestAsset("TestAppWithSlnAndExistingCsprojReferences") + .CopyTestAsset("TestAppWithSlnAndExistingCsprojReferences", identifier: $"GivenDotnetSlnList-{solutionCommand}{solutionExtension}") .WithSource() .Path; var cmd = new DotnetCommand(Log) .WithWorkingDirectory(projectDirectory) - .Execute(solutionCommand, "list"); + .Execute(solutionCommand, $"App{solutionExtension}", "list"); cmd.Should().Pass(); cmd.StdOut.Should().BeVisuallyEquivalentTo(expectedOutput); } [Theory] - [InlineData("sln")] - [InlineData("solution")] - public void WhenProjectsPresentInTheReadonlySolutionItListsThem(string solutionCommand) + [InlineData("sln", ".sln")] + [InlineData("solution", ".sln")] + [InlineData("sln", ".slnx")] + [InlineData("solution", ".slnx")] + public void WhenProjectsPresentInTheReadonlySolutionItListsThem(string solutionCommand, string solutionExtension) { var expectedOutput = $@"{CommandLocalizableStrings.ProjectsHeader} {new string('-', CommandLocalizableStrings.ProjectsHeader.Length)} @@ -210,17 +224,17 @@ public void WhenProjectsPresentInTheReadonlySolutionItListsThem(string solutionC {Path.Combine("Lib", "Lib.csproj")}"; var projectDirectory = _testAssetsManager - .CopyTestAsset("TestAppWithSlnAndExistingCsprojReferences") + .CopyTestAsset("TestAppWithSlnAndExistingCsprojReferences", identifier: $"GivenDotnetSlnList-Readonly-{solutionCommand}{solutionExtension}") .WithSource() .Path; - var slnFileName = Path.Combine(projectDirectory, "App.sln"); + var slnFileName = Path.Combine(projectDirectory, $"App{solutionExtension}"); var attributes = File.GetAttributes(slnFileName); File.SetAttributes(slnFileName, attributes | FileAttributes.ReadOnly); var cmd = new DotnetCommand(Log) .WithWorkingDirectory(projectDirectory) - .Execute(solutionCommand, "list"); + .Execute(solutionCommand, $"App{solutionExtension}", "list"); cmd.Should().Pass(); cmd.StdOut.Should().BeVisuallyEquivalentTo(expectedOutput); } @@ -235,7 +249,7 @@ public void WhenProjectsInSolutionFoldersPresentInTheSolutionItListsSolutionFold $"{Path.Combine("NestedSolution", "NestedFolder", "NestedFolder")}" }; var projectDirectory = _testAssetsManager - .CopyTestAsset("SlnFileWithSolutionItemsInNestedFolders") + .CopyTestAsset("SlnFileWithSolutionItemsInNestedFolders", identifier: $"GivenDotnetSlnList-{solutionCommand}") .WithSource() .Path; diff --git a/test/dotnet-sln.Tests/GivenDotnetSlnMigrate.cs b/test/dotnet-sln.Tests/GivenDotnetSlnMigrate.cs new file mode 100644 index 000000000000..7af7267a2997 --- /dev/null +++ b/test/dotnet-sln.Tests/GivenDotnetSlnMigrate.cs @@ -0,0 +1,37 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.DotNet.Cli.Sln.Internal; +using Microsoft.DotNet.Tools; +using Microsoft.DotNet.Tools.Common; +using CommandLocalizableStrings = Microsoft.DotNet.Tools.Sln.LocalizableStrings; + +namespace Microsoft.DotNet.Cli.Sln.Migrate.Tests +{ + public class GivenDotnetSlnMigrate : SdkTest + { + public GivenDotnetSlnMigrate(ITestOutputHelper log) : base(log) { } + + [Theory] + [InlineData("sln")] + [InlineData("solution")] + public void WhenSlnFileIsValidShouldGenerateValidSlnxFile(string solutionCommand) + { + var projectDirectory = _testAssetsManager + .CopyTestAsset("TestAppWithEmptySln") + .WithSource() + .Path; + var slnFileName = Path.Combine(projectDirectory, "App.sln"); + var slnMigrateCommand = new DotnetCommand(Log) + .WithWorkingDirectory(projectDirectory) + .Execute(solutionCommand, "App.sln", "migrate"); + slnMigrateCommand.Should().Pass(); + + var slnxFileName = Path.ChangeExtension(slnFileName, ".slnx"); + var slnxBuildCommand = new DotnetCommand(Log) + .WithWorkingDirectory(projectDirectory) + .Execute("build", slnxFileName); + slnxBuildCommand.Should().ExitWith(0); + } + } +} diff --git a/test/dotnet-sln.Tests/dotnet-sln.Tests.csproj b/test/dotnet-sln.Tests/dotnet-sln.Tests.csproj index 2dce887f4cfb..ad45aa7b7e6c 100644 --- a/test/dotnet-sln.Tests/dotnet-sln.Tests.csproj +++ b/test/dotnet-sln.Tests/dotnet-sln.Tests.csproj @@ -24,5 +24,9 @@ + + + +