File: CreateXHarnessAndroidWorkItemsTests.cs
Web Access
Project: src\src\Microsoft.DotNet.Helix\Sdk.Tests\Microsoft.DotNet.Helix.Sdk.Tests\Microsoft.DotNet.Helix.Sdk.Tests.csproj (Microsoft.DotNet.Helix.Sdk.Tests)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Linq;
using System.Threading.Tasks;
using FluentAssertions;
using Microsoft.Arcade.Common;
using Microsoft.Arcade.Test.Common;
using Microsoft.Build.Framework;
using Microsoft.DotNet.Internal.DependencyInjection.Testing;
using Microsoft.Extensions.DependencyInjection;
using Moq;
using Xunit;
 
#nullable enable
namespace Microsoft.DotNet.Helix.Sdk.Tests
{
    public class CreateXHarnessAndroidWorkItemsTests
    {
        private readonly MockFileSystem _fileSystem;
        private readonly Mock<IZipArchiveManager> _zipArchiveManager;
        private readonly CreateXHarnessAndroidWorkItems _task;
 
        public CreateXHarnessAndroidWorkItemsTests()
        {
            _fileSystem = new MockFileSystem();
            _zipArchiveManager = new();
            _zipArchiveManager.SetReturnsDefault(Task.CompletedTask);
            _zipArchiveManager
                .Setup(x => x.ArchiveFile(It.IsAny<string>(), It.IsAny<string>()))
                .Callback<string, string>((folder, zipPath) =>
                {
                    _fileSystem.Files.Add(zipPath, "zip of " + folder);
                });
 
            _task = new CreateXHarnessAndroidWorkItems()
            {                
                BuildEngine = new MockBuildEngine(),
            };
        }
 
        [Fact]
        public void MissingApkNamePropertyIsCaught()
        {
            var collection = CreateMockServiceCollection();
            _task.ConfigureServices(collection);
            _task.Apks = new[]
            {
                CreateApk("/apks/System.Foo.app", null!)
            };
 
            // Act
            using var provider = collection.BuildServiceProvider();
            _task.InvokeExecute(provider).Should().BeFalse();
 
            // Verify
            _task.WorkItems.Length.Should().Be(0);
        }
 
        [Fact]
        public void AndroidXHarnessWorkItemIsCreated()
        {
            var collection = CreateMockServiceCollection();
            _task.ConfigureServices(collection);
            _task.Apks = new[]
            {
                CreateApk("/apks/System.Foo.apk", "System.Foo", "00:15:42", "00:08:55")
            };
 
            // Act
            using var provider = collection.BuildServiceProvider();
            _task.InvokeExecute(provider).Should().BeTrue();
 
            // Verify
            _task.WorkItems.Length.Should().Be(1);
 
            var workItem = _task.WorkItems.First();
            workItem.GetMetadata("Identity").Should().Be("System.Foo");
            workItem.GetMetadata("Timeout").Should().Be("00:17:42");
 
            var payloadArchive = workItem.GetMetadata("PayloadArchive");
            payloadArchive.Should().NotBeNullOrEmpty();
            _fileSystem.FileExists(payloadArchive).Should().BeTrue();
 
            var command = workItem.GetMetadata("Command");
            command.Should().Contain("-timeout \"00:08:55\"");
 
            _zipArchiveManager
                .Verify(x => x.ArchiveFile("/apks/System.Foo.apk", payloadArchive), Times.Once);
            _zipArchiveManager
                .Verify(x => x.AddResourceFileToArchive<XHarnessTaskBase>(payloadArchive, It.Is<string>(s => s.Contains("xharness-helix-job.android.sh")), "xharness-helix-job.android.sh"), Times.AtLeastOnce);
            _zipArchiveManager
                .Verify(x => x.AddResourceFileToArchive<XHarnessTaskBase>(payloadArchive, It.Is<string>(s => s.Contains("xharness-helix-job.android.ps1")), "xharness-helix-job.android.ps1"), Times.AtLeastOnce);
        }
 
        [Fact]
        public void ArchivePayloadIsOverwritten()
        {
            var collection = CreateMockServiceCollection();
            _task.ConfigureServices(collection);
            _task.Apks = new[]
            {
                CreateApk("apks/System.Foo.apk", "System.Foo"),
                CreateApk("apks/System.Bar.apk", "System.Bar"),
            };
 
            _fileSystem.Files.Add("apks/xharness-payload-system.foo.zip", "archive");
 
            // Act
            using var provider = collection.BuildServiceProvider();
            _task.InvokeExecute(provider).Should().BeTrue();
 
            // Verify
            _task.WorkItems.Length.Should().Be(2);
 
            var workItem = _task.WorkItems.Last();
            workItem.GetMetadata("Identity").Should().Be("System.Bar");
            
            workItem = _task.WorkItems.First();
            workItem.GetMetadata("Identity").Should().Be("System.Foo");
 
            var payloadArchive = workItem.GetMetadata("PayloadArchive");
            payloadArchive.Should().NotBeNullOrEmpty();
            _fileSystem.FileExists(payloadArchive).Should().BeTrue();
            _fileSystem.RemovedFiles.Should().Contain(payloadArchive);
        }
 
