|
// 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.Generic;
using System.IO;
using System.Text;
using System.Xml;
using Microsoft.Build.Construction;
using Microsoft.Build.Evaluation;
using Xunit;
using InvalidProjectFileException = Microsoft.Build.Exceptions.InvalidProjectFileException;
#nullable disable
namespace Microsoft.Build.UnitTests.OM.Construction
{
/// <summary>
/// Tests for the ProjectChooseElement class (and for ProjectWhenElement and ProjectOtherwiseElement)
/// </summary>
public class ProjectChooseElement_Tests
{
/// <summary>
/// Read choose with unexpected attribute
/// </summary>
[Fact]
public void ReadInvalidAttribute()
{
Assert.Throws<InvalidProjectFileException>(() =>
{
string content = @"
<Project>
<Choose X='Y'/>
</Project>
";
ProjectRootElement.Create(XmlReader.Create(new StringReader(content)));
});
}
/// <summary>
/// Read choose with unexpected Condition attribute.
/// Condition is not currently allowed on Choose.
/// </summary>
[Fact]
public void ReadInvalidConditionAttribute()
{
Assert.Throws<InvalidProjectFileException>(() =>
{
string content = @"
<Project>
<Choose Condition='true'/>
</Project>
";
ProjectRootElement.Create(XmlReader.Create(new StringReader(content)));
});
}
/// <summary>
/// Read choose with unexpected child
/// </summary>
[Fact]
public void ReadInvalidChild()
{
Assert.Throws<InvalidProjectFileException>(() =>
{
string content = @"
<Project>
<Choose>
<X/>
</Choose>
</Project>
";
ProjectRootElement.Create(XmlReader.Create(new StringReader(content)));
});
}
/// <summary>
/// Read choose with a When containing no Condition attribute
/// </summary>
[Fact]
public void ReadInvalidWhen()
{
Assert.Throws<InvalidProjectFileException>(() =>
{
string content = @"
<Project>
<Choose>
<When>
<PropertyGroup><x/></PropertyGroup>
</When>
<Otherwise>
<PropertyGroup><y/></PropertyGroup>
</Otherwise>
</Choose>
</Project>
";
ProjectRootElement.Create(XmlReader.Create(new StringReader(content)));
});
}
/// <summary>
/// Read choose with only an otherwise
/// </summary>
[Fact]
public void ReadInvalidOnlyOtherwise()
{
Assert.Throws<InvalidProjectFileException>(() =>
{
string content = @"
<Project>
<Choose>
<Otherwise/>
</Choose>
</Project>
";
ProjectRootElement.Create(XmlReader.Create(new StringReader(content)));
});
}
/// <summary>
/// Read choose with two otherwises
/// </summary>
[Fact]
public void ReadInvalidTwoOtherwise()
{
Assert.Throws<InvalidProjectFileException>(() =>
{
string content = @"
<Project>
<Choose>
<Otherwise/>
<Otherwise/>
</Choose>
</Project>
";
ProjectRootElement.Create(XmlReader.Create(new StringReader(content)));
});
}
/// <summary>
/// Read choose with otherwise before when
/// </summary>
[Fact]
public void ReadInvalidOtherwiseBeforeWhen()
{
Assert.Throws<InvalidProjectFileException>(() =>
{
string content = @"
<Project>
<Choose>
<Otherwise/>
<When Condition='c'/>
</Choose>
</Project>
";
ProjectRootElement.Create(XmlReader.Create(new StringReader(content)));
});
}
/// <summary>
/// Read empty choose
/// </summary>
/// <remarks>
/// One might think this should work but 2.0 required at least one When.
/// </remarks>
[Fact]
public void ReadInvalidEmptyChoose()
{
Assert.Throws<InvalidProjectFileException>(() =>
{
string content = @"
<Project>
<Choose/>
</Project>
";
ProjectRootElement project = ProjectRootElement.Create(XmlReader.Create(new StringReader(content)));
ProjectChooseElement choose = (ProjectChooseElement)Helpers.GetFirst(project.Children);
Assert.Null(Helpers.GetFirst(choose.Children));
});
}
/// <summary>
/// Read choose with only a when
/// </summary>
[Fact]
public void ReadChooseOnlyWhen()
{
string content = @"
<Project>
<Choose>
<When Condition='c'/>
</Choose>
</Project>
";
using ProjectRootElementFromString projectRootElementFromString = new(content);
ProjectRootElement project = projectRootElementFromString.Project;
ProjectChooseElement choose = (ProjectChooseElement)Helpers.GetFirst(project.Children);
Assert.Equal(1, Helpers.Count(choose.WhenElements));
Assert.Null(choose.OtherwiseElement);
}
/// <summary>
/// Read basic choose
/// </summary>
[Fact]
public void ReadChooseBothWhenOtherwise()
{
string content = @"
<Project>
<Choose>
<When Condition='c1'/>
<When Condition='c2'/>
<Otherwise/>
</Choose>
</Project>
";
using ProjectRootElementFromString projectRootElementFromString = new(content);
ProjectRootElement project = projectRootElementFromString.Project;
ProjectChooseElement choose = (ProjectChooseElement)Helpers.GetFirst(project.Children);
List<ProjectWhenElement> whens = Helpers.MakeList(choose.WhenElements);
Assert.Equal(2, whens.Count);
Assert.Equal("c1", whens[0].Condition);
Assert.Equal("c2", whens[1].Condition);
Assert.NotNull(choose.OtherwiseElement);
}
/// <summary>
/// Test stack overflow is prevented.
/// </summary>
[Fact]
public void ExcessivelyNestedChoose()
{
Assert.Throws<InvalidProjectFileException>(() =>
{
StringBuilder builder1 = new StringBuilder();
StringBuilder builder2 = new StringBuilder();
for (int i = 0; i < 52; i++)
{
builder1.Append("<Choose><When Condition='true'>");
builder2.Append("</When></Choose>");
}
string content = "<Project>";
content += builder1.ToString();
content += builder2.ToString();
content += @"</Project>";
ProjectRootElement.Create(XmlReader.Create(new StringReader(content)));
});
}
/// <summary>
/// Setting a When's condition should dirty the project
/// </summary>
[Fact]
public void SettingWhenConditionDirties()
{
string content = @"
<Project>
<Choose>
<When Condition='true'>
<PropertyGroup>
<p>v1</p>
</PropertyGroup>
</When>
</Choose>
</Project>
";
using ProjectFromString projectFromString = new(content);
Project project = projectFromString.Project;
ProjectChooseElement choose = Helpers.GetFirst(project.Xml.ChooseElements);
ProjectWhenElement when = Helpers.GetFirst(choose.WhenElements);
when.Condition = "false";
Assert.Equal("v1", project.GetPropertyValue("p"));
project.ReevaluateIfNecessary();
Assert.Equal(String.Empty, project.GetPropertyValue("p"));
}
}
}
|