File: ReadLinesFromFile_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.IO;
#if FEATURE_SECURITY_PERMISSIONS
using System.Security.AccessControl;
#endif
 
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 ReadLinesFromFile_Tests
    {
        /// <summary>
        /// Write one line, read one line.
        /// </summary>
        [Fact]
        public void Basic()
        {
            // Start with a missing file.
            var file = FileUtilities.GetTemporaryFileName();
            try
            {
                // Append one line to the file.
                var a = new WriteLinesToFile
                {
                    File = new TaskItem(file),
                    Lines = new ITaskItem[] { new TaskItem("Line1") }
                };
                Assert.True(a.Execute());
 
                // Read the line from the file.
                var r = new ReadLinesFromFile
                {
                    File = new TaskItem(file)
                };
                Assert.True(r.Execute());
 
                Assert.Single(r.Lines);
                Assert.Equal("Line1", r.Lines[0].ItemSpec);
 
                // Write two more lines to the file.
                a.Lines = new ITaskItem[] { new TaskItem("Line2"), new TaskItem("Line3") };
                Assert.True(a.Execute());
 
                // Read all of the lines and verify them.
                Assert.True(r.Execute());
                Assert.Equal(3, r.Lines.Length);
                Assert.Equal("Line1", r.Lines[0].ItemSpec);
                Assert.Equal("Line2", r.Lines[1].ItemSpec);
                Assert.Equal("Line3", r.Lines[2].ItemSpec);
            }
            finally
            {
                File.Delete(file);
            }
        }
 
        /// <summary>
        /// Write one line, read one line, where the line contains MSBuild-escapable characters.
        /// The file should contain the *unescaped* lines, but no escaping information should be
        /// lost when read.
        /// </summary>
        [Fact]
        public void Escaping()
        {
            // Start with a missing file.
            var file = FileUtilities.GetTemporaryFileName();
            try
            {
                // Append one line to the file.
                var a = new WriteLinesToFile
                {
                    File = new TaskItem(file),
                    Lines = new ITaskItem[] { new TaskItem("Line1_%253b_") }
                };
                Assert.True(a.Execute());
 
                // Read the line from the file.
                var r = new ReadLinesFromFile
                {
                    File = new TaskItem(file)
                };
                Assert.True(r.Execute());
 
                Assert.Single(r.Lines);
                Assert.Equal("Line1_%3b_", r.Lines[0].ItemSpec);
 
                // Write two more lines to the file.
                a.Lines = new ITaskItem[] { new TaskItem("Line2"), new TaskItem("Line3") };
                Assert.True(a.Execute());
 
                // Read all of the lines and verify them.
                Assert.True(r.Execute());
                Assert.Equal(3, r.Lines.Length);
                Assert.Equal("Line1_%3b_", r.Lines[0].ItemSpec);
                Assert.Equal("Line2", r.Lines[1].ItemSpec);
                Assert.Equal("Line3", r.Lines[2].ItemSpec);
            }
            finally
            {
                File.Delete(file);
            }
        }
 
        /// <summary>
        /// Write a line that contains an ANSI character that is not ASCII.
        /// </summary>
        [Fact]
        public void ANSINonASCII()
        {
            // Start with a missing file.
            var file = FileUtilities.GetTemporaryFileName();
            try
            {
                // Append one line to the file.
                var a = new WriteLinesToFile
                {
                    File = new TaskItem(file),
                    Lines = new ITaskItem[] { new TaskItem("My special character is \u00C3") }
                };
                Assert.True(a.Execute());
 
                // Read the line from the file.
                var r = new ReadLinesFromFile
                {
                    File = new TaskItem(file)
                };
                Assert.True(r.Execute());
 
                Assert.Single(r.Lines);
                Assert.Equal("My special character is \u00C3", r.Lines[0].ItemSpec);
            }
            finally
            {
                File.Delete(file);
            }
        }
 
        /// <summary>
        /// Reading lines from an missing file should result in the empty list.
        /// </summary>
        [Fact]
        public void ReadMissing()
        {
            var file = FileUtilities.GetTemporaryFileName();
 
            // Read the line from the file.
            var r = new ReadLinesFromFile
            {
                File = new TaskItem(file)
            };
            Assert.True(r.Execute());
 
            Assert.Empty(r.Lines);
        }
 
        /// <summary>
        /// Reading blank lines from a file should be ignored.
        /// </summary>
        [Fact]
        public void IgnoreBlankLines()
        {
            // Start with a missing file.
            var file = FileUtilities.GetTemporaryFileName();
            try
            {
                // Append one line to the file.
                var a = new WriteLinesToFile
                {
                    File = new TaskItem(file),
                    Lines = new ITaskItem[]
                {
                    new TaskItem("Line1"),
                    new TaskItem("  "),
                    new TaskItem("Line2"),
                    new TaskItem(""),
                    new TaskItem("Line3"),
                    new TaskItem("\0\0\0\0\0\0\0\0\0")
                }
                };
                Assert.True(a.Execute());
 
                // Read the line from the file.
                var r = new ReadLinesFromFile
                {
                    File = new TaskItem(file)
                };
                Assert.True(r.Execute());
 
                Assert.Equal(3, r.Lines.Length);
                Assert.Equal("Line1", r.Lines[0].ItemSpec);
                Assert.Equal("Line2", r.Lines[1].ItemSpec);
                Assert.Equal("Line3", r.Lines[2].ItemSpec);
            }
            finally
            {
                File.Delete(file);
            }
        }
 
#if FEATURE_SECURITY_PERMISSIONS
        /// <summary>
        /// Reading lines from a file that you have no access to.
        /// </summary>
        [Fact]
        public void ReadNoAccess()
        {
            if (NativeMethodsShared.IsUnixLike)
            {
                return; // "The security API is not the same under Unix"
            }
 
            // Start with a missing file.
            var file = FileUtilities.GetTemporaryFileName();
            try
            {
                // Append one line to the file.
                var a = new WriteLinesToFile
                {
                    File = new TaskItem(file),
                    Lines = new ITaskItem[] { new TaskItem("This is a new line") }
                };
                Assert.True(a.Execute());
 
                // Remove all File access to the file to current user
                var fSecurity = File.GetAccessControl(file);
                var userAccount = string.Format(@"{0}\{1}", System.Environment.UserDomainName, System.Environment.UserName);
                fSecurity.AddAccessRule(new FileSystemAccessRule(userAccount, FileSystemRights.ReadData, AccessControlType.Deny));
                File.SetAccessControl(file, fSecurity);
 
                // Attempt to Read lines from the file.
                var r = new ReadLinesFromFile();
                var mEngine = new MockEngine();
                r.BuildEngine = mEngine;
                r.File = new TaskItem(file);
                Assert.False(r.Execute());
            }
            finally
            {
                var fSecurity = File.GetAccessControl(file);
                var userAccount = string.Format(@"{0}\{1}", System.Environment.UserDomainName, System.Environment.UserName);
                fSecurity.AddAccessRule(new FileSystemAccessRule(userAccount, FileSystemRights.ReadData, AccessControlType.Allow));
                File.SetAccessControl(file, fSecurity);
 
                // Delete file
                File.Delete(file);
            }
        }
#endif
 
    }
}