Skip to content

Commit

Permalink
Merge branch 'vs15.3-preview' into merge15.3IntoMaster
Browse files Browse the repository at this point in the history
 Conflicts:
	src/Build.OM.UnitTests/Construction/ProjectSdkImplicitImport_Tests.cs
	version.json
  • Loading branch information
cdmihai committed May 12, 2017
2 parents 2a2ceca + 3c9ab94 commit 6b0ddfc
Show file tree
Hide file tree
Showing 8 changed files with 217 additions and 99 deletions.
2 changes: 2 additions & 0 deletions ref/net46/Microsoft.Build/Microsoft.Build.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,12 @@ public partial class ProjectImportElement : Microsoft.Build.Construction.Project
{
internal ProjectImportElement() { }
public Microsoft.Build.Construction.ImplicitImportLocation ImplicitImportLocation { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
public string MinimumVersion { get { throw null; } set { } }
public string Project { get { throw null; } set { } }
public Microsoft.Build.Construction.ElementLocation ProjectLocation { get { throw null; } }
public string Sdk { get { throw null; } set { } }
public Microsoft.Build.Construction.ElementLocation SdkLocation { get { throw null; } }
public string Version { get { throw null; } set { } }
protected override Microsoft.Build.Construction.ProjectElement CreateNewInstance(Microsoft.Build.Construction.ProjectRootElement owner) { throw null; }
}
[System.Diagnostics.DebuggerDisplayAttribute("#Imports={Count} Condition={Condition} Label={Label}")]
Expand Down
2 changes: 2 additions & 0 deletions ref/netstandard1.3/Microsoft.Build/Microsoft.Build.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,12 @@ public partial class ProjectImportElement : Microsoft.Build.Construction.Project
{
internal ProjectImportElement() { }
public Microsoft.Build.Construction.ImplicitImportLocation ImplicitImportLocation { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
public string MinimumVersion { get { throw null; } set { } }
public string Project { get { throw null; } set { } }
public Microsoft.Build.Construction.ElementLocation ProjectLocation { get { throw null; } }
public string Sdk { get { throw null; } set { } }
public Microsoft.Build.Construction.ElementLocation SdkLocation { get { throw null; } }
public string Version { get { throw null; } set { } }
protected override Microsoft.Build.Construction.ProjectElement CreateNewInstance(Microsoft.Build.Construction.ProjectRootElement owner) { throw null; }
}
[System.Diagnostics.DebuggerDisplayAttribute("#Imports={Count} Condition={Condition} Label={Label}")]
Expand Down
36 changes: 36 additions & 0 deletions src/Build.OM.UnitTests/Construction/ConstructionEditing_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
using Microsoft.Build.Construction;
using Microsoft.Build.Engine.UnitTests;
using Microsoft.Build.Evaluation;
using Microsoft.Build.Framework;
using Microsoft.Build.Shared;

using InvalidProjectFileException = Microsoft.Build.Exceptions.InvalidProjectFileException;
Expand Down Expand Up @@ -3244,6 +3245,30 @@ public void AddProperty_WithSdk_KeepsSdkAndImplicitImports()
}
}

public void UpdateSdkImportProperty()
{
ProjectRootElement project = ProjectRootElement.Create();
ProjectImportElement import = project.AddImport("file");

// Add properties and assert that the SdkReference is updated accordingly.
import.Sdk = "Name";
AssertSdkEquals(import, "Name", null, null);

import.Version = "Version";
AssertSdkEquals(import, "Name", "Version", null);

import.MinimumVersion = "Min";
AssertSdkEquals(import, "Name", "Version", "Min");

import.MinimumVersion = null;
AssertSdkEquals(import, "Name", "Version", null);

import.Version = null;
AssertSdkEquals(import, "Name", "Version", null);

Assert.Throws<ArgumentException>(() => import.Sdk = null);
}

private static string AdjustSpacesForItem(string expectedItem)
{
Assert.False(string.IsNullOrEmpty(expectedItem));
Expand Down Expand Up @@ -3277,5 +3302,16 @@ private static string AdjustSpacesForItem(string expectedItem)
expectedItem = sb.ToString();
return expectedItem;
}

private void AssertSdkEquals(ProjectImportElement importElement, string name, string version, string minimumVersion)
{
// Use reflection to verify the value. The property is not public and we do not have InternalsVisibleTo (by design).
PropertyInfo pi = importElement.GetType().GetProperty("ParsedSdkReference");

var expected = new SdkReference(name, version, minimumVersion);
var actual = (SdkReference) pi.GetValue(importElement);

Assert.Equal(expected, actual);
}
}
}
183 changes: 92 additions & 91 deletions src/Build.OM.UnitTests/Construction/ProjectSdkImplicitImport_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
using Microsoft.Build.Engine.UnitTests;
using Microsoft.Build.Evaluation;
using Microsoft.Build.Exceptions;
using Microsoft.Build.Shared;
using Xunit;

