File: AssignLinkMetadata_Tests.cs
Web Access
Project: ..\..\..\src\Tasks.UnitTests\Microsoft.Build.Tasks.UnitTests.csproj (Microsoft.Build.Tasks.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.Collections.Generic;
using System.IO;
using Microsoft.Build.Evaluation;
using Microsoft.Build.Execution;
using Microsoft.Build.Framework;
using Microsoft.Build.Shared;
using Microsoft.Build.Tasks;
using Microsoft.Build.Utilities;
using Xunit;
 
#nullable disable
 
namespace Microsoft.Build.UnitTests
{
    public sealed class AssignLinkMetadata_Tests
    {
        private readonly string _defaultItemSpec = Path.Combine(Path.GetTempPath(), "SubFolder", "a.cs");
 
        /// <summary>
        /// AssignLinkMetadata should behave nicely when no items are set to it
        /// </summary>
        [Fact]
        public void NoItems()
        {
            AssignLinkMetadata t = new AssignLinkMetadata
            {
                BuildEngine = new MockEngine()
            };
            bool success = t.Execute();
 
            Assert.True(success);
            Assert.Empty(t.OutputItems);
        }
 
        /// <summary>
        /// AssignLinkMetadata should behave nicely when there is an item with an
        /// itemspec that contains invalid path characters.
        /// </summary>
        [Fact]
        public void InvalidItemPath()
        {
            ITaskItem item = GetParentedTaskItem(_defaultItemSpec);
            item.ItemSpec = "|||";
 
            AssignLinkMetadata t = new AssignLinkMetadata
            {
                BuildEngine = new MockEngine(),
                Items = new ITaskItem[] { new TaskItem(item) }
            };
            bool success = t.Execute();
 
            Assert.True(success);
            Assert.Empty(t.OutputItems);
        }
 
        /// <summary>
        /// Test basic function of the AssignLinkMetadata task
        /// </summary>
        [Fact]
        public void Basic()
        {
            ITaskItem item = GetParentedTaskItem(_defaultItemSpec);
 
            AssignLinkMetadata t = new AssignLinkMetadata
            {
                BuildEngine = new MockEngine(),
                Items = new ITaskItem[] { new TaskItem(item) }
            };
            bool success = t.Execute();
 
            Assert.True(success);
            Assert.Single(t.OutputItems);
            Assert.Equal(item.ItemSpec, t.OutputItems[0].ItemSpec);
 
            // Link metadata should have been added by the task, and OriginalItemSpec was added by the copy
            Assert.Equal(item.MetadataCount + 2, t.OutputItems[0].MetadataCount);
            Assert.Equal(Path.Combine("SubFolder", "a.cs"), t.OutputItems[0].GetMetadata("Link"));
        }
 
        /// <summary>
        /// AssignLinkMetadata should behave nicely when there is an item with an
        /// itemspec that contains invalid path characters, and still successfully
        /// output any items that aren't problematic.
        /// </summary>
        [Fact]
        public void InvalidItemPathWithOtherValidItem()
        {
            ITaskItem item1 = GetParentedTaskItem(itemSpec: "|||");
            ITaskItem item2 = GetParentedTaskItem(_defaultItemSpec);
 
            AssignLinkMetadata t = new AssignLinkMetadata
            {
                BuildEngine = new MockEngine(),
                Items = new ITaskItem[] { new TaskItem(item1), new TaskItem(item2) }
            };
            bool success = t.Execute();
 
            Assert.True(success);
            Assert.Single(t.OutputItems);
            Assert.Equal(item2.ItemSpec, t.OutputItems[0].ItemSpec);
 
            // Link metadata should have been added by the task, and OriginalItemSpec was added by the copy
            Assert.Equal(item2.MetadataCount + 2, t.OutputItems[0].MetadataCount);
            Assert.Equal(Path.Combine("SubFolder", "a.cs"), t.OutputItems[0].GetMetadata("Link"));
        }
 
        /// <summary>
        /// AssignLinkMetadata should not override if Link is already set
        /// </summary>
        [Fact]
        public void DontOverrideLink()
        {
            ITaskItem item = GetParentedTaskItem(_defaultItemSpec, Path.Combine("SubFolder2", "SubSubFolder", "a.cs"));
 
            AssignLinkMetadata t = new AssignLinkMetadata
            {
                BuildEngine = new MockEngine(),
                Items = new ITaskItem[] { new TaskItem(item) }
            };
            bool success = t.Execute();
 
            Assert.True(success);
            Assert.Empty(t.OutputItems);
        }
 
        /// <summary>
        /// AssignLinkMetadata should not set Link if the item is outside the
        /// defining project's cone
        /// </summary>
        [Fact]
        public void OutsideDefiningProjectCone()
        {
            var item = GetParentedTaskItem(NativeMethodsShared.IsUnixLike
                ? Path.Combine("//subfolder/a.cs")
                : @"c:\subfolder\a.cs");
 
            AssignLinkMetadata t = new AssignLinkMetadata
            {
                BuildEngine = new MockEngine(),
                Items = new ITaskItem[] { new TaskItem(item) }
            };
            bool success = t.Execute();
 
            Assert.True(success);
            Assert.Empty(t.OutputItems);
        }
 
        /// <summary>
        /// AssignLinkMetadata should not set Link if the item does not know its
        /// defining project
        /// </summary>
        [Fact]
        public void NoDefiningProjectMetadata()
        {
            ITaskItem item = new TaskItem(Path.Combine("SubFolder", "a.cs"));
 
            AssignLinkMetadata t = new AssignLinkMetadata
            {
                BuildEngine = new MockEngine(),
                Items = new ITaskItem[] { item }
            };
            bool success = t.Execute();
 
            Assert.True(success);
            Assert.Empty(t.OutputItems);
        }
 
        /// <summary>
        /// Helper function creating a task item that is associated with a parent project
        /// </summary>
        private ITaskItem GetParentedTaskItem(string itemSpec, string linkMetadata = null)
        {
            using var collection = new ProjectCollection();
            Project p = new Project(collection)
            {
                FullPath = Path.Combine(Path.GetTempPath(), "a.proj")
            };
            ProjectInstance pi = p.CreateProjectInstance();
 
            IDictionary<string, string> metadata = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
 
            if (linkMetadata != null)
            {
                metadata.Add("Link", linkMetadata);
            }
 
            ITaskItem item = pi.AddItem("Foo", itemSpec, metadata);
            return item;
        }
    }
}