File: Construction\ProjectOnErrorElement_Tests.cs
Web Access
Project: ..\..\..\src\Build.OM.UnitTests\Microsoft.Build.Engine.OM.UnitTests.csproj (Microsoft.Build.Engine.OM.UnitTests)
// 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.IO;
using System.Xml;
using Microsoft.Build.Construction;
using Xunit;
using InvalidProjectFileException = Microsoft.Build.Exceptions.InvalidProjectFileException;
 
#nullable disable
 
namespace Microsoft.Build.UnitTests.OM.Construction
{
    /// <summary>
    /// Tests for the ProjectOnErrorElement class
    /// </summary>
    public class ProjectOnErrorElement_Tests
    {
        /// <summary>
        /// Read a target containing only OnError
        /// </summary>
        [Fact]
        public void ReadTargetOnlyContainingOnError()
        {
            ProjectOnErrorElement onError = GetOnError();
 
            Assert.Equal("t", onError.ExecuteTargetsAttribute);
            Assert.Equal("c", onError.Condition);
        }
 
        /// <summary>
        /// Read a target with two onerrors, and some tasks
        /// </summary>
        [Fact]
        public void ReadTargetTwoOnErrors()
        {
            string content = @"
                    <Project>
                        <Target Name='t'>
                            <t1/>
                            <t2/>
                            <OnError ExecuteTargets='1'/>
                            <OnError ExecuteTargets='2'/>
                        </Target>
                    </Project>
                ";
 
            using ProjectRootElementFromString projectRootElementFromString = new(content);
            ProjectRootElement project = projectRootElementFromString.Project;
            ProjectTargetElement target = (ProjectTargetElement)Helpers.GetFirst(project.Children);
            var onErrors = Helpers.MakeList(target.OnErrors);
 
            ProjectOnErrorElement onError1 = onErrors[0];
            ProjectOnErrorElement onError2 = onErrors[1];
 
            Assert.Equal("1", onError1.ExecuteTargetsAttribute);
            Assert.Equal("2", onError2.ExecuteTargetsAttribute);
        }
 
        /// <summary>
        /// Read onerror with no executetargets attribute
        /// </summary>
        /// <remarks>
        /// This was accidentally allowed in 2.0/3.5 but it should be an error now.
        /// </remarks>
        [Fact]
        public void ReadMissingExecuteTargets()
        {
            Assert.Throws<InvalidProjectFileException>(() =>
            {
                string content = @"
                    <Project>
                        <Target Name='t'>
                            <OnError/>
                        </Target>
                    </Project>
                ";
 
                ProjectRootElement project = ProjectRootElement.Create(XmlReader.Create(new StringReader(content)));
                ProjectTargetElement target = (ProjectTargetElement)Helpers.GetFirst(project.Children);
                ProjectOnErrorElement onError = (ProjectOnErrorElement)Helpers.GetFirst(target.Children);
 
                Assert.Equal(String.Empty, onError.ExecuteTargetsAttribute);
            });
        }
        /// <summary>
        /// Read onerror with empty executetargets attribute
        /// </summary>
        /// <remarks>
        /// This was accidentally allowed in 2.0/3.5 but it should be an error now.
        /// </remarks>
        [Fact]
        public void ReadEmptyExecuteTargets()
        {
            Assert.Throws<InvalidProjectFileException>(() =>
            {
                string content = @"
                    <Project>
                        <Target Name='t'>
                            <OnError ExecuteTargets=''/>
                        </Target>
                    </Project>
                ";
 
                ProjectRootElement project = ProjectRootElement.Create(XmlReader.Create(new StringReader(content)));
                ProjectTargetElement target = (ProjectTargetElement)Helpers.GetFirst(project.Children);
                ProjectOnErrorElement onError = (ProjectOnErrorElement)Helpers.GetFirst(target.Children);
 
                Assert.Equal(String.Empty, onError.ExecuteTargetsAttribute);
            });
        }
        /// <summary>
        /// Read onerror with invalid attribute
        /// </summary>
        [Fact]
        public void ReadInvalidUnexpectedAttribute()
        {
            Assert.Throws<InvalidProjectFileException>(() =>
            {
                string content = @"
                    <Project>
                        <Target Name='t'>
                            <OnError ExecuteTargets='t' XX='YY'/>
                        </Target>
                    </Project>
                ";
 
                ProjectRootElement.Create(XmlReader.Create(new StringReader(content)));
            });
        }
        /// <summary>
        /// Read onerror with invalid child element
        /// </summary>
        [Fact]
        public void ReadInvalidUnexpectedChild()
        {
            Assert.Throws<InvalidProjectFileException>(() =>
            {
                string content = @"
                    <Project>
                        <Target Name='t'>
                            <OnError ExecuteTargets='t'>
                                <X/>
                            </OnError>
                        </Target>
                    </Project>
                ";
 
                ProjectRootElement.Create(XmlReader.Create(new StringReader(content)));
            });
        }
        /// <summary>
        /// Read onerror before task
        /// </summary>
        [Fact]
        public void ReadInvalidBeforeTask()
        {
            Assert.Throws<InvalidProjectFileException>(() =>
            {
                string content = @"
                    <Project>
                        <Target Name='t'>
                            <OnError ExecuteTargets='t'/>
                            <t/>
                        </Target>
                    </Project>
                ";
 
                ProjectRootElement.Create(XmlReader.Create(new StringReader(content)));
            });
        }
        /// <summary>
        /// Read onerror before task
        /// </summary>
        [Fact]
        public void ReadInvalidBeforePropertyGroup()
        {
            Assert.Throws<InvalidProjectFileException>(() =>
            {
                string content = @"
                    <Project>
                        <Target Name='t'>
                            <OnError ExecuteTargets='t'/>
                            <PropertyGroup/>
                        </Target>
                    </Project>
                ";
 
                ProjectRootElement.Create(XmlReader.Create(new StringReader(content)));
            });
        }
        /// <summary>
        /// Read onerror before task
        /// </summary>
        [Fact]
        public void ReadInvalidBeforeItemGroup()
        {
            Assert.Throws<InvalidProjectFileException>(() =>
            {
                string content = @"
                    <Project>
                        <Target Name='t'>
                            <OnError ExecuteTargets='t'/>
                            <ItemGroup/>
                        </Target>
                    </Project>
                ";
 
                ProjectRootElement.Create(XmlReader.Create(new StringReader(content)));
            });
        }
        /// <summary>
        /// Set ExecuteTargets
        /// </summary>
        [Fact]
        public void SetExecuteTargetsValid()
        {
            ProjectOnErrorElement onError = GetOnError();
 
            onError.ExecuteTargetsAttribute = "t2";
 
            Assert.Equal("t2", onError.ExecuteTargetsAttribute);
        }
 
