|
// 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;
using System.Xml;
using Microsoft.Build.Framework;
using Microsoft.Build.Tasks;
using Microsoft.Build.Utilities;
using Xunit;
using Xunit.Abstractions;
#nullable disable
namespace Microsoft.Build.UnitTests
{
/// <summary>
/// Most of the common ResolveNonMSBuildOutput/AssignProjectConfiguration functionality is tested
/// in ResolveNonMSBuildProjectOutput_Tests.
/// Here, only test the AssignProjectConfiguration specific code
/// </summary>
public sealed class AssignProjectConfiguration_Tests
{
private readonly ITestOutputHelper _output;
public AssignProjectConfiguration_Tests(ITestOutputHelper output)
{
_output = output;
}
private void TestResolveHelper(string itemSpec, string projectGuid, string package, string name,
Hashtable pregenConfigurations, bool expectedResult,
string expectedFullConfiguration, string expectedConfiguration, string expectedPlatform)
{
ITaskItem reference = ResolveNonMSBuildProjectOutput_Tests.CreateReferenceItem(itemSpec, projectGuid, package, name);
// Use the XML string generation method from our sister class - XML element names will be different,
// but they are ignored anyway, and the rest is identical
string xmlString = ResolveNonMSBuildProjectOutput_Tests.CreatePregeneratedPathDoc(pregenConfigurations);
ITaskItem resolvedProjectWithConfiguration;
AssignProjectConfiguration rpc = new AssignProjectConfiguration();
rpc.SolutionConfigurationContents = xmlString;
rpc.CacheProjectElementsFromXml(xmlString);
bool result = rpc.ResolveProject(reference, out resolvedProjectWithConfiguration);
string message = string.Format("Reference \"{0}\" [project \"{1}\", package \"{2}\", name \"{3}\"] Pregen Xml string : \"{4}\"" +
"expected result \"{5}\", actual result \"{6}\", expected configuration \"{7}\", actual configuration \"{8}\".",
itemSpec, projectGuid, package, name, xmlString, expectedResult, result, expectedFullConfiguration,
(resolvedProjectWithConfiguration == null) ? string.Empty : resolvedProjectWithConfiguration.GetMetadata("FullConfiguration"));
Assert.Equal(expectedResult, result);
if (result)
{
Assert.Equal(expectedFullConfiguration, resolvedProjectWithConfiguration.GetMetadata("FullConfiguration"));
Assert.Equal(expectedConfiguration, resolvedProjectWithConfiguration.GetMetadata("Configuration"));
Assert.Equal(expectedPlatform, resolvedProjectWithConfiguration.GetMetadata("Platform"));
Assert.Equal("Configuration=" + expectedConfiguration, resolvedProjectWithConfiguration.GetMetadata("SetConfiguration"));
Assert.Equal("Platform=" + expectedPlatform, resolvedProjectWithConfiguration.GetMetadata("SetPlatform"));
Assert.Equal(reference.ItemSpec, resolvedProjectWithConfiguration.ItemSpec);
}
else
{
Assert.Null(resolvedProjectWithConfiguration);
}
}
[Fact]
public void TestResolve()
{
// empty pre-generated string
Hashtable projectOutputs = new Hashtable();
TestResolveHelper("MCDep1.vcproj", "{2F6BBCC3-7111-4116-A68B-34CFC76F37C5}", "{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}", "MCDep1",
projectOutputs, false, null, null, null);
// non matching project in string
projectOutputs = new Hashtable();
projectOutputs.Add("{11111111-1111-1111-1111-111111111111}", @"Debug|Win32");
TestResolveHelper("MCDep1.vcproj", "{2F6BBCC3-7111-4116-A68B-34CFC76F37C5}", "{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}", "MCDep1",
projectOutputs, false, null, null, null);
// matching projects in string
projectOutputs = new Hashtable();
projectOutputs.Add("{2F6BBCC3-7111-4116-A68B-34CFC76F37C5}", @"Debug|Win32");
projectOutputs.Add("{2F6BBCC3-7111-4116-A68B-666666666666}", @"Debug");
TestResolveHelper("MCDep1.vcproj", "{2F6BBCC3-7111-4116-A68B-34CFC76F37C5}", "{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}", "MCDep1",
projectOutputs, true, @"Debug|Win32", "Debug", "Win32");
TestResolveHelper("MCDep2.vcproj", "{2F6BBCC3-7111-4116-A68B-666666666666}", "{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}", "MCDep1",
projectOutputs, true, @"Debug", "Debug", string.Empty);
// multiple non matching projects in string
projectOutputs = new Hashtable();
projectOutputs.Add("{11111111-1111-1111-1111-111111111111}", @"Config1|Win32");
projectOutputs.Add("{11111111-1111-1111-1111-111111111112}", @"Config2|AnyCPU");
projectOutputs.Add("{11111111-1111-1111-1111-111111111113}", @"Config3|AnyCPU");
TestResolveHelper("MCDep1.vcproj", "{2F6BBCC3-7111-4116-A68B-34CFC76F37C5}", "{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}", "MCDep1",
projectOutputs, false, null, null, null);
// multiple non matching projects in string, two matching
projectOutputs = new Hashtable();
projectOutputs.Add("{11111111-1111-1111-1111-111111111111}", @"Config1|Win32");
projectOutputs.Add("{11111111-1111-1111-1111-111111111112}", @"Config2|AnyCPU");
projectOutputs.Add("{11111111-1111-1111-1111-111111111113}", @"Config3|AnyCPU");
projectOutputs.Add("{2F6BBCC3-7111-4116-A68B-34CFC76F37C5}", @"CorrectProjectConfig|Platform");
projectOutputs.Add("{2F6BBCC3-7111-4116-A68B-666666666666}", @"JustConfig");
TestResolveHelper("MCDep1.vcproj", "{2F6BBCC3-7111-4116-A68B-34CFC76F37C5}", "{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}", "MCDep1",
projectOutputs, true, @"CorrectProjectConfig|Platform", "CorrectProjectConfig", "Platform");
TestResolveHelper("MCDep2.vcproj", "{2F6BBCC3-7111-4116-A68B-666666666666}", "{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}", "MCDep1",
projectOutputs, true, @"JustConfig", "JustConfig", string.Empty);
}
/// <summary>
/// Test the case where the project reference does not have either of the metadata set on it.
///
/// We would expect the following case:
///
/// 1) The xml element does not have the BuildProjectInSolution attribute set
/// Expect none of the metadata to be set
/// </summary>
[Fact]
public void TestReferenceWithNoMetadataBadBuildInProjectAttribute()
{
// Test the case where the metadata is missing and we are not supposed to build the reference
ITaskItem referenceItem = new TaskItem("TestItem");
XmlDocument doc = new XmlDocument();
XmlElement element = doc.CreateElement("TestElement");
element.SetAttribute("BuildProjectInSolution", "IAmReallyABadOne");
AssignProjectConfiguration.SetBuildInProjectAndReferenceOutputAssemblyMetadata(true, referenceItem, element);
Assert.Empty(referenceItem.GetMetadata("BuildReference"));
Assert.Empty(referenceItem.GetMetadata("ReferenceOutputAssembly"));
}
/// <summary>
/// Test the case where the project reference does not have either of the metadata set on it.
///
/// We would expect the following case:
///
/// 1) The xml element does not have the BuildProjectInSolution attribute set
/// Expect none of the metadata to be set
/// </summary>
[Fact]
public void TestReferenceWithNoMetadataNoBuildInProjectAttribute()
{
// Test the case where the metadata is missing and we are not supposed to build the reference
ITaskItem referenceItem = new TaskItem("TestItem");
XmlDocument doc = new XmlDocument();
XmlElement element = doc.CreateElement("TestElement");
AssignProjectConfiguration.SetBuildInProjectAndReferenceOutputAssemblyMetadata(true, referenceItem, element);
Assert.Empty(referenceItem.GetMetadata("BuildReference"));
Assert.Empty(referenceItem.GetMetadata("ReferenceOutputAssembly"));
}
/// <summary>
/// Test the case where the project reference does not have either of the metadata set on it.
///
/// We would expect the following case:
/// 1) The xml element has BuildProjectInSolution set to true
/// Expect none of the metadata to be set
/// </summary>
[Fact]
public void TestReferenceWithNoMetadataBuildInProjectAttributeTrue()
{
// Test the case where the metadata is missing and we are not supposed to build the reference
ITaskItem referenceItem = new TaskItem("TestItem");
XmlDocument doc = new XmlDocument();
XmlElement element = doc.CreateElement("TestElement");
element.SetAttribute("BuildProjectInSolution", "true");
AssignProjectConfiguration.SetBuildInProjectAndReferenceOutputAssemblyMetadata(true, referenceItem, element);
Assert.Empty(referenceItem.GetMetadata("BuildReference"));
Assert.Empty(referenceItem.GetMetadata("ReferenceOutputAssembly"));
}
/// <summary>
/// Test the case where the project reference does not have either of the metadata set on it.
///
/// We would expect the following case:
/// ReferenceAndBuildProjectsDisabledInProjectConfiguration is set to true meaning we want to build disabled projects.
///
/// 1) The xml element has BuildProjectInSolution set to false
/// Expect no pieces of metadata to be set on the reference item
/// </summary>
[Fact]
public void TestReferenceWithNoMetadataBuildInProjectAttributeFalseReferenceAndBuildProjectsDisabledInProjectConfiguration()
{
// Test the case where the metadata is missing and we are not supposed to build the reference
ITaskItem referenceItem = new TaskItem("TestItem");
XmlDocument doc = new XmlDocument();
XmlElement element = doc.CreateElement("TestElement");
element.SetAttribute("BuildProjectInSolution", "false");
AssignProjectConfiguration.SetBuildInProjectAndReferenceOutputAssemblyMetadata(false, referenceItem, element);
Assert.Empty(referenceItem.GetMetadata("BuildReference"));
Assert.Empty(referenceItem.GetMetadata("ReferenceOutputAssembly"));
}
/// <summary>
/// Test the case where the project reference does not have either of the metadata set on it.
///
/// We would expect the following case:
/// 1) The xml element has BuildProjectInSolution set to false
/// Expect two pieces of metadata to be put on the item and be set to false (BuildReference, and ReferenceOutputAssembly)
/// </summary>
[Fact]
public void TestReferenceWithNoMetadataBuildInProjectAttributeFalse()
{
// Test the case where the metadata is missing and we are not supposed to build the reference
ITaskItem referenceItem = new TaskItem("TestItem");
XmlDocument doc = new XmlDocument();
XmlElement element = doc.CreateElement("TestElement");
element.SetAttribute("BuildProjectInSolution", "false");
AssignProjectConfiguration.SetBuildInProjectAndReferenceOutputAssemblyMetadata(true, referenceItem, element);
Assert.Equal("false", referenceItem.GetMetadata("BuildReference"));
Assert.Equal("false", referenceItem.GetMetadata("ReferenceOutputAssembly"));
}
/// <summary>
/// Test the case where the project reference does has one or more of the metadata set on it.
///
/// We would expect the following case:
/// 1) The xml element has BuildProjectInSolution set to false
/// Expect two pieces of metadata to be put on the item and be set to true since they were already set (BuildReference, and ReferenceOutputAssembly)
/// </summary>
[Fact]
public void TestReferenceWithMetadataAlreadySetBuildInProjectAttributeFalse()
{
// Test the case where the metadata is missing and we are not supposed to build the reference
ITaskItem referenceItem = new TaskItem("TestItem");
referenceItem.SetMetadata("BuildReference", "true");
referenceItem.SetMetadata("ReferenceOutputAssembly", "true");
XmlDocument doc = new XmlDocument();
XmlElement element = doc.CreateElement("TestElement");
element.SetAttribute("BuildProjectInSolution", "false");
AssignProjectConfiguration.SetBuildInProjectAndReferenceOutputAssemblyMetadata(true, referenceItem, element);
Assert.Equal("true", referenceItem.GetMetadata("BuildReference"));
Assert.Equal("true", referenceItem.GetMetadata("ReferenceOutputAssembly"));
// Test the case where only ReferenceOutputAssembly is not set
referenceItem = new TaskItem("TestItem");
referenceItem.SetMetadata("BuildReference", "true");
doc = new XmlDocument();
element = doc.CreateElement("TestElement");
element.SetAttribute("BuildProjectInSolution", "false");
AssignProjectConfiguration.SetBuildInProjectAndReferenceOutputAssemblyMetadata(true, referenceItem, element);
Assert.Equal("true", referenceItem.GetMetadata("BuildReference"));
Assert.Equal("false", referenceItem.GetMetadata("ReferenceOutputAssembly"));
// Test the case where only BuildReference is not set
referenceItem = new TaskItem("TestItem");
referenceItem.SetMetadata("ReferenceOutputAssembly", "true");
doc = new XmlDocument();
element = doc.CreateElement("TestElement");
element.SetAttribute("BuildProjectInSolution", "false");
AssignProjectConfiguration.SetBuildInProjectAndReferenceOutputAssemblyMetadata(true, referenceItem, element);
Assert.Equal("false", referenceItem.GetMetadata("BuildReference"));
Assert.Equal("true", referenceItem.GetMetadata("ReferenceOutputAssembly"));
}
private void TestUnresolvedReferencesHelper(ArrayList projectRefs, Hashtable pregenConfigurations,
out Hashtable unresolvedProjects, out Hashtable resolvedProjects)
{
// Use the XML string generation method from our sister class - XML element names will be different,
// but they are ignored anyway, and the rest is identical
string xmlString = ResolveNonMSBuildProjectOutput_Tests.CreatePregeneratedPathDoc(pregenConfigurations);
MockEngine engine = new MockEngine(_output);
AssignProjectConfiguration rpc = new AssignProjectConfiguration();
rpc.BuildEngine = engine;
rpc.SolutionConfigurationContents = xmlString;
rpc.ProjectReferences = (ITaskItem[])projectRefs.ToArray(typeof(ITaskItem));
bool result = rpc.Execute();
unresolvedProjects = new Hashtable();
for (int i = 0; i < rpc.UnassignedProjects.Length; i++)
{
unresolvedProjects[rpc.UnassignedProjects[i].ItemSpec] = rpc.UnassignedProjects[i];
}
resolvedProjects = new Hashtable();
for (int i = 0; i < rpc.AssignedProjects.Length; i++)
{
resolvedProjects[rpc.AssignedProjects[i].GetMetadata("FullConfiguration")] = rpc.AssignedProjects[i];
}
}
/// <summary>
/// Verifies that the UnresolvedProjectReferences output parameter is populated correctly.
/// </summary>
[Fact]
public void TestUnresolvedReferences()
{
ArrayList projectRefs = new ArrayList();
projectRefs.Add(ResolveNonMSBuildProjectOutput_Tests.CreateReferenceItem("MCDep1.vcproj", "{2F6BBCC3-7111-4116-A68B-000000000000}",
"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}", "MCDep1"));
projectRefs.Add(ResolveNonMSBuildProjectOutput_Tests.CreateReferenceItem("MCDep2.vcproj", "{2F6BBCC3-7111-4116-A68B-34CFC76F37C5}",
"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}", "MCDep2"));
// 1. multiple projects, none resolvable
Hashtable projectConfigurations = new Hashtable();
projectConfigurations.Add("{11111111-1111-1111-1111-111111111111}", @"Config1|Win32");
projectConfigurations.Add("{11111111-1111-1111-1111-111111111112}", @"Config2|AnyCPU");
projectConfigurations.Add("{11111111-1111-1111-1111-111111111113}", @"Config3|AnyCPU");
Hashtable unresolvedProjects;
Hashtable resolvedProjects;
TestUnresolvedReferencesHelper(projectRefs, projectConfigurations, out unresolvedProjects, out resolvedProjects);
Assert.Empty(resolvedProjects); // "No resolved refs expected for case 1"
Assert.Equal(2, unresolvedProjects.Count); // "Two unresolved refs expected for case 1"
Assert.Equal(unresolvedProjects["MCDep1.vcproj"], projectRefs[0]);
Assert.Equal(unresolvedProjects["MCDep2.vcproj"], projectRefs[1]);
// 2. multiple projects, one resolvable
projectConfigurations = new Hashtable();
projectConfigurations.Add("{11111111-1111-1111-1111-111111111111}", @"Config1|Win32");
projectConfigurations.Add("{11111111-1111-1111-1111-111111111112}", @"Config2|AnyCPU");
projectConfigurations.Add("{11111111-1111-1111-1111-111111111113}", @"Config3|AnyCPU");
projectConfigurations.Add("{2F6BBCC3-7111-4116-A68B-34CFC76F37C5}", @"CorrectProjectConfig|Platform");
TestUnresolvedReferencesHelper(projectRefs, projectConfigurations, out unresolvedProjects, out resolvedProjects);
Assert.Single(resolvedProjects); // "One resolved ref expected for case 2"
Assert.True(resolvedProjects.ContainsKey(@"CorrectProjectConfig|Platform"));
Assert.Single(unresolvedProjects); // "One unresolved ref expected for case 2"
Assert.Equal(unresolvedProjects["MCDep1.vcproj"], projectRefs[0]);
// 3. multiple projects, all resolvable
projectConfigurations = new Hashtable();
projectConfigurations.Add("{11111111-1111-1111-1111-111111111111}", @"Config1|Win32");
projectConfigurations.Add("{11111111-1111-1111-1111-111111111112}", @"Config2|AnyCPU");
projectConfigurations.Add("{11111111-1111-1111-1111-111111111113}", @"Config3|AnyCPU");
projectConfigurations.Add("{2F6BBCC3-7111-4116-A68B-34CFC76F37C5}", @"CorrectProjectConfig|Platform");
projectConfigurations.Add("{2F6BBCC3-7111-4116-A68B-000000000000}", @"CorrectProjectConfig2|Platform");
TestUnresolvedReferencesHelper(projectRefs, projectConfigurations, out unresolvedProjects, out resolvedProjects);
Assert.Equal(2, resolvedProjects.Count); // "Two resolved refs expected for case 3"
Assert.True(resolvedProjects.ContainsKey(@"CorrectProjectConfig|Platform"));
Assert.True(resolvedProjects.ContainsKey(@"CorrectProjectConfig2|Platform"));
Assert.Empty(unresolvedProjects); // "No unresolved refs expected for case 3"
}
#region Test Defaults
/// <summary>
/// Verify if no values are passed in for certain properties that their default values are used.
/// </summary>
[Fact]
public void VerifyDefaultValueDefaultToVcxPlatformMappings()
{
string expectedDefaultToVcxPlatformMapping = "AnyCPU=Win32;X86=Win32;X64=X64;Itanium=Itanium";
AssignProjectConfiguration assignProjectConfiguration = new AssignProjectConfiguration();
// Test defaults with nothing set
string actualDefaultToVcxPlatformMapping = assignProjectConfiguration.DefaultToVcxPlatformMapping;
Assert.Equal(actualDefaultToVcxPlatformMapping, expectedDefaultToVcxPlatformMapping);
assignProjectConfiguration.DefaultToVcxPlatformMapping = String.Empty;
actualDefaultToVcxPlatformMapping = assignProjectConfiguration.DefaultToVcxPlatformMapping;
Assert.Equal(actualDefaultToVcxPlatformMapping, expectedDefaultToVcxPlatformMapping);
assignProjectConfiguration.DefaultToVcxPlatformMapping = null;
actualDefaultToVcxPlatformMapping = assignProjectConfiguration.DefaultToVcxPlatformMapping;
Assert.Equal(actualDefaultToVcxPlatformMapping, expectedDefaultToVcxPlatformMapping);
}
/// <summary>
/// Verify if no values are passed in for certain properties that their default values are used.
/// </summary>
[Fact]
public void VerifyDefaultValuesVcxToDefaultPlatformMappingNoOutput()
{
string expectedVcxToDefaultPlatformMappingNoOutput = "Win32=X86;X64=X64;Itanium=Itanium";
AssignProjectConfiguration assignProjectConfiguration = new AssignProjectConfiguration();
// Test the case for VcxToDefaultPlatformMapping when the outputType is not library
string actualVcxToDefaultPlatformMappingNoOutput = assignProjectConfiguration.VcxToDefaultPlatformMapping;
Assert.Equal(actualVcxToDefaultPlatformMappingNoOutput, expectedVcxToDefaultPlatformMappingNoOutput);
assignProjectConfiguration.VcxToDefaultPlatformMapping = String.Empty;
actualVcxToDefaultPlatformMappingNoOutput = assignProjectConfiguration.VcxToDefaultPlatformMapping;
Assert.Equal(actualVcxToDefaultPlatformMappingNoOutput, expectedVcxToDefaultPlatformMappingNoOutput);
assignProjectConfiguration.VcxToDefaultPlatformMapping = null;
actualVcxToDefaultPlatformMappingNoOutput = assignProjectConfiguration.VcxToDefaultPlatformMapping;
Assert.Equal(actualVcxToDefaultPlatformMappingNoOutput, expectedVcxToDefaultPlatformMappingNoOutput);
}
/// <summary>
/// Verify if no values are passed in for certain properties that their default values are used.
/// </summary>
[Fact]
public void VerifyDefaultValuesVcxToDefaultPlatformMappingLibraryOutput()
{
string expectedVcxToDefaultPlatformMappingLibraryOutput = "Win32=AnyCPU;X64=X64;Itanium=Itanium";
AssignProjectConfiguration assignProjectConfiguration = new AssignProjectConfiguration();
// Test the case for VcxToDefaultPlatformMapping when the outputType is library
assignProjectConfiguration.OutputType = "Library";
string actualVcxToDefaultPlatformMappingNoOutput = assignProjectConfiguration.VcxToDefaultPlatformMapping;
Assert.Equal(actualVcxToDefaultPlatformMappingNoOutput, expectedVcxToDefaultPlatformMappingLibraryOutput);
assignProjectConfiguration.VcxToDefaultPlatformMapping = String.Empty;
actualVcxToDefaultPlatformMappingNoOutput = assignProjectConfiguration.VcxToDefaultPlatformMapping;
Assert.Equal(actualVcxToDefaultPlatformMappingNoOutput, expectedVcxToDefaultPlatformMappingLibraryOutput);
assignProjectConfiguration.VcxToDefaultPlatformMapping = null;
actualVcxToDefaultPlatformMappingNoOutput = assignProjectConfiguration.VcxToDefaultPlatformMapping;
Assert.Equal(actualVcxToDefaultPlatformMappingNoOutput, expectedVcxToDefaultPlatformMappingLibraryOutput);
}
#endregion
}
}
|