// Copyright (c) .NET Foundation and contributors. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; using System.IO; using System.Linq; using Microsoft.Build.Construction; using Microsoft.DotNet.Internal.ProjectModel; using Microsoft.DotNet.Internal.ProjectModel.Files; using Microsoft.DotNet.TestFramework; using Microsoft.DotNet.Tools.Test.Utilities; using NuGet.Frameworks; using Xunit; using FluentAssertions; using Microsoft.DotNet.ProjectJsonMigration.Rules; namespace Microsoft.DotNet.ProjectJsonMigration.Tests { public class GivenThatIWantToMigratePublishOptions : TestBase { [Fact] private void MigratingPublishOptionsForConsoleAppIncludeExcludePopulatesContentItemWithInclude() { var testDirectory = Temp.CreateDirectory().Path; WriteFilesInProjectDirectory(testDirectory); var mockProj = RunPublishOptionsRuleOnPj(@" { ""publishOptions"": { ""include"": [""root"", ""src"", ""rootfile.cs""], ""exclude"": [""src"", ""rootfile.cs""], ""includeFiles"": [""src/file1.cs"", ""src/file2.cs""], ""excludeFiles"": [""src/file2.cs""] } }", testDirectory: testDirectory); mockProj.Items.Count(i => i.ItemType.Equals("None", StringComparison.Ordinal)).Should().Be(4); foreach (var item in mockProj.Items.Where(i => i.ItemType.Equals("None", StringComparison.Ordinal))) { item.Metadata.Count(m => m.Name == "CopyToPublishDirectory").Should().Be(1); if (item.Update.Contains(@"src\file1.cs")) { item.Update.Should().Be(@"src\file1.cs"); item.Exclude.Should().BeEmpty(); item.Metadata.Count(m => m.Name == "CopyToPublishDirectory" && m.Value == "PreserveNewest").Should().Be(1); } else if (item.Update.Contains(@"src\file2.cs")) { item.Update.Should().Be(@"src\file2.cs"); item.Exclude.Should().BeEmpty(); item.Metadata.Count(m => m.Name == "CopyToPublishDirectory" && m.Value == "Never").Should().Be(1); } else if (item.Update.Contains(@"root\**\*")) { item.Update.Should().Be(@"root\**\*"); item.Exclude.Should().BeEmpty(); item.Metadata.Count(m => m.Name == "CopyToPublishDirectory" && m.Value == "PreserveNewest").Should().Be(1); } else { item.Update.Should().Be(@"src\**\*;rootfile.cs"); item.Exclude.Should().BeEmpty(); item.Metadata.Count(m => m.Name == "CopyToPublishDirectory" && m.Value == "Never").Should().Be(1); } } } [Fact] private void MigratingPublishOptionsForWebAppIncludeExcludePopulatesContentItemWithUpdate() { var testDirectory = Temp.CreateDirectory().Path; WriteFilesInProjectDirectory(testDirectory); var mockProj = RunPublishOptionsRuleOnPj(@" { ""publishOptions"": { ""include"": [""root"", ""src"", ""rootfile.cs""], ""exclude"": [""src"", ""rootfile.cs""], ""includeFiles"": [""src/file1.cs"", ""src/file2.cs""], ""excludeFiles"": [""src/file2.cs""] }, ""buildOptions"": { ""emitEntryPoint"": true }, ""dependencies"": { ""Microsoft.AspNetCore.Mvc"" : { ""version"": ""1.0.0"" } }, ""frameworks"": { ""netcoreapp1.0"": {} } }", testDirectory: testDirectory); mockProj.Items.Count(i => i.ItemType.Equals("None", StringComparison.Ordinal)).Should().Be(4); foreach (var item in mockProj.Items.Where(i => i.ItemType.Equals("None", StringComparison.Ordinal))) { item.Metadata.Count(m => m.Name == "CopyToPublishDirectory").Should().Be(1); if (item.Update.Contains(@"src\file1.cs")) { item.Update.Should().Be(@"src\file1.cs"); item.Exclude.Should().BeEmpty(); item.Metadata.Count(m => m.Name == "CopyToPublishDirectory" && m.Value == "PreserveNewest").Should().Be(1); } else if (item.Update.Contains(@"src\file2.cs")) { item.Update.Should().Be(@"src\file2.cs"); item.Exclude.Should().BeEmpty(); item.Metadata.Count(m => m.Name == "CopyToPublishDirectory" && m.Value == "Never").Should().Be(1); } else if (item.Update.Contains(@"root\**\*")) { item.Update.Should().Be(@"root\**\*"); item.Exclude.Should().BeEmpty(); item.Metadata.Count(m => m.Name == "CopyToPublishDirectory" && m.Value == "PreserveNewest").Should().Be(1); } else { item.Update.Should().Be(@"src\**\*;rootfile.cs"); item.Exclude.Should().BeEmpty(); item.Metadata.Count(m => m.Name == "CopyToPublishDirectory" && m.Value == "Never").Should().Be(1); } } } [Fact] private void MigratingConsoleAppWithPublishOptionsAndBuildOptionsCopyToOutputMergesContentItemsWithInclude() { var testDirectory = Temp.CreateDirectory().Path; WriteFilesInProjectDirectory(testDirectory); var mockProj = RunPublishAndBuildOptionsRuleOnPj(@" { ""buildOptions"": { ""copyToOutput"": { ""include"": [""src"", ""rootfile.cs""], ""exclude"": [""src"", ""rootfile.cs""], ""includeFiles"": [""src/file1.cs"", ""src/file2.cs""], ""excludeFiles"": [""src/file2.cs""] } }, ""publishOptions"": { ""include"": [""root"", ""src"", ""rootfile.cs""], ""exclude"": [""src"", ""rootfile.cs""], ""includeFiles"": [""src/file1.cs"", ""src/file2.cs""], ""excludeFiles"": [""src/file3.cs""] } }", testDirectory: testDirectory); mockProj.Items.Count(i => i.ItemType.Equals("None", StringComparison.Ordinal)).Should().Be(5); foreach (var item in mockProj.Items.Where(i => i.ItemType.Equals("None", StringComparison.Ordinal))) { if (item.Update.Contains(@"root\**\*")) { item.Update.Should().Be(@"root\**\*"); item.Metadata.Count(m => m.Name == "CopyToPublishDirectory" && m.Value == "PreserveNewest").Should().Be(1); } else if (item.Update.Contains(@"src\file1.cs")) { item.Update.Should().Be(@"src\file1.cs"); item.Metadata.Count(m => m.Name == "CopyToOutputDirectory" && m.Value == "PreserveNewest").Should().Be(1); item.Metadata.Count(m => m.Name == "CopyToPublishDirectory" && m.Value == "PreserveNewest").Should().Be(1); } else if (item.Update.Contains(@"src\file2.cs")) { item.Update.Should().Be(@"src\file2.cs"); item.Metadata.Count(m => m.Name == "CopyToOutputDirectory" && m.Value == "Never").Should().Be(1); item.Metadata.Count(m => m.Name == "CopyToPublishDirectory" && m.Value == "PreserveNewest").Should().Be(1); } else if (item.Update.Contains(@"src\file3.cs")) { item.Update.Should().Be(@"src\file3.cs"); item.Metadata.Count(m => m.Name == "CopyToPublishDirectory" && m.Value == "Never").Should().Be(1); } else { item.Update.Should() .Be(@"src\**\*;rootfile.cs"); item.Metadata.Count(m => m.Name == "CopyToOutputDirectory" && m.Value == "Never").Should().Be(1); item.Metadata.Count(m => m.Name == "CopyToPublishDirectory" && m.Value == "Never").Should().Be(1); } } } [Fact] private void MigratingWebAppWithPublishOptionsAndBuildOptionsCopyToOutputMergesContentItemsWithUpdate() { var testDirectory = Temp.CreateDirectory().Path; WriteFilesInProjectDirectory(testDirectory); var mockProj = RunPublishAndBuildOptionsRuleOnPj(@" { ""buildOptions"": { ""copyToOutput"": { ""include"": [""src"", ""rootfile.cs""], ""exclude"": [""src"", ""rootfile.cs""], ""includeFiles"": [""src/file1.cs"", ""src/file2.cs""], ""excludeFiles"": [""src/file2.cs""] }, ""emitEntryPoint"": true }, ""publishOptions"": { ""include"": [""root"", ""src"", ""rootfile.cs""], ""exclude"": [""src"", ""rootfile.cs""], ""includeFiles"": [""src/file1.cs"", ""src/file2.cs""], ""excludeFiles"": [""src/file3.cs""] }, ""dependencies"": { ""Microsoft.AspNetCore.Mvc"" : { ""version"": ""1.0.0"" } }, ""frameworks"": { ""netcoreapp1.0"": {} } }", testDirectory: testDirectory); mockProj.Items.Count(i => i.ItemType.Equals("None", StringComparison.Ordinal)).Should().Be(5); // From ProjectReader #L725 (Both are empty) var defaultIncludePatterns = Enumerable.Empty(); var defaultExcludePatterns = Enumerable.Empty(); foreach (var item in mockProj.Items.Where(i => i.ItemType.Equals("None", StringComparison.Ordinal))) { var metadata = string.Join(",", item.Metadata.Select(m => m.Name)); if (item.Update.Contains(@"root\**\*")) { item.Update.Should().Be(@"root\**\*"); item.Exclude.Should().BeEmpty(); item.Metadata.Count(m => m.Name == "CopyToPublishDirectory" && m.Value == "PreserveNewest").Should().Be(1); } else if (item.Update.Contains(@"src\file1.cs")) { item.Update.Should().Be(@"src\file1.cs"); item.Exclude.Should().BeEmpty(); item.Metadata.Count(m => m.Name == "CopyToOutputDirectory" && m.Value == "PreserveNewest").Should().Be(1); item.Metadata.Count(m => m.Name == "CopyToPublishDirectory" && m.Value == "PreserveNewest").Should().Be(1); } else if (item.Update.Contains(@"src\file2.cs")) { item.Update.Should().Be(@"src\file2.cs"); item.Exclude.Should().BeEmpty(); item.Metadata.Count(m => m.Name == "CopyToOutputDirectory" && m.Value == "Never").Should().Be(1); item.Metadata.Count(m => m.Name == "CopyToPublishDirectory" && m.Value == "PreserveNewest").Should().Be(1); } else if (item.Update.Contains(@"src\file3.cs")) { item.Update.Should().Be(@"src\file3.cs"); item.Exclude.Should().BeEmpty(); item.Metadata.Count(m => m.Name == "CopyToPublishDirectory" && m.Value == "Never").Should().Be(1); } else { item.Update.Should().Be(@"src\**\*;rootfile.cs"); item.Exclude.Should().BeEmpty(); item.Metadata.Count(m => m.Name == "CopyToOutputDirectory" && m.Value == "Never").Should().Be(1); item.Metadata.Count(m => m.Name == "CopyToPublishDirectory" && m.Value == "Never").Should().Be(1); } } } [Fact] public void ExcludedPatternsAreNotEmittedOnNoneWhenBuildingAWebProject() { var mockProj = RunPublishOptionsRuleOnPj(@" { ""buildOptions"": { ""emitEntryPoint"": true }, ""publishOptions"": { ""include"": [""wwwroot"", ""**/*.cshtml"", ""appsettings.json"", ""web.config""], }, ""dependencies"": { ""Microsoft.AspNetCore.Mvc"" : { ""version"": ""1.0.0"" } }, ""frameworks"": { ""netcoreapp1.0"": {} } }"); mockProj.Items.Count(i => i.ItemType.Equals("None", StringComparison.Ordinal)).Should().Be(0); } private void WriteFilesInProjectDirectory(string testDirectory) { Directory.CreateDirectory(Path.Combine(testDirectory, "root")); Directory.CreateDirectory(Path.Combine(testDirectory, "src")); File.WriteAllText(Path.Combine(testDirectory, "root", "file1.txt"), "content"); File.WriteAllText(Path.Combine(testDirectory, "root", "file2.txt"), "content"); File.WriteAllText(Path.Combine(testDirectory, "root", "file3.txt"), "content"); File.WriteAllText(Path.Combine(testDirectory, "src", "file1.cs"), "content"); File.WriteAllText(Path.Combine(testDirectory, "src", "file2.cs"), "content"); File.WriteAllText(Path.Combine(testDirectory, "src", "file3.cs"), "content"); File.WriteAllText(Path.Combine(testDirectory, "rootfile.cs"), "content"); } private ProjectRootElement RunPublishOptionsRuleOnPj(string s, string testDirectory = null) { testDirectory = testDirectory ?? Temp.CreateDirectory().Path; return TemporaryProjectFileRuleRunner.RunRules(new IMigrationRule[] { new MigratePublishOptionsRule() }, s, testDirectory); } private ProjectRootElement RunPublishAndBuildOptionsRuleOnPj(string s, string testDirectory = null) { testDirectory = testDirectory ?? Temp.CreateDirectory().Path; return TemporaryProjectFileRuleRunner.RunRules(new IMigrationRule[] { new MigrateBuildOptionsRule(), new MigratePublishOptionsRule() }, s, testDirectory); } } }