        /// <summary>
        /// Set ExecuteTargets to null
        /// </summary>
        [Fact]
        public void SetInvalidExecuteTargetsNull()
        {
            Assert.Throws<ArgumentNullException>(() =>
            {
                ProjectOnErrorElement onError = GetOnError();
 
                onError.ExecuteTargetsAttribute = null;
            });
        }
        /// <summary>
        /// Set ExecuteTargets to empty string
        /// </summary>
        [Fact]
        public void SetInvalidExecuteTargetsEmpty()
        {
            Assert.Throws<ArgumentException>(() =>
            {
                ProjectOnErrorElement onError = GetOnError();
 
                onError.ExecuteTargetsAttribute = String.Empty;
            });
        }
        /// <summary>
        /// Set on error condition
        /// </summary>
        [Fact]
        public void SetCondition()
        {
            ProjectRootElement project = ProjectRootElement.Create();
            ProjectTargetElement target = project.AddTarget("t");
            ProjectOnErrorElement onError = project.CreateOnErrorElement("et");
            target.AppendChild(onError);
            Helpers.ClearDirtyFlag(project);
 
            onError.Condition = "c";
 
            Assert.Equal("c", onError.Condition);
            Assert.True(project.HasUnsavedChanges);
        }
 
        /// <summary>
        /// Set on error executetargets value
        /// </summary>
        [Fact]
        public void SetExecuteTargets()
        {
            ProjectRootElement project = ProjectRootElement.Create();
            ProjectTargetElement target = project.AddTarget("t");
            ProjectOnErrorElement onError = project.CreateOnErrorElement("et");
            target.AppendChild(onError);
            Helpers.ClearDirtyFlag(project);
 
            onError.ExecuteTargetsAttribute = "et2";
 
            Assert.Equal("et2", onError.ExecuteTargetsAttribute);
            Assert.True(project.HasUnsavedChanges);
        }
 
        /// <summary>
        /// Get a basic ProjectOnErrorElement
        /// </summary>
        private static ProjectOnErrorElement GetOnError()
        {
            string content = @"
                    <Project>
                        <Target Name='t'>
                            <OnError ExecuteTargets='t' Condition='c'/>
                        </Target>
                    </Project>
                ";
 
            using ProjectRootElementFromString projectRootElementFromString = new(content);
            ProjectRootElement project = projectRootElementFromString.Project;
            ProjectTargetElement target = (ProjectTargetElement)Helpers.GetFirst(project.Children);
            ProjectOnErrorElement onError = (ProjectOnErrorElement)Helpers.GetFirst(target.Children);
            return onError;
        }
    }
}