diff --git a/src/Cli/dotnet/commands/dotnet-new/PostActions/DotnetSlnPostActionProcessor.cs b/src/Cli/dotnet/commands/dotnet-new/PostActions/DotnetSlnPostActionProcessor.cs index 28143fd21d82..c03937f3723e 100644 --- a/src/Cli/dotnet/commands/dotnet-new/PostActions/DotnetSlnPostActionProcessor.cs +++ b/src/Cli/dotnet/commands/dotnet-new/PostActions/DotnetSlnPostActionProcessor.cs @@ -27,8 +27,11 @@ public DotnetSlnPostActionProcessor(Func, string?, internal static IReadOnlyList FindSolutionFilesAtOrAbovePath(IPhysicalFileSystem fileSystem, string outputBasePath) { - return FileFindHelpers.FindFilesAtOrAbovePath(fileSystem, outputBasePath, "*.sln") - ?? FileFindHelpers.FindFilesAtOrAbovePath(fileSystem, outputBasePath, "*.slnx"); + return + [ + ..FileFindHelpers.FindFilesAtOrAbovePath(fileSystem, outputBasePath, "*.sln"), + ..FileFindHelpers.FindFilesAtOrAbovePath(fileSystem, outputBasePath, "*.slnx") + ]; } // The project files to add are a subset of the primary outputs, specifically the primary outputs indicated by the primaryOutputIndexes post action argument (semicolon separated) diff --git a/test/dotnet.Tests/dotnet-new/DotnetSlnPostActionTests.cs b/test/dotnet.Tests/dotnet-new/DotnetSlnPostActionTests.cs index f32e970ff806..3dc919c05eb2 100644 --- a/test/dotnet.Tests/dotnet-new/DotnetSlnPostActionTests.cs +++ b/test/dotnet.Tests/dotnet-new/DotnetSlnPostActionTests.cs @@ -19,11 +19,13 @@ public DotnetSlnPostActionTests(EnvironmentSettingsHelper environmentSettingsHel _engineEnvironmentSettings = environmentSettingsHelper.CreateEnvironment(hostIdentifier: GetType().Name, virtualize: true); } - [Fact(DisplayName = nameof(AddProjectToSolutionPostActionFindSolutionFileAtOutputPath))] - public void AddProjectToSolutionPostActionFindSolutionFileAtOutputPath() + [Theory] + [InlineData("MySln.sln")] + [InlineData("MySln.slnx")] + public void AddProjectToSolutionPostActionFindSolutionFileAtOutputPath(string solutionFileName) { - string targetBasePath = _engineEnvironmentSettings.GetTempVirtualizedPath(); - string solutionFileFullPath = Path.Combine(targetBasePath, "MySln.sln"); + string targetBasePath = GetVirtualizedRootPath(); + string solutionFileFullPath = Path.Combine(targetBasePath, solutionFileName); _engineEnvironmentSettings.Host.FileSystem.WriteAllText(solutionFileFullPath, string.Empty); IReadOnlyList solutionFiles = DotnetSlnPostActionProcessor.FindSolutionFilesAtOrAbovePath(_engineEnvironmentSettings.Host.FileSystem, targetBasePath); @@ -34,7 +36,7 @@ public void AddProjectToSolutionPostActionFindSolutionFileAtOutputPath() [Fact(DisplayName = nameof(AddProjectToSolutionPostActionFindsOneProjectToAdd))] public void AddProjectToSolutionPostActionFindsOneProjectToAdd() { - string outputBasePath = _engineEnvironmentSettings.GetTempVirtualizedPath(); + string outputBasePath = GetVirtualizedRootPath(); IPostAction postAction = new MockPostAction(default, default, default, default, default!) { ActionId = DotnetSlnPostActionProcessor.ActionProcessorId, @@ -160,14 +162,16 @@ public void AddProjectToSolutionPostActionWithoutPrimaryOutputIndexesWithOutputB Assert.Contains(outputFileFullPath1, foundProjectFiles.ToList()); } - [Fact(DisplayName = nameof(AddProjectToSolutionCanTargetASingleProjectWithAJsonArray))] - public void AddProjectToSolutionCanTargetASingleProjectWithAJsonArray() + [Theory] + [InlineData("MySln.sln")] + [InlineData("MySln.slnx")] + public void AddProjectToSolutionCanTargetASingleProjectWithAJsonArray(string solutionFileName) { var callback = new MockAddProjectToSolutionCallback(); var actionProcessor = new DotnetSlnPostActionProcessor(callback.AddProjectToSolution); - string targetBasePath = _engineEnvironmentSettings.GetTempVirtualizedPath(); - string slnFileFullPath = Path.Combine(targetBasePath, "MyApp.sln"); + string targetBasePath = GetVirtualizedRootPath(); + string slnFileFullPath = Path.Combine(targetBasePath, solutionFileName); string projFileFullPath = Path.Combine(targetBasePath, "MyApp.csproj"); _engineEnvironmentSettings.Host.FileSystem.WriteAllText(slnFileFullPath, ""); @@ -189,14 +193,16 @@ public void AddProjectToSolutionCanTargetASingleProjectWithAJsonArray() Assert.Equal(slnFileFullPath, callback.Solution); } - [Fact(DisplayName = nameof(AddProjectToSolutionCanTargetASingleProjectWithTheProjectName))] - public void AddProjectToSolutionCanTargetASingleProjectWithTheProjectName() + [Theory] + [InlineData("MySln.sln")] + [InlineData("MySln.slnx")] + public void AddProjectToSolutionCanTargetASingleProjectWithTheProjectName(string solutionFileName) { var callback = new MockAddProjectToSolutionCallback(); var actionProcessor = new DotnetSlnPostActionProcessor(callback.AddProjectToSolution); - string targetBasePath = _engineEnvironmentSettings.GetTempVirtualizedPath(); - string slnFileFullPath = Path.Combine(targetBasePath, "MyApp.sln"); + string targetBasePath = GetVirtualizedRootPath(); + string slnFileFullPath = Path.Combine(targetBasePath, solutionFileName); string projFileFullPath = Path.Combine(targetBasePath, "MyApp.csproj"); _engineEnvironmentSettings.Host.FileSystem.WriteAllText(slnFileFullPath, ""); @@ -218,14 +224,16 @@ public void AddProjectToSolutionCanTargetASingleProjectWithTheProjectName() Assert.Equal(slnFileFullPath, callback.Solution); } - [Fact(DisplayName = nameof(AddProjectToSolutionCanPlaceProjectInSolutionRoot))] - public void AddProjectToSolutionCanPlaceProjectInSolutionRoot() + [Theory] + [InlineData("MySln.sln")] + [InlineData("MySln.slnx")] + public void AddProjectToSolutionCanPlaceProjectInSolutionRoot(string solutionFileName) { var callback = new MockAddProjectToSolutionCallback(); var actionProcessor = new DotnetSlnPostActionProcessor(callback.AddProjectToSolution); - string targetBasePath = _engineEnvironmentSettings.GetTempVirtualizedPath(); - string slnFileFullPath = Path.Combine(targetBasePath, "MyApp.sln"); + string targetBasePath = GetVirtualizedRootPath(); + string slnFileFullPath = Path.Combine(targetBasePath, solutionFileName); string projFileFullPath = Path.Combine(targetBasePath, "MyApp.csproj"); _engineEnvironmentSettings.Host.FileSystem.WriteAllText(slnFileFullPath, ""); @@ -250,14 +258,16 @@ public void AddProjectToSolutionCanPlaceProjectInSolutionRoot() Assert.Null(callback.TargetFolder); } - [Fact] - public void AddProjectToSolutionCanPlaceProjectInSolutionFolder() + [Theory] + [InlineData("MySln.sln")] + [InlineData("MySln.slnx")] + public void AddProjectToSolutionCanPlaceProjectInSolutionFolder(string solutionFileName) { var callback = new MockAddProjectToSolutionCallback(); var actionProcessor = new DotnetSlnPostActionProcessor(callback.AddProjectToSolution); - string targetBasePath = _engineEnvironmentSettings.GetTempVirtualizedPath(); - string slnFileFullPath = Path.Combine(targetBasePath, "MyApp.sln"); + string targetBasePath = GetVirtualizedRootPath(); + string slnFileFullPath = Path.Combine(targetBasePath, solutionFileName); string projFileFullPath = Path.Combine(targetBasePath, "MyApp.csproj"); _engineEnvironmentSettings.Host.FileSystem.WriteAllText(slnFileFullPath, ""); @@ -282,14 +292,16 @@ public void AddProjectToSolutionCanPlaceProjectInSolutionFolder() Assert.Equal("src", callback.TargetFolder); } - [Fact] - public void AddProjectToSolutionFailsWhenSolutionFolderAndInRootSpecified() + [Theory] + [InlineData("MySln.sln")] + [InlineData("MySln.slnx")] + public void AddProjectToSolutionFailsWhenSolutionFolderAndInRootSpecified(string solutionFileName) { var callback = new MockAddProjectToSolutionCallback(); var actionProcessor = new DotnetSlnPostActionProcessor(callback.AddProjectToSolution); - string targetBasePath = _engineEnvironmentSettings.GetTempVirtualizedPath(); - string slnFileFullPath = Path.Combine(targetBasePath, "MyApp.sln"); + string targetBasePath = GetVirtualizedRootPath(); + string slnFileFullPath = Path.Combine(targetBasePath, solutionFileName); string projFileFullPath = Path.Combine(targetBasePath, "MyApp.csproj"); _engineEnvironmentSettings.Host.FileSystem.WriteAllText(slnFileFullPath, ""); @@ -314,6 +326,21 @@ public void AddProjectToSolutionFailsWhenSolutionFolderAndInRootSpecified() Assert.False(result); } + /// + /// Creates a virtualized path at the root. + /// This is used to test the behavior of finding *.slnx files after failing to find *.sln files. + /// + /// If the root is not virtualized, tests will fail because the "FindFilesAtOrAbovePath" method + /// will run into a non-virtualized directory and fail due to it not existing within the "virtual cone". + /// + /// The root path virtualized + private string GetVirtualizedRootPath() + { + var root = Path.GetPathRoot(Directory.GetCurrentDirectory())!; + _engineEnvironmentSettings.Host.VirtualizeDirectory(root); + return Path.Combine(Directory.GetCurrentDirectory(), "sandbox", Guid.NewGuid().ToString()) + Path.DirectorySeparatorChar; + } + private class MockAddProjectToSolutionCallback { public string? Solution { get; private set; }