|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.BuildTasks.UnitTests
{
public class GenerateMSBuildEditorConfigTests
{
[Fact]
public void GlobalPropertyIsGeneratedIfEmpty()
{
GenerateMSBuildEditorConfig configTask = new GenerateMSBuildEditorConfig();
configTask.Execute();
var result = configTask.ConfigFileContents;
Assert.Equal(@"is_global = true
", result);
}
[Fact]
public void PropertiesAreGeneratedInGlobalSection()
{
ITaskItem property1 = MSBuildUtil.CreateTaskItem("Property1", new Dictionary<string, string> { { "Value", "abc123" } });
ITaskItem property2 = MSBuildUtil.CreateTaskItem("Property2", new Dictionary<string, string> { { "Value", "def456" } });
GenerateMSBuildEditorConfig configTask = new GenerateMSBuildEditorConfig()
{
PropertyItems = new[] { property1, property2 }
};
configTask.Execute();
var result = configTask.ConfigFileContents;
Assert.Equal(@"is_global = true
build_property.Property1 = abc123
build_property.Property2 = def456
", result);
}
[Fact]
public void ItemMetaDataCreatesSection()
{
ITaskItem item1 = MSBuildUtil.CreateTaskItem("c:/file1.cs", new Dictionary<string, string> { { "ItemType", "Compile" }, { "MetadataName", "ToRetrieve" }, { "ToRetrieve", "abc123" } });
GenerateMSBuildEditorConfig configTask = new GenerateMSBuildEditorConfig()
{
MetadataItems = new[] { item1 }
};
configTask.Execute();
var result = configTask.ConfigFileContents;
Assert.Equal(@"is_global = true
[c:/file1.cs]
build_metadata.Compile.ToRetrieve = abc123
", result);
}
[Fact]
public void MultipleItemMetaDataCreatesSections()
{
ITaskItem item1 = MSBuildUtil.CreateTaskItem("c:/file1.cs", new Dictionary<string, string> { { "ItemType", "Compile" }, { "MetadataName", "ToRetrieve" }, { "ToRetrieve", "abc123" } });
ITaskItem item2 = MSBuildUtil.CreateTaskItem("c:/file2.cs", new Dictionary<string, string> { { "ItemType", "Compile" }, { "MetadataName", "ToRetrieve" }, { "ToRetrieve", "def456" } });
ITaskItem item3 = MSBuildUtil.CreateTaskItem("c:/file3.cs", new Dictionary<string, string> { { "ItemType", "AdditionalFiles" }, { "MetadataName", "ToRetrieve" }, { "ToRetrieve", "ghi789" } });
GenerateMSBuildEditorConfig configTask = new GenerateMSBuildEditorConfig()
{
MetadataItems = new[] { item1, item2, item3 }
};
configTask.Execute();
var result = configTask.ConfigFileContents;
Assert.Equal(@"is_global = true
[c:/file1.cs]
build_metadata.Compile.ToRetrieve = abc123
[c:/file2.cs]
build_metadata.Compile.ToRetrieve = def456
[c:/file3.cs]
build_metadata.AdditionalFiles.ToRetrieve = ghi789
", result);
}
[Fact]
[WorkItem(52469, "https://github.com/dotnet/roslyn/issues/52469")]
public void MultipleSpecialCharacterItemMetaDataCreatesSections()
{
ITaskItem item1 = MSBuildUtil.CreateTaskItem("c:/{f*i?le1}.cs", new Dictionary<string, string> { { "ItemType", "Compile" }, { "MetadataName", "ToRetrieve" }, { "ToRetrieve", "abc123" } });
ITaskItem item2 = MSBuildUtil.CreateTaskItem("c:/f,ile#2.cs", new Dictionary<string, string> { { "ItemType", "Compile" }, { "MetadataName", "ToRetrieve" }, { "ToRetrieve", "def456" } });
ITaskItem item3 = MSBuildUtil.CreateTaskItem("c:/f;i!le[3].cs", new Dictionary<string, string> { { "ItemType", "Compile" }, { "MetadataName", "ToRetrieve" }, { "ToRetrieve", "ghi789" } });
GenerateMSBuildEditorConfig configTask = new GenerateMSBuildEditorConfig()
{
MetadataItems = new[] { item1, item2, item3 }
};
configTask.Execute();
var result = configTask.ConfigFileContents;
Assert.Equal(@"is_global = true
[c:/\{f\*i\?le1\}.cs]
build_metadata.Compile.ToRetrieve = abc123
[c:/f\,ile\#2.cs]
build_metadata.Compile.ToRetrieve = def456
[c:/f\;i\!le\[3\].cs]
build_metadata.Compile.ToRetrieve = ghi789
", result);
}
[Fact]
public void DuplicateItemSpecsAreCombinedInSections()
{
ITaskItem item1 = MSBuildUtil.CreateTaskItem("c:/file1.cs", new Dictionary<string, string> { { "ItemType", "Compile" }, { "MetadataName", "ToRetrieve" }, { "ToRetrieve", "abc123" } });
ITaskItem item2 = MSBuildUtil.CreateTaskItem("c:/file1.cs", new Dictionary<string, string> { { "ItemType", "AdditionalFile" }, { "MetadataName", "ToRetrieve" }, { "ToRetrieve", "def456" } });
GenerateMSBuildEditorConfig configTask = new GenerateMSBuildEditorConfig()
{
MetadataItems = new[] { item1, item2 }
};
configTask.Execute();
var result = configTask.ConfigFileContents;
Assert.Equal(@"is_global = true
[c:/file1.cs]
build_metadata.Compile.ToRetrieve = abc123
build_metadata.AdditionalFile.ToRetrieve = def456
", result);
}
[Fact]
public void ItemIsMissingRequestedMetadata()
{
ITaskItem item1 = MSBuildUtil.CreateTaskItem("c:/file1.cs", new Dictionary<string, string> { { "ItemType", "Compile" }, { "MetadataName", "ToRetrieve" } });
GenerateMSBuildEditorConfig configTask = new GenerateMSBuildEditorConfig()
{
MetadataItems = new[] { item1 }
};
configTask.Execute();
var result = configTask.ConfigFileContents;
Assert.Equal(@"is_global = true
[c:/file1.cs]
build_metadata.Compile.ToRetrieve =
", result);
}
[Fact]
public void ItemIsMissingRequiredMetadata()
{
ITaskItem item1 = MSBuildUtil.CreateTaskItem("c:/file1.cs", new Dictionary<string, string> { });
ITaskItem item2 = MSBuildUtil.CreateTaskItem("c:/file1.cs", new Dictionary<string, string> { { "ItemType", "Compile" } });
ITaskItem item3 = MSBuildUtil.CreateTaskItem("c:/file1.cs", new Dictionary<string, string> { { "MetadataName", "ToRetrieve" } });
GenerateMSBuildEditorConfig configTask = new GenerateMSBuildEditorConfig()
{
MetadataItems = new[] { item1, item2, item3 }
};
configTask.Execute();
var result = configTask.ConfigFileContents;
Assert.Equal(@"is_global = true
[c:/file1.cs]
", result);
}
[Fact]
public void PropertiesAreGeneratedBeforeItems()
{
ITaskItem item1 = MSBuildUtil.CreateTaskItem("c:/file1.cs", new Dictionary<string, string> { { "ItemType", "Compile" }, { "MetadataName", "ToRetrieve" }, { "ToRetrieve", "abc123" } });
ITaskItem item2 = MSBuildUtil.CreateTaskItem("c:/file2.cs", new Dictionary<string, string> { { "ItemType", "Compile" }, { "MetadataName", "ToRetrieve" }, { "ToRetrieve", "def456" } });
ITaskItem item3 = MSBuildUtil.CreateTaskItem("c:/file3.cs", new Dictionary<string, string> { { "ItemType", "AdditionalFiles" }, { "MetadataName", "ToRetrieve" }, { "ToRetrieve", "ghi789" } });
ITaskItem item4 = MSBuildUtil.CreateTaskItem("c:/file1.cs", new Dictionary<string, string> { { "ItemType", "AdditionalFiles" }, { "MetadataName", "ToRetrieve" }, { "ToRetrieve", "jkl012" } });
ITaskItem property1 = MSBuildUtil.CreateTaskItem("Property1", new Dictionary<string, string> { { "Value", "abc123" } });
ITaskItem property2 = MSBuildUtil.CreateTaskItem("Property2", new Dictionary<string, string> { { "Value", "def456" } });
GenerateMSBuildEditorConfig configTask = new GenerateMSBuildEditorConfig()
{
MetadataItems = new[] { item1, item2, item3, item4 },
PropertyItems = new[] { property1, property2 }
};
configTask.Execute();
var result = configTask.ConfigFileContents;
Assert.Equal(@"is_global = true
build_property.Property1 = abc123
build_property.Property2 = def456
[c:/file1.cs]
build_metadata.Compile.ToRetrieve = abc123
build_metadata.AdditionalFiles.ToRetrieve = jkl012
[c:/file2.cs]
build_metadata.Compile.ToRetrieve = def456
[c:/file3.cs]
build_metadata.AdditionalFiles.ToRetrieve = ghi789
", result);
}
[Fact]
public void ItemIsNotFullyQualifiedPath()
{
TaskItem item1 = new TaskItem("file1.cs", new Dictionary<string, string> { { "ItemType", "Compile" }, { "MetadataName", "ToRetrieve" }, { "ToRetrieve", "abc123" } });
TaskItem item2 = new TaskItem("subDir\\file2.cs", new Dictionary<string, string> { { "ItemType", "Compile" }, { "MetadataName", "ToRetrieve" }, { "ToRetrieve", "abc123" } });
TaskItem item3 = new TaskItem("someDir\\otherDir\\thirdDir\\..\\file3.cs", new Dictionary<string, string> { { "ItemType", "Compile" }, { "MetadataName", "ToRetrieve" }, { "ToRetrieve", "abc123" } });
GenerateMSBuildEditorConfig configTask = new GenerateMSBuildEditorConfig()
{
MetadataItems = new[] { item1, item2, item3 }
};
configTask.Execute();
var result = configTask.ConfigFileContents;
// MSBuild will convert the above relative paths to absolute paths based on the current location.
// We replicate that behavior here to test we get the expected full paths
string executingLocation = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)?.Replace('\\', '/') ?? string.Empty;
string expectedPath1 = $"{executingLocation}/file1.cs";
string expectedPath2 = $"{executingLocation}/subDir/file2.cs";
string expectedPath3 = $"{executingLocation}/someDir/otherDir/file3.cs";
Assert.Equal($@"is_global = true
[{expectedPath1}]
build_metadata.Compile.ToRetrieve = abc123
[{expectedPath2}]
build_metadata.Compile.ToRetrieve = abc123
[{expectedPath3}]
build_metadata.Compile.ToRetrieve = abc123
", result);
}
[Fact]
public void ItemsWithDifferentRelativeButSameFullPathAreCombined()
{
TaskItem item1 = new TaskItem("file1.cs", new Dictionary<string, string> { { "ItemType", "Compile" }, { "MetadataName", "ToRetrieve" }, { "ToRetrieve", "abc123" } });
TaskItem item2 = new TaskItem("someDir\\..\\file1.cs", new Dictionary<string, string> { { "ItemType", "AdditionalFile" }, { "MetadataName", "ToRetrieve" }, { "ToRetrieve", "def456" } });
GenerateMSBuildEditorConfig configTask = new GenerateMSBuildEditorConfig()
{
MetadataItems = new[] { item1, item2 }
};
configTask.Execute();
var result = configTask.ConfigFileContents;
// MSBuild will convert the above relative paths to absolute paths based on the current location.
// We replicate that behavior here to test we get the expected full paths
string executingLocation = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)?.Replace('\\', '/') ?? string.Empty;
string expectedPath = $"{executingLocation}/file1.cs";
Assert.Equal($@"is_global = true
[{expectedPath}]
build_metadata.Compile.ToRetrieve = abc123
build_metadata.AdditionalFile.ToRetrieve = def456
", result);
}
[Fact]
[WorkItem(43970, "https://github.com/dotnet/roslyn/issues/43970")]
public void PropertiesWithNewLines()
{
// Currently new lines transfer from MSBuild through to the resulting configuration
// which can break downstream parsing. This tests tracks issue #43970 and should
// be adjusted when we address that.
string longPropertyValue = @"this is
a
property
with
linebreaks
"" quotation "" marks
and
property = looking
values
";
TaskItem property1 = new TaskItem("Property1", new Dictionary<string, string> { { "Value", longPropertyValue } });
TaskItem property2 = new TaskItem("Property2", new Dictionary<string, string> { { "Value", "def456" } });
GenerateMSBuildEditorConfig configTask = new GenerateMSBuildEditorConfig()
{
PropertyItems = new[] { property1, property2 }
};
configTask.Execute();
var result = configTask.ConfigFileContents;
Assert.Equal(@"is_global = true
build_property.Property1 = this is
a
property
with
linebreaks
"" quotation "" marks
and
property = looking
values
build_property.Property2 = def456
", result);
}
[ConditionalFact(typeof(WindowsOnly))]
public void ItemMetadataPathIsAdjustedOnWindows()
{
ITaskItem item1 = MSBuildUtil.CreateTaskItem("c:\\file1.cs", new Dictionary<string, string> { { "ItemType", "Compile" }, { "MetadataName", "ToRetrieve" }, { "ToRetrieve", "abc123" } });
GenerateMSBuildEditorConfig configTask = new GenerateMSBuildEditorConfig()
{
MetadataItems = new[] { item1 }
};
configTask.Execute();
var result = configTask.ConfigFileContents;
Assert.Equal(@"is_global = true
[c:/file1.cs]
build_metadata.Compile.ToRetrieve = abc123
", result);
}
[Fact]
public void ConfigFileCanBeWrittenToDisk()
{
ITaskItem property1 = MSBuildUtil.CreateTaskItem("Property1", new Dictionary<string, string> { { "Value", "abc123" } });
ITaskItem property2 = MSBuildUtil.CreateTaskItem("Property2", new Dictionary<string, string> { { "Value", "def456" } });
var fileName = Path.Combine(TempRoot.Root, "ConfigFileCanBeWrittenToDisk.GenerateMSBuildEditorConfig.editorconfig");
GenerateMSBuildEditorConfig configTask = new GenerateMSBuildEditorConfig()
{
PropertyItems = new[] { property1, property2 },
FileName = new TaskItem(fileName)
};
configTask.Execute();
var expectedContents = @"is_global = true
build_property.Property1 = abc123
build_property.Property2 = def456
";
Assert.True(File.Exists(fileName));
Assert.True(configTask.WriteMSBuildEditorConfig());
Assert.Equal(expectedContents, File.ReadAllText(fileName));
}
}
}
|