namespace Microsoft.Build.UnitTests.OM.Construction
Expand All @@ -21,6 +20,24 @@ namespace Microsoft.Build.UnitTests.OM.Construction
/// </summary>
public class ProjectSdkImplicitImport_Tests : IDisposable
{
private const string ProjectTemplateSdkAsAttribute = @"
<Project Sdk=""{0}"">
{1}
</Project>";

private const string ProjectTemplateSdkAsElement = @"
<Project>
<Sdk Name=""{0}"" />
{1}
</Project>";

private const string ProjectTemplateSdkAsExplicitImport = @"
<Project>
<Import Project=""Sdk.props"" Sdk=""{0}"" />
{1}
<Import Project=""Sdk.targets"" Sdk=""{0}"" />
</Project>";

private const string SdkName = "MSBuildUnitTestSdk";
private TestEnvironment _env;
private readonly string _testSdkRoot;
Expand All @@ -41,72 +58,46 @@ public ProjectSdkImplicitImport_Tests()
}

[Theory]
[InlineData(@"
<Project Sdk=""{0}"">
<PropertyGroup>
<UsedToTestIfImplicitImportsAreInTheCorrectLocation>null</UsedToTestIfImplicitImportsAreInTheCorrectLocation>
</PropertyGroup>
</Project>
")]
[InlineData(@"
<Project>
<Sdk Name=""{0}"" />
<PropertyGroup>
<UsedToTestIfImplicitImportsAreInTheCorrectLocation>null</UsedToTestIfImplicitImportsAreInTheCorrectLocation>
</PropertyGroup>
</Project>
")]
public void SdkImportsAreInLogicalProject(string projectFormatString)
[InlineData(ProjectTemplateSdkAsAttribute, false)]
[InlineData(ProjectTemplateSdkAsElement, true)]
[InlineData(ProjectTemplateSdkAsExplicitImport, false)]
public void SdkImportsAreInLogicalProject(string projectFormatString, bool expectImportInLogicalProject)
{
_env.SetEnvironmentVariable("MSBuildSDKsPath", _testSdkRoot);

string projectInnerContents = @"<PropertyGroup><UsedToTestIfImplicitImportsAreInTheCorrectLocation>null</UsedToTestIfImplicitImportsAreInTheCorrectLocation></PropertyGroup>";
File.WriteAllText(_sdkPropsPath, "<Project><PropertyGroup><InitialImportProperty>Hello</InitialImportProperty></PropertyGroup></Project>");
File.WriteAllText(_sdkTargetsPath, "<Project><PropertyGroup><FinalImportProperty>World</FinalImportProperty></PropertyGroup></Project>");

string content = string.Format(projectFormatString, SdkName);
string content = string.Format(projectFormatString, SdkName, projectInnerContents);

ProjectRootElement projectRootElement =
ProjectRootElement.Create(XmlReader.Create(new StringReader(content)));
ProjectRootElement projectRootElement = ProjectRootElement.Create(XmlReader.Create(new StringReader(content)));

var project = new Project(projectRootElement);

IList<ProjectElement> children = project.GetLogicalProject().ToList();

// <Sdk> style will have an extra ProjectElment.
var expected = projectFormatString.Contains("Sdk=") ? 6 : 7;
Assert.Equal(expected, children.Count);
Assert.Equal(expectImportInLogicalProject ? 7 : 6, children.Count);
}

[Theory]
[InlineData(@"
<Project Sdk=""{0}"">
<PropertyGroup>
<UsedToTestIfImplicitImportsAreInTheCorrectLocation>null</UsedToTestIfImplicitImportsAreInTheCorrectLocation>
</PropertyGroup>
</Project>
")]
[InlineData(@"
<Project>
<Sdk Name=""{0}"" />
<PropertyGroup>
<UsedToTestIfImplicitImportsAreInTheCorrectLocation>null</UsedToTestIfImplicitImportsAreInTheCorrectLocation>
</PropertyGroup>
</Project>
")]
public void SdkImportsAreInImportList(string projectFormatString)
[InlineData(ProjectTemplateSdkAsAttribute, false)]
[InlineData(ProjectTemplateSdkAsElement, false)]
[InlineData(ProjectTemplateSdkAsExplicitImport, true)]
public void SdkImportsAreInImportList(string projectFormatString, bool expectImportInLogicalProject)
{
_env.SetEnvironmentVariable("MSBuildSDKsPath", _testSdkRoot);

string projectInnerContents = @"<PropertyGroup><UsedToTestIfImplicitImportsAreInTheCorrectLocation>null</UsedToTestIfImplicitImportsAreInTheCorrectLocation></PropertyGroup>";
File.WriteAllText(_sdkPropsPath, "<Project><PropertyGroup><InitialImportProperty>Hello</InitialImportProperty></PropertyGroup></Project>");
File.WriteAllText(_sdkTargetsPath, "<Project><PropertyGroup><FinalImportProperty>World</FinalImportProperty></PropertyGroup></Project>");
string content = string.Format(projectFormatString, SdkName);
string content = string.Format(projectFormatString, SdkName, projectInnerContents);

ProjectRootElement projectRootElement = ProjectRootElement.Create(XmlReader.Create(new StringReader(content)));

var project = new Project(projectRootElement);

// The XML representation of the project should indicate there are no imports
Assert.Equal(0, projectRootElement.Imports.Count);
// The XML representation of the project should only indicate an import if they are not implicit.
Assert.Equal(expectImportInLogicalProject ? 2 : 0, projectRootElement.Imports.Count);

// The project representation should have imports
Assert.Equal(2, project.Imports.Count);
Expand All @@ -130,14 +121,24 @@ public void SdkImportsAreInImportList(string projectFormatString)
[Theory]
[InlineData(@"
<Project Sdk=""{0};{1};{2}"">
</Project >")]
</Project >", false)]
[InlineData(@"
<Project>
<Sdk Name=""{0}"" />
<Sdk Name=""{1}"" />
<Sdk Name=""{2}"" />
</Project>")]
public void SdkSupportsMultiple(string projectFormatString)
</Project>", false)]
[InlineData(@"
<Project>
<Import Project=""Sdk.props"" Sdk=""{0}"" />
<Import Project=""Sdk.props"" Sdk=""{1}"" />
<Import Project=""Sdk.props"" Sdk=""{2}"" />
<Import Project=""Sdk.targets"" Sdk=""{0}"" />
<Import Project=""Sdk.targets"" Sdk=""{1}"" />
<Import Project=""Sdk.targets"" Sdk=""{2}"" />
</Project>", true)]
public void SdkSupportsMultiple(string projectFormatString, bool expectImportInLogicalProject)
{
_env.SetEnvironmentVariable("MSBuildSDKsPath", _testSdkRoot);

Expand All @@ -157,13 +158,12 @@ public void SdkSupportsMultiple(string projectFormatString)
}
string content = string.Format(projectFormatString, sdkNames[0], sdkNames[1], sdkNames[2]);

ProjectRootElement projectRootElement =
ProjectRootElement.Create(XmlReader.Create(new StringReader(content)));
ProjectRootElement projectRootElement = ProjectRootElement.Create(XmlReader.Create(new StringReader(content)));

Project project = new Project(projectRootElement);

// The XML representation of the project should indicate there are no imports
Assert.Equal(0, projectRootElement.Imports.Count);
Assert.Equal(expectImportInLogicalProject ? 6 : 0, projectRootElement.Imports.Count);

// The project representation should have twice as many imports as SDKs
Assert.Equal(sdkNames.Count * 2, project.Imports.Count);
Expand All @@ -174,21 +174,14 @@ public void SdkSupportsMultiple(string projectFormatString)
}

[Theory]
[InlineData(@"<Project Sdk=""{0}"" ToolsVersion=""15.0"">
")]
[InlineData(@"<Project ToolsVersion=""15.0"">
<Sdk Name=""{0}"" />
")]
public void ProjectWithSdkImportsIsCloneable(string projectFileFirstLineFormat)
[InlineData(ProjectTemplateSdkAsAttribute)]
[InlineData(ProjectTemplateSdkAsElement)]
[InlineData(ProjectTemplateSdkAsExplicitImport)]
public void ProjectWithSdkImportsIsCloneable(string projectFormatString)
{
_env.SetEnvironmentVariable("MSBuildSDKsPath", _testSdkRoot);

File.WriteAllText(_sdkPropsPath, "<Project />");
File.WriteAllText(_sdkTargetsPath, "<Project />");

// Based on the new-console-project CLI template (but not matching exactly
// should not be a deal-breaker).
string content = $@"{string.Format(projectFileFirstLineFormat, SdkName)}
string projectInnerContents = @"
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp1.0</TargetFramework>
Expand All @@ -201,31 +194,28 @@ public void ProjectWithSdkImportsIsCloneable(string projectFileFirstLineFormat)
<ItemGroup>
<PackageReference Include=""Microsoft.NETCore.App"" Version=""1.0.1"" />
</ItemGroup>
</Project>";
</ItemGroup>";
File.WriteAllText(_sdkPropsPath, "<Project />");
File.WriteAllText(_sdkTargetsPath, "<Project />");

// Based on the new-console-project CLI template (but not matching exactly
// should not be a deal-breaker).
string content = string.Format(projectFormatString, SdkName, projectInnerContents);
ProjectRootElement project = ProjectRootElement.Create(XmlReader.Create(new StringReader(content)));

project.DeepClone();

}

[Theory]
[InlineData(@"<Project Sdk=""{0}"" ToolsVersion=""15.0"">
")]
[InlineData(@"<Project ToolsVersion=""15.0"">
<Sdk Name=""{0}"" />
")]
public void ProjectWithSdkImportsIsRemoveable(string projectFileFirstLineFormat)
[InlineData(ProjectTemplateSdkAsAttribute)]
[InlineData(ProjectTemplateSdkAsElement)]
[InlineData(ProjectTemplateSdkAsExplicitImport)]
public void ProjectWithSdkImportsIsRemoveable(string projectFormatString)
{
_env.SetEnvironmentVariable("MSBuildSDKsPath", _testSdkRoot);

File.WriteAllText(_sdkPropsPath, "<Project />");
File.WriteAllText(_sdkTargetsPath, "<Project />");

// Based on the new-console-project CLI template (but not matching exactly
// should not be a deal-breaker).
string content = $@"{string.Format(projectFileFirstLineFormat, SdkName)}
string projectInnerContents = @"
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp1.0</TargetFramework>
Expand All @@ -238,16 +228,20 @@ public void ProjectWithSdkImportsIsRemoveable(string projectFileFirstLineFormat)
<ItemGroup>
<PackageReference Include=""Microsoft.NETCore.App"" Version=""1.0.1"" />
</ItemGroup>
</Project>";
</ItemGroup>";
File.WriteAllText(_sdkPropsPath, " <Project />");
File.WriteAllText(_sdkTargetsPath, "<Project />");

// Based on the new-console-project CLI template (but not matching exactly
// should not be a deal-breaker).
string content = string.Format(projectFormatString, SdkName, projectInnerContents);
ProjectRootElement project = ProjectRootElement.Create(XmlReader.Create(new StringReader(content)));
ProjectRootElement clone = ProjectRootElement.Create(XmlReader.Create(new StringReader(content)));

clone.DeepCopyFrom(project);

clone.RemoveAllChildren();

}

/// <summary>
Expand Down Expand Up @@ -278,21 +272,28 @@ public void ProjectWithInvalidSdkName()
/// <summary>
/// Verifies that an empty SDK attribute works and nothing is imported.
/// </summary>
[Fact]
public void ProjectWithEmptySdkName()
[Theory]
[InlineData(ProjectTemplateSdkAsAttribute, false)]
[InlineData(ProjectTemplateSdkAsElement, true)]
[InlineData(ProjectTemplateSdkAsExplicitImport, true)]
public void ProjectWithEmptySdkName(string projectFormatString, bool throwsOnEvaluate)
{
_env.SetEnvironmentVariable("MSBuildSDKsPath", _testSdkRoot);
string projectInnerContents =
@"<PropertyGroup><UsedToTestIfImplicitImportsAreInTheCorrectLocation>null</UsedToTestIfImplicitImportsAreInTheCorrectLocation></PropertyGroup>";

string content = @"
<Project Sdk="""">
<PropertyGroup>
<UsedToTestIfImplicitImportsAreInTheCorrectLocation>null</UsedToTestIfImplicitImportsAreInTheCorrectLocation>
</PropertyGroup>
</Project>";

Project project = new Project(ProjectRootElement.Create(XmlReader.Create(new StringReader(content))));
_env.SetEnvironmentVariable("MSBuildSDKsPath", _testSdkRoot);

Assert.Equal(0, project.Imports.Count);
string content = string.Format(projectFormatString, string.Empty, projectInnerContents);
if (throwsOnEvaluate)
{
Assert.Throws<InvalidProjectFileException>(
() => new Project(ProjectRootElement.Create(XmlReader.Create(new StringReader(content)))));
}
else
{
var project = new Project(ProjectRootElement.Create(XmlReader.Create(new StringReader(content))));
Assert.Equal(0, project.Imports.Count);
}
}

/// <summary>
Expand Down
Loading

0 comments on commit 6b0ddfc

Please sign in to comment.