        [Fact]
        public void ApkIsReused()
        {
            var collection = CreateMockServiceCollection();
            _task.ConfigureServices(collection);
            _task.Apks = new[]
            {
                CreateApk("item-1", "System.Foo", apkPath: "apks/System.Foo.apk"),
                CreateApk("item-2", "System.Foo", apkPath: "apks/System.Foo.apk"),
            };
 
            // Act
            using var provider = collection.BuildServiceProvider();
            _task.InvokeExecute(provider).Should().BeTrue();
 
            // Verify
            _task.WorkItems.Length.Should().Be(2);
            _fileSystem.RemovedFiles.Should().BeEmpty();
 
            var workItem1 = _task.WorkItems.Last();
            workItem1.GetMetadata("Identity").Should().Be("item-2");
 
            var payloadArchive = workItem1.GetMetadata("PayloadArchive");
            payloadArchive.Should().NotBeNullOrEmpty();
            _fileSystem.FileExists(payloadArchive).Should().BeTrue();
 
            var workItem2 = _task.WorkItems.First();
            workItem2.GetMetadata("Identity").Should().Be("item-1");
 
            payloadArchive = workItem2.GetMetadata("PayloadArchive");
            payloadArchive.Should().NotBeNullOrEmpty();
            _fileSystem.FileExists(payloadArchive).Should().BeTrue();
        }
 
        [Fact]
        public void ZippedApkIsProvided()
        {
            var collection = CreateMockServiceCollection();
            _task.ConfigureServices(collection);
            _task.Apks = new[]
            {
                CreateApk("/apks/System.Foo.zip", "System.Foo", "00:15:42", "00:08:55")
            };
 
            // Act
            using var provider = collection.BuildServiceProvider();
            _task.InvokeExecute(provider).Should().BeTrue();
 
            // Verify
            _task.WorkItems.Length.Should().Be(1);
 
            var workItem = _task.WorkItems.First();
            workItem.GetMetadata("Identity").Should().Be("System.Foo");
            workItem.GetMetadata("Timeout").Should().Be("00:17:42");
 
            var payloadArchive = workItem.GetMetadata("PayloadArchive");
            payloadArchive.Should().NotBeNullOrEmpty();
            _fileSystem.FileExists(payloadArchive).Should().BeTrue();
 
            var command = workItem.GetMetadata("Command");
            command.Should().Contain("-timeout \"00:08:55\"");
 
            _zipArchiveManager
                .Verify(x => x.ArchiveFile(It.IsAny<string>(), It.IsAny<string>()), Times.Never);
            _zipArchiveManager
                .Verify(x => x.AddResourceFileToArchive<XHarnessTaskBase>(payloadArchive, It.Is<string>(s => s.Contains("xharness-helix-job.android.sh")), "xharness-helix-job.android.sh"), Times.AtLeastOnce);
            _zipArchiveManager
                .Verify(x => x.AddResourceFileToArchive<XHarnessTaskBase>(payloadArchive, It.Is<string>(s => s.Contains("xharness-helix-job.android.ps1")), "xharness-helix-job.android.ps1"), Times.AtLeastOnce);
        }
 
        [Fact]
        public void AreDependenciesRegistered()
        {
            var task = new CreateXHarnessAndroidWorkItems();
 
            var collection = new ServiceCollection();
            task.ConfigureServices(collection);
            var provider = collection.BuildServiceProvider();
 
            DependencyInjectionValidation.IsDependencyResolutionCoherent(
                s => task.ConfigureServices(s),
                out string message,
                additionalSingletonTypes: task.GetExecuteParameterTypes()
            )
            .Should()
            .BeTrue(message);
        }
 
        private ITaskItem CreateApk(
            string itemSpec,
            string apkName,
            string? workItemTimeout = null,
            string? testTimeout = null,
            int expectedExitCode = 0,
            string? apkPath = null)
        {
            var mockBundle = new Mock<ITaskItem>();
            mockBundle.SetupGet(x => x.ItemSpec).Returns(itemSpec);
            mockBundle.Setup(x => x.GetMetadata(CreateXHarnessAndroidWorkItems.MetadataNames.AndroidPackageName)).Returns(apkName);
 
            if (workItemTimeout != null)
            {
                mockBundle.Setup(x => x.GetMetadata(XHarnessTaskBase.MetadataName.WorkItemTimeout)).Returns(workItemTimeout);
            }
 
            if (testTimeout != null)
            {
                mockBundle.Setup(x => x.GetMetadata(XHarnessTaskBase.MetadataName.TestTimeout)).Returns(testTimeout);
            }
 
            if (expectedExitCode != 0)
            {
                mockBundle.Setup(x => x.GetMetadata(XHarnessTaskBase.MetadataName.ExpectedExitCode)).Returns(expectedExitCode.ToString());
            }
 
            if (apkPath != null)
            {
                mockBundle.Setup(x => x.GetMetadata(CreateXHarnessAndroidWorkItems.MetadataNames.ApkPath)).Returns(apkPath);
            }
 
            _fileSystem.WriteToFile(apkPath ?? itemSpec, "apk");
 
            return mockBundle.Object;
        }
 
        private IServiceCollection CreateMockServiceCollection()
        {
            var collection = new ServiceCollection();
            collection.AddSingleton<IFileSystem>(_fileSystem);
            collection.AddSingleton(_zipArchiveManager.Object);
            return collection;
        }
    }
}