public void ArtifactToSignMustExistInArtifacts()
        {
            var          localPackagePath = TestInputs.GetFullPath(Path.Combine("Nupkgs", "test-package-a.1.0.0.nupkg"));
            const string zipPath          = @"this/is/a/zip.zip";
            const string bogusNupkgToSign = "totallyboguspackage.nupkg";

            var artifacts = new ITaskItem[]
            {
                new TaskItem(localPackagePath, new Dictionary <string, string>()),
                new TaskItem(zipPath, new Dictionary <string, string>()
                {
                    { "RelativeBlobPath", zipPath },
                })
            };

            var itemsToSign = new ITaskItem[]
            {
                new TaskItem(bogusNupkgToSign),
                new TaskItem(Path.GetFileName(zipPath)),
                new TaskItem(Path.GetFileName(localPackagePath)),
            };

            var model = _buildModelFactory.CreateModelFromItems(artifacts, itemsToSign,
                                                                null, null, null, null,
                                                                _testAzdoBuildId, _defaultManifestBuildData, _testAzdoRepoUri, _testBuildBranch, _testBuildCommit, false,
                                                                VersionTools.BuildManifest.Model.PublishingInfraVersion.All,
                                                                true);

            _taskLoggingHelper.HasLoggedErrors.Should().BeTrue();
            _buildEngine.BuildErrorEvents.Should().HaveCount(1);
            _buildEngine.BuildErrorEvents.Should().Contain(e => e.Message.Equals($"Item to sign '{bogusNupkgToSign}' was not found in the artifacts"));
        }
示例#2
0
        public void PublishSymbolApiIsCalledTest()
        {
            var path = TestInputs.GetFullPath("Symbols");

            string[] fileEntries           = Directory.GetFiles(path);
            var      feedConfigsForSymbols = new HashSet <TargetFeedConfig>();

            feedConfigsForSymbols.Add(new TargetFeedConfig(
                                          TargetFeedContentType.Symbols,
                                          TargetUrl,
                                          FeedType.AzureStorageFeed,
                                          SymWebToken,
                                          string.Empty,
                                          AssetSelection.All,
                                          isolated: true,
                                          @internal: false,
                                          allowOverwrite: true,
                                          SymbolTargetType.SymWeb));
            Assert.True(PublishSymbolsHelper.PublishAsync(
                            log: null,
                            symbolServerPath: path,
                            personalAccessToken: SymWebToken,
                            inputPackages: fileEntries,
                            inputFiles: fileEntries,
                            packageExcludeFiles: null,
                            expirationInDays: 365,
                            convertPortablePdbsToWindowsPdbs: false,
                            publishSpecialClrFiles: false,
                            pdbConversionTreatAsWarning: null,
                            treatPdbConversionIssuesAsInfo: false,
                            dryRun: false,
                            timer: false,
                            verboseLogging: false).IsCompleted);
        }
        public void NoSigningInformationDoesNotThrowAnError()
        {
            var localPackagePath = TestInputs.GetFullPath(Path.Combine("Nupkgs", "test-package-a.1.0.0.nupkg"));

            var artifacts = new ITaskItem[]
            {
                new TaskItem(localPackagePath, new Dictionary <string, string>()
                {
                    { "ManifestArtifactData", "nonshipping=true;Category=CASE" },
                })
            };

            var model = _buildModelFactory.CreateModelFromItems(artifacts, null,
                                                                null, null, null, null, _testAzdoBuildId, _defaultManifestBuildData, _testAzdoRepoUri, _testBuildBranch, _testBuildCommit, false,
                                                                VersionTools.BuildManifest.Model.PublishingInfraVersion.All,
                                                                true);

            _taskLoggingHelper.HasLoggedErrors.Should().BeFalse();
            model.SigningInformation.Should().NotBeNull();
            model.SigningInformation.ItemsToSign.Should().BeEmpty();
            model.SigningInformation.CertificatesSignInfo.Should().BeEmpty();
            model.SigningInformation.FileExtensionSignInfo.Should().BeEmpty();
            model.SigningInformation.FileSignInfo.Should().BeEmpty();
            model.SigningInformation.StrongNameSignInfo.Should().BeEmpty();
        }
示例#4
0
        public void DownloadFileAsyncSucceedsForValidUrl()
        {
            var buildEngine = new MockBuildEngine();
            var publishTask = new PublishArtifactsInManifestV3
            {
                BuildEngine = buildEngine,
            };

            var testFile        = Path.Combine("Symbols", "test.txt");
            var responseContent = TestInputs.ReadAllBytes(testFile);
            var response        = new HttpResponseMessage(HttpStatusCode.OK)
            {
                Content = new ByteArrayContent(responseContent)
            };

            using HttpClient client = FakeHttpClient.WithResponses(response);
            var path = TestInputs.GetFullPath(Guid.NewGuid().ToString());

            var test = publishTask.DownloadFileAsync(
                client,
                PublishArtifactsInManifestBase.ArtifactName.BlobArtifacts,
                "1234",
                "test.txt",
                path);

            Assert.True(File.Exists(path));
            publishTask.DeleteTemporaryFiles(path);
            publishTask.DeleteTemporaryDirectory(path);
        }
        public void InitialLocationInformationAttributesAreAccepted(string attributeName)
        {
            var localPackagePath = TestInputs.GetFullPath(Path.Combine("Nupkgs", "test-package-a.1.0.0.nupkg"));

            var artifacts = new ITaskItem[]
            {
                new TaskItem(localPackagePath, new Dictionary <string, string>
                {
                    { "ManifestArtifactData", "NonShipping=true" }
                })
            };

            var manifestBuildData = new string[]
            {
                $"{attributeName}={_testInitialLocation}"
            };

            var model = _buildModelFactory.CreateModelFromItems(artifacts, null,
                                                                null, null, null, null, _testAzdoBuildId, manifestBuildData, _testAzdoRepoUri, _testBuildBranch, _testBuildCommit, false,
                                                                VersionTools.BuildManifest.Model.PublishingInfraVersion.All,
                                                                true);

            // Should have logged an error that an initial location was not present.
            _taskLoggingHelper.HasLoggedErrors.Should().BeFalse();

            // Check that the build model has the initial assets location
            model.Identity.Attributes.Should().Contain(attributeName, _normalizedTestInitialLocation);
        }
示例#6
0
        public async Task CompareLocalPackageToFeedPackageShouldCorrectlyInterpretFeedResponse(
            string feedResponseContentName,
            HttpStatusCode feedResponseStatusCode,
            PackageFeedStatus expectedResult)
        {
            var localPackagePath  = TestInputs.GetFullPath(Path.Combine("Nupkgs", "test-package-a.zip"));
            var packageContentUrl = $"https://fakefeed.azure.com/nuget/v3/{feedResponseContentName}.nupkg";
            var taskLoggingHelper = new Microsoft.Build.Utilities.TaskLoggingHelper(new StubTask());
            var retryHandler      = new MockRetryHandler();

            var response = new HttpResponseMessage(feedResponseStatusCode);

            if (!string.IsNullOrEmpty(feedResponseContentName))
            {
                var content = TestInputs.ReadAllBytes(Path.Combine("Nupkgs", $"{feedResponseContentName}.zip"));
                response.Content = new ByteArrayContent(content);
            }
            ;

            var httpClient = FakeHttpClient.WithResponses(response);

            var result = await GeneralUtils.CompareLocalPackageToFeedPackage(
                localPackagePath,
                packageContentUrl,
                httpClient,
                taskLoggingHelper,
                retryHandler);

            result.Should().Be(expectedResult);
        }
示例#7
0
        [InlineData(HttpStatusCode.InternalServerError, 2)] // retry on 5xx
        public async Task CompareLocalPackageToFeedPackageShouldRetryFailedRequests(
            HttpStatusCode initialResponseStatusCode,
            int expectedAttemptCount)
        {
            var testPackageName   = Path.Combine("Nupkgs", "test-package-a.zip");
            var localPackagePath  = TestInputs.GetFullPath(testPackageName);
            var packageContentUrl = "https://fakefeed.azure.com/nuget/v3/test-package-a.zip";
            var taskLoggingHelper = new Microsoft.Build.Utilities.TaskLoggingHelper(new StubTask());

            var retryHandler = new MockRetryHandler(maxAttempts: 2);

            var responseContent = TestInputs.ReadAllBytes(testPackageName);
            var responses       = new[]
            {
                new HttpResponseMessage(initialResponseStatusCode)
                {
                    Content = new ByteArrayContent(responseContent)
                },
                new HttpResponseMessage(HttpStatusCode.OK)
                {
                    Content = new ByteArrayContent(responseContent)
                }
            };

            var httpClient = FakeHttpClient.WithResponses(responses);

            await GeneralUtils.CompareLocalPackageToFeedPackage(
                localPackagePath,
                packageContentUrl,
                httpClient,
                taskLoggingHelper,
                retryHandler);

            retryHandler.ActualAttempts.Should().Be(expectedAttemptCount);
        }
        public void ArtifactMetadataIsCaseInsensitive()
        {
            var localPackagePath = TestInputs.GetFullPath(Path.Combine("Nupkgs", "test-package-a.1.0.0.nupkg"));

            var artifacts = new ITaskItem[]
            {
                new TaskItem(localPackagePath, new Dictionary <string, string>()
                {
                    { "ManifestArtifactData", "nonshipping=true;Category=CASE" },
                })
            };

            var model = _buildModelFactory.CreateModelFromItems(artifacts, null,
                                                                null, null, null, null, _testAzdoBuildId, _defaultManifestBuildData, _testAzdoRepoUri, _testBuildBranch, _testBuildCommit, false,
                                                                VersionTools.BuildManifest.Model.PublishingInfraVersion.All,
                                                                true);

            model.Artifacts.Blobs.Should().BeEmpty();
            model.Artifacts.Packages.Should().SatisfyRespectively(
                package =>
            {
                package.Id.Should().Be("test-package-a");
                package.Version.Should().Be("1.0.0");
                // We used "nonshipping=true" in our artifact metadata
                package.NonShipping.Should().BeTrue();
                package.Attributes.Should().Contain("nonshipping", "true");
                package.Attributes.Should().Contain("Category", "CASE");
                package.Attributes.Should().Contain("Id", "test-package-a");
                package.Attributes.Should().Contain("Version", "1.0.0");
            });
        }
示例#9
0
        public void PublishSymbolApiIsCalledTest()
        {
            var path = TestInputs.GetFullPath("Symbols");

            string[] fileEntries           = Directory.GetFiles(path);
            var      feedConfigsForSymbols = new HashSet <TargetFeedConfig>();

            feedConfigsForSymbols.Add(new TargetFeedConfig(
                                          TargetFeedContentType.Symbols,
                                          TargetUrl,
                                          FeedType.AzureStorageFeed,
                                          SymWebToken,
                                          string.Empty,
                                          AssetSelection.All,
                                          isolated: true,
                                          @internal: false,
                                          allowOverwrite: true,
                                          SymbolTargetType.SymWeb));
            Assert.True(PublishSymbolsHelper.PublishAsync(null,
                                                          path,
                                                          SymWebToken,
                                                          fileEntries,
                                                          fileEntries,
                                                          null,
                                                          365,
                                                          false,
                                                          false,
                                                          null,
                                                          false,
                                                          false,
                                                          false).IsCompleted);
        }
示例#10
0
        public void ConstructV3PublishingTask()
        {
            var manifestFullPath = TestInputs.GetFullPath(Path.Combine("Manifests", "SampleV3.xml"));

            var buildEngine = new MockBuildEngine();
            var task        = new PublishArtifactsInManifest()
            {
                BuildEngine    = buildEngine,
                TargetChannels = GeneralTestingChannelId
            };

            // Dependency Injection setup
            var collection = new ServiceCollection()
                             .AddSingleton <IFileSystem, FileSystem>()
                             .AddSingleton <IBuildModelFactory, BuildModelFactory>();

            task.ConfigureServices(collection);
            using var provider = collection.BuildServiceProvider();

            // Act and Assert
            task.InvokeExecute(provider);

            var which = task.WhichPublishingTask(manifestFullPath);

            which.Should().BeOfType <PublishArtifactsInManifestV3>();
        }
示例#11
0
        public void TemporarySymbolsDirectoryTest()
        {
            var publishTask = new PublishArtifactsInManifestV3();
            var path        = TestInputs.GetFullPath("Test");

            publishTask.EnsureTemporarySymbolDirectoryExists(path);
            Assert.True(Directory.Exists(path));
            publishTask.DeleteSymbolTemporaryDirectory(path);
            Assert.False(Directory.Exists(path));
        }
示例#12
0
        public void TemporarySymbolDirectoryDoesNotExists()
        {
            var buildEngine = new MockBuildEngine();
            var task        = new PublishArtifactsInManifestV3()
            {
                BuildEngine = buildEngine,
            };
            var path    = TestInputs.GetFullPath("Symbol");
            var publish = task.HandleSymbolPublishingAsync(path, MsdlToken, SymWebToken, "", path, false);

            Assert.True(task.Log.HasLoggedErrors);
        }
示例#13
0
        public async Task TemporarySymbolDirectoryDoesNotExists()
        {
            var buildEngine = new MockBuildEngine();
            var task        = new PublishArtifactsInManifestV3()
            {
                BuildEngine = buildEngine,
            };
            var path       = TestInputs.GetFullPath("Symbol");
            var buildAsset = new Dictionary <string, HashSet <Asset> >();
            await task.HandleSymbolPublishingAsync(path, MsdlToken, SymWebToken, "", false, buildAsset, null, path);

            Assert.True(task.Log.HasLoggedErrors);
        }
示例#14
0
        public void ConstructV3PublishingTask()
        {
            var manifestFullPath = TestInputs.GetFullPath(Path.Combine("Manifests", "SampleV3.xml"));

            var buildEngine = new MockBuildEngine();
            var task        = new PublishArtifactsInManifest()
            {
                BuildEngine    = buildEngine,
                TargetChannels = GeneralTestingChannelId
            };

            var which = task.WhichPublishingTask(manifestFullPath);

            which.Should().BeOfType <PublishArtifactsInManifestV3>();
        }
示例#15
0
        public async Task DownloadFailureWhenStatusCodeIsInvalid(HttpStatusCode httpStatus)
        {
            var buildEngine = new MockBuildEngine();
            var publishTask = new PublishArtifactsInManifestV3
            {
                BuildEngine = buildEngine,
            };
            var testFile        = Path.Combine("Symbols", "test.txt");
            var responseContent = TestInputs.ReadAllBytes(testFile);

            publishTask.RetryHandler = new ExponentialRetry()
            {
                MaxAttempts = 3, DelayBase = 1
            };

            var responses = new[]
            {
                new HttpResponseMessage(httpStatus)
                {
                    Content = new ByteArrayContent(responseContent)
                },
                new HttpResponseMessage(httpStatus)
                {
                    Content = new ByteArrayContent(responseContent)
                },
                new HttpResponseMessage(httpStatus)
                {
                    Content = new ByteArrayContent(responseContent)
                }
            };

            using HttpClient client = FakeHttpClient.WithResponses(responses);
            var path = TestInputs.GetFullPath(Guid.NewGuid().ToString());

            var actualError = await Assert.ThrowsAsync <Exception>(() =>
                                                                   publishTask.DownloadFileAsync(
                                                                       client,
                                                                       PublishArtifactsInManifestBase.ArtifactName.BlobArtifacts,
                                                                       "1234",
                                                                       "test.txt",
                                                                       path));

            Assert.Contains($"Failed to download local file '{path}' after {publishTask.RetryHandler.MaxAttempts} attempts.  See inner exception for details.", actualError.Message);
        }
示例#16
0
        public async Task ErrorAfterMaxRetriesToGetContainerId(HttpStatusCode httpStatus)
        {
            var buildEngine = new MockBuildEngine();
            var publishTask = new PublishArtifactsInManifestV3
            {
                BuildEngine = buildEngine,
            };

            publishTask.BuildId      = "1243456";
            publishTask.RetryHandler = new ExponentialRetry()
            {
                MaxAttempts = 3, DelayBase = 1
            };

            var testPackageName = Path.Combine("Symbols", "test.txt");
            var responseContent = TestInputs.ReadAllBytes(testPackageName);
            var responses       = new[]
            {
                new HttpResponseMessage(httpStatus)
                {
                    Content = new ByteArrayContent(responseContent)
                },
                new HttpResponseMessage(httpStatus)
                {
                    Content = new ByteArrayContent(responseContent)
                },
                new HttpResponseMessage(httpStatus)
                {
                    Content = new ByteArrayContent(responseContent)
                }
            };

            using HttpClient client = FakeHttpClient.WithResponses(responses);

            var actualError = await Assert.ThrowsAsync <Exception>(() =>
                                                                   publishTask.GetContainerIdAsync(
                                                                       client,
                                                                       PublishArtifactsInManifestBase.ArtifactName.BlobArtifacts));

            Assert.Contains($"Failed to get container id after {publishTask.RetryHandler.MaxAttempts} attempts.  See inner exception for details,", actualError.Message);
        }
示例#17
0
        public async Task DownloadFileSuccessfulAfterRetryTest(HttpStatusCode httpStatus)
        {
            var buildEngine = new MockBuildEngine();
            var publishTask = new PublishArtifactsInManifestV3
            {
                BuildEngine = buildEngine,
            };
            var testFile        = Path.Combine("Symbols", "test.txt");
            var responseContent = TestInputs.ReadAllBytes(testFile);

            publishTask.RetryHandler = new ExponentialRetry()
            {
                MaxAttempts = 2, DelayBase = 1
            };

            var responses = new[]
            {
                new HttpResponseMessage(httpStatus)
                {
                    Content = new ByteArrayContent(responseContent)
                },
                new HttpResponseMessage(HttpStatusCode.OK)
                {
                    Content = new ByteArrayContent(responseContent)
                }
            };

            using HttpClient client = FakeHttpClient.WithResponses(responses);
            var path = TestInputs.GetFullPath(Guid.NewGuid().ToString());

            await publishTask.DownloadFileAsync(
                client,
                PublishArtifactsInManifestBase.ArtifactName.BlobArtifacts,
                "1234",
                "test.txt",
                path);

            Assert.True(File.Exists(path));
            publishTask.DeleteTemporaryFiles(path);
            publishTask.DeleteTemporaryDirectory(path);
        }
        public void MissingLocationInformationThrowsError()
        {
            var localPackagePath = TestInputs.GetFullPath(Path.Combine("Nupkgs", "test-package-a.zip"));

            var artifacts = new ITaskItem[]
            {
                new TaskItem(localPackagePath, new Dictionary <string, string>
                {
                    { "ManifestArtifactData", "NonShipping=true" }
                })
            };

            _buildModelFactory.CreateModelFromItems(artifacts, null,
                                                    null, null, null, null, _testAzdoBuildId, null, _testAzdoRepoUri, _testBuildBranch, _testBuildCommit, false,
                                                    VersionTools.BuildManifest.Model.PublishingInfraVersion.Latest,
                                                    true);

            // Should have logged an error that an initial location was not present.
            _taskLoggingHelper.HasLoggedErrors.Should().BeTrue();
            _buildEngine.BuildErrorEvents.Should().Contain(e => e.Message.Equals("Missing 'location' property from ManifestBuildData"));
        }
示例#19
0
        public async Task GetContainerIdToDownloadArtifactAsync(PublishArtifactsInManifestBase.ArtifactName artifactName, string containerId)
        {
            var buildEngine = new MockBuildEngine();
            var publishTask = new PublishArtifactsInManifestV3
            {
                BuildEngine = buildEngine,
            };

            publishTask.BuildId = "1243456";
            var testPackageName = Path.Combine("Symbols", "test.txt");
            var responseContent = TestInputs.ReadAllBytes(testPackageName);
            var responses       = new HttpResponseMessage(HttpStatusCode.OK)
            {
                Content = new ByteArrayContent(responseContent)
            };

            using HttpClient client = FakeHttpClient.WithResponses(responses);
            var test = await publishTask.GetContainerIdAsync(
                client,
                artifactName);

            Assert.Equal(containerId, test);
        }
        public void RoundTripFromTaskItemsToFileToXml()
        {
            var localPackagePath = TestInputs.GetFullPath(Path.Combine("Nupkgs", "test-package-a.1.0.0.nupkg"));

            const string bopSymbolsNupkg      = "foo/bar/baz/bop.symbols.nupkg";
            string       bobSymbolsExpectedId = $"assets/symbols/{Path.GetFileName(bopSymbolsNupkg)}";
            const string bopSnupkg            = "foo/bar/baz/bop.symbols.nupkg";
            string       bopSnupkgExpectedId  = $"assets/symbols/{Path.GetFileName(bopSnupkg)}";
            const string zipArtifact          = "foo/bar/baz/bing.zip";

            var artifacts = new ITaskItem[]
            {
                new TaskItem(bopSymbolsNupkg, new Dictionary <string, string>
                {
                    { "ManifestArtifactData", "NonShipping=true;Category=SMORKELER" },
                    { "ThisIsntArtifactMetadata", "YouGoofed!" }
                }),
                new TaskItem(bopSnupkg, new Dictionary <string, string>
                {
                    { "ManifestArtifactData", "NonShipping=false;Category=SNORPKEG;" }
                }),
                // Include a package and a fake zip too
                // Note that the relative blob path is a "first class" attribute,
                // not parsed from ManifestArtifactData
                new TaskItem(zipArtifact, new Dictionary <string, string>
                {
                    { "RelativeBlobPath", zipArtifact },
                    { "ManifestArtifactData", "ARandomBitOfMAD=" },
                }),
                new TaskItem(localPackagePath, new Dictionary <string, string>()
                {
                    // This isn't recognized or used for a nupkg
                    { "RelativeBlobPath", zipArtifact },
                    { "ManifestArtifactData", "ShouldWePushDaNorpKeg=YES" },
                })
            };

            var itemsToSign = new ITaskItem[]
            {
                new TaskItem(localPackagePath),
                new TaskItem(zipArtifact)
            };

            var strongNameSignInfo = new ITaskItem[]
            {
                new TaskItem(localPackagePath, new Dictionary <string, string>()
                {
                    { "CertificateName", "IHasACert" },
                    { "PublicKeyToken", "abcdabcdabcdabcd" }
                })
            };

            var fileSignInfo = new ITaskItem[]
            {
                new TaskItem(localPackagePath, new Dictionary <string, string>()
                {
                    { "CertificateName", "IHasACert2" }
                }),
                // Added per issue: dotnet/arcade#7064
                new TaskItem("Microsoft.DiaSymReader.dll", new Dictionary <string, string>()
                {
                    { "CertificateName", "MicrosoftWin8WinBlue" },
                    { "TargetFramework", ".NETFramework,Version=v2.0" },
                    { "PublicKeyToken", "31bf3856ad364e35" }
                }),
                new TaskItem("Microsoft.DiaSymReader.dll", new Dictionary <string, string>()
                {
                    { "CertificateName", "Microsoft101240624" },
                    { "TargetFramework", ".NETStandard,Version=v1.1" },
                    { "PublicKeyToken", "31bf3856ad364e35" }
                })
            };

            var certificatesSignInfo = new ITaskItem[]
            {
                new TaskItem("MyCert", new Dictionary <string, string>()
                {
                    { "DualSigningAllowed", "false" }
                }),
                new TaskItem("MyOtherCert", new Dictionary <string, string>()
                {
                    { "DualSigningAllowed", "true" }
                })
            };

            var fileExtensionSignInfo = new ITaskItem[]
            {
                new TaskItem(".dll", new Dictionary <string, string>()
                {
                    { "CertificateName", "MyCert" }
                })
            };

            string tempXmlFile = Path.GetTempFileName();

            try
            {
                var modelFromItems = _buildModelFactory.CreateModelFromItems(artifacts, itemsToSign,
                                                                             strongNameSignInfo, fileSignInfo, fileExtensionSignInfo, certificatesSignInfo, _testAzdoBuildId,
                                                                             _defaultManifestBuildData, _testAzdoRepoUri, _testBuildBranch, _testBuildCommit, true,
                                                                             VersionTools.BuildManifest.Model.PublishingInfraVersion.Next,
                                                                             false);

                _buildModelFactory.CreateBuildManifest(
                    modelFromItems.Artifacts.Blobs,
                    modelFromItems.Artifacts.Packages,
                    tempXmlFile,
                    modelFromItems.Identity.Name,
                    modelFromItems.Identity.BuildId,
                    modelFromItems.Identity.Branch,
                    modelFromItems.Identity.Commit,
                    modelFromItems.Identity.Attributes.Select(kv => $"{kv.Key}={kv.Value}").ToArray(),
                    modelFromItems.Identity.IsStable,
                    modelFromItems.Identity.PublishingVersion,
                    modelFromItems.Identity.IsReleaseOnlyPackageVersion,
                    modelFromItems.SigningInformation);

                // Read the xml file back in and create a model from it.
                var modelFromFile = _buildModelFactory.ManifestFileToModel(tempXmlFile);

                // There will be some reordering of the attributes here (they are written to the xml file in
                // a defined order for some properties, then ordered by case).
                // As a result, this comparison isn't exactly the same as some other tests.
                _taskLoggingHelper.HasLoggedErrors.Should().BeFalse();
                modelFromItems.Identity.Name.Should().Be(_testAzdoRepoUri);
                modelFromItems.Identity.BuildId.Should().Be(_testAzdoBuildId);
                modelFromItems.Identity.Commit.Should().Be(_testBuildCommit);
                modelFromItems.Identity.PublishingVersion.Should().Be(VersionTools.BuildManifest.Model.PublishingInfraVersion.Next);
                modelFromItems.Identity.IsReleaseOnlyPackageVersion.Should().BeFalse();
                modelFromItems.Identity.IsStable.Should().BeTrue();
                modelFromFile.Artifacts.Blobs.Should().SatisfyRespectively(
                    blob =>
                {
                    blob.Id.Should().Be(bobSymbolsExpectedId);
                    blob.NonShipping.Should().BeTrue();
                    blob.Attributes.Should().Contain("Id", bobSymbolsExpectedId);
                    blob.Attributes.Should().Contain("Category", "SMORKELER");
                    blob.Attributes.Should().Contain("NonShipping", "true");
                },
                    blob =>
                {
                    blob.Id.Should().Be(bopSnupkgExpectedId);
                    blob.NonShipping.Should().BeFalse();
                    blob.Attributes.Should().Contain("Id", bopSnupkgExpectedId);
                    blob.Attributes.Should().Contain("Category", "SNORPKEG");
                    blob.Attributes.Should().Contain("NonShipping", "false");
                },
                    blob =>
                {
                    blob.Id.Should().Be(zipArtifact);
                    blob.NonShipping.Should().BeFalse();
                    blob.Attributes.Should().Contain("Id", zipArtifact);
                    blob.Attributes.Should().Contain("ARandomBitOfMAD", string.Empty);
                });

                modelFromFile.Artifacts.Packages.Should().SatisfyRespectively(
                    package =>
                {
                    package.Id.Should().Be("test-package-a");
                    package.Version.Should().Be("1.0.0");
                    package.NonShipping.Should().BeFalse();
                    package.Attributes.Should().Contain("Id", "test-package-a");
                    package.Attributes.Should().Contain("Version", "1.0.0");
                    package.Attributes.Should().Contain("ShouldWePushDaNorpKeg", "YES");
                });

                modelFromFile.SigningInformation.Should().NotBeNull();
                modelFromFile.SigningInformation.ItemsToSign.Should().SatisfyRespectively(
                    item =>
                {
                    item.Include.Should().Be("bing.zip");
                },
                    item =>
                {
                    item.Include.Should().Be("test-package-a.1.0.0.nupkg");
                });
                modelFromFile.SigningInformation.StrongNameSignInfo.Should().SatisfyRespectively(
                    item =>
                {
                    item.Include.Should().Be("test-package-a.1.0.0.nupkg");
                    item.CertificateName.Should().Be("IHasACert");
                    item.PublicKeyToken.Should().Be("abcdabcdabcdabcd");
                });
                modelFromFile.SigningInformation.FileSignInfo.Should().SatisfyRespectively(
                    item =>
                {
                    item.Include.Should().Be("Microsoft.DiaSymReader.dll");
                    item.CertificateName.Should().Be("Microsoft101240624");
                    item.TargetFramework.Should().Be(".NETStandard,Version=v1.1");
                    item.PublicKeyToken.Should().Be("31bf3856ad364e35");
                },
                    item =>
                {
                    item.Include.Should().Be("Microsoft.DiaSymReader.dll");
                    item.CertificateName.Should().Be("MicrosoftWin8WinBlue");
                    item.TargetFramework.Should().Be(".NETFramework,Version=v2.0");
                    item.PublicKeyToken.Should().Be("31bf3856ad364e35");
                },
                    item =>
                {
                    item.Include.Should().Be("test-package-a.1.0.0.nupkg");
                    item.CertificateName.Should().Be("IHasACert2");
                });
                modelFromFile.SigningInformation.CertificatesSignInfo.Should().SatisfyRespectively(
                    item =>
                {
                    item.Include.Should().Be("MyCert");
                    item.DualSigningAllowed.Should().Be(false);
                },
                    item =>
                {
                    item.Include.Should().Be("MyOtherCert");
                    item.DualSigningAllowed.Should().Be(true);
                });
                modelFromFile.SigningInformation.FileExtensionSignInfo.Should().SatisfyRespectively(
                    item =>
                {
                    item.Include.Should().Be(".dll");
                    item.CertificateName.Should().Be("MyCert");
                });
            }
            finally
            {
                if (File.Exists(tempXmlFile))
                {
                    File.Delete(tempXmlFile);
                }
            }
        }
        public void SignInfoIsCorrectlyPopulatedFromItems()
        {
            var localPackagePath = TestInputs.GetFullPath(Path.Combine("Nupkgs", "test-package-a.1.0.0.nupkg"));
            var zipPath          = @"this/is/a/zip.zip";

            var artifacts = new ITaskItem[]
            {
                new TaskItem(localPackagePath, new Dictionary <string, string>()),
                new TaskItem(zipPath, new Dictionary <string, string>()
                {
                    { "RelativeBlobPath", zipPath },
                })
            };

            var itemsToSign = new ITaskItem[]
            {
                new TaskItem(localPackagePath),
                new TaskItem(zipPath)
            };

            var strongNameSignInfo = new ITaskItem[]
            {
                new TaskItem(localPackagePath, new Dictionary <string, string>()
                {
                    { "CertificateName", "IHasACert" },
                    { "PublicKeyToken", "abcdabcdabcdabcd" }
                })
            };

            var fileSignInfo = new ITaskItem[]
            {
                new TaskItem(localPackagePath, new Dictionary <string, string>()
                {
                    { "CertificateName", "IHasACert2" }
                })
            };

            var certificatesSignInfo = new ITaskItem[]
            {
                new TaskItem("MyCert", new Dictionary <string, string>()
                {
                    { "DualSigningAllowed", "false" }
                }),
                new TaskItem("MyOtherCert", new Dictionary <string, string>()
                {
                    { "DualSigningAllowed", "true" }
                })
            };

            var fileExtensionSignInfo = new ITaskItem[]
            {
                new TaskItem(".dll", new Dictionary <string, string>()
                {
                    { "CertificateName", "MyCert" }
                })
            };

            var model = _buildModelFactory.CreateModelFromItems(artifacts, itemsToSign,
                                                                strongNameSignInfo, fileSignInfo, fileExtensionSignInfo, certificatesSignInfo,
                                                                _testAzdoBuildId, _defaultManifestBuildData, _testAzdoRepoUri, _testBuildBranch, _testBuildCommit, false,
                                                                VersionTools.BuildManifest.Model.PublishingInfraVersion.All,
                                                                true);

            _taskLoggingHelper.HasLoggedErrors.Should().BeFalse();
            model.SigningInformation.Should().NotBeNull();
            model.SigningInformation.ItemsToSign.Should().SatisfyRespectively(
                item =>
            {
                item.Include.Should().Be("test-package-a.1.0.0.nupkg");
            },
                item =>
            {
                item.Include.Should().Be("zip.zip");
            });
            model.SigningInformation.StrongNameSignInfo.Should().SatisfyRespectively(
                item =>
            {
                item.Include.Should().Be("test-package-a.1.0.0.nupkg");
                item.CertificateName.Should().Be("IHasACert");
                item.PublicKeyToken.Should().Be("abcdabcdabcdabcd");
            });
            model.SigningInformation.FileSignInfo.Should().SatisfyRespectively(
                item =>
            {
                item.Include.Should().Be("test-package-a.1.0.0.nupkg");
                item.CertificateName.Should().Be("IHasACert2");
            });
            model.SigningInformation.CertificatesSignInfo.Should().SatisfyRespectively(
                item =>
            {
                item.Include.Should().Be("MyCert");
                item.DualSigningAllowed.Should().Be(false);
            },
                item =>
            {
                item.Include.Should().Be("MyOtherCert");
                item.DualSigningAllowed.Should().Be(true);
            });
            model.SigningInformation.FileExtensionSignInfo.Should().SatisfyRespectively(
                item =>
            {
                item.Include.Should().Be(".dll");
                item.CertificateName.Should().Be("MyCert");
            });
        }
        public void ManifestArtifactParsingTest()
        {
            var localPackagePath = TestInputs.GetFullPath(Path.Combine("Nupkgs", "test-package-a.1.0.0.nupkg"));

            const string bopSymbolsNupkg      = "foo/bar/baz/bop.symbols.nupkg";
            string       bobSymbolsExpectedId = $"assets/symbols/{Path.GetFileName(bopSymbolsNupkg)}";
            const string bopSnupkg            = "foo/bar/baz/bop.symbols.nupkg";
            string       bopSnupkgExpectedId  = $"assets/symbols/{Path.GetFileName(bopSnupkg)}";
            const string zipArtifact          = "foo/bar/baz/bing.zip";

            var artifacts = new ITaskItem[]
            {
                new TaskItem(bopSymbolsNupkg, new Dictionary <string, string>
                {
                    { "ManifestArtifactData", "NonShipping=true;Category=SMORKELER" },
                    { "ThisIsntArtifactMetadata", "YouGoofed!" }
                }),
                new TaskItem(bopSnupkg, new Dictionary <string, string>
                {
                    { "ManifestArtifactData", "NonShipping=false;Category=SNORPKEG;" }
                }),
                // Include a package and a fake zip too
                // Note that the relative blob path is a "first class" attribute,
                // not parsed from ManifestArtifactData
                new TaskItem(zipArtifact, new Dictionary <string, string>
                {
                    { "RelativeBlobPath", zipArtifact },
                    { "ManifestArtifactData", "ARandomBitOfMAD=" },
                }),
                new TaskItem(localPackagePath, new Dictionary <string, string>()
                {
                    // This isn't recognized or used for a nupkg
                    { "RelativeBlobPath", zipArtifact },
                    { "ManifestArtifactData", "ShouldWePushDaNorpKeg=YES" },
                })
            };

            var model = _buildModelFactory.CreateModelFromItems(artifacts, null,
                                                                null, null, null, null, _testAzdoBuildId, _defaultManifestBuildData, _testAzdoRepoUri, _testBuildBranch, _testBuildCommit, false,
                                                                VersionTools.BuildManifest.Model.PublishingInfraVersion.All,
                                                                true);

            _taskLoggingHelper.HasLoggedErrors.Should().BeFalse();
            // When Maestro sees a symbol package, it is supposed to re-do the symbol package path to
            // be assets/symbols/<file-name>
            model.Artifacts.Blobs.Should().SatisfyRespectively(
                blob =>
            {
                blob.Id.Should().Be(bobSymbolsExpectedId);
                blob.NonShipping.Should().BeTrue();
                blob.Attributes.Should().Contain("NonShipping", "true");
                blob.Attributes.Should().Contain("Category", "SMORKELER");
                blob.Attributes.Should().Contain("Id", bobSymbolsExpectedId);
            },
                blob =>
            {
                blob.Id.Should().Be(bopSnupkgExpectedId);
                blob.NonShipping.Should().BeFalse();
                blob.Attributes.Should().Contain("NonShipping", "false");
                blob.Attributes.Should().Contain("Category", "SNORPKEG");
                blob.Attributes.Should().Contain("Id", bopSnupkgExpectedId);
            },
                blob =>
            {
                blob.Id.Should().Be(zipArtifact);
                blob.NonShipping.Should().BeFalse();
                blob.Attributes.Should().Contain("ARandomBitOfMAD", string.Empty);
                blob.Attributes.Should().Contain("Id", zipArtifact);
            });

            model.Artifacts.Packages.Should().SatisfyRespectively(
                package =>
            {
                package.Id.Should().Be("test-package-a");
                package.Version.Should().Be("1.0.0");
                package.NonShipping.Should().BeFalse();
                package.Attributes.Should().Contain("ShouldWePushDaNorpKeg", "YES");
                package.Attributes.Should().Contain("Id", "test-package-a");
                package.Attributes.Should().Contain("Version", "1.0.0");
            });

            model.Identity.Attributes.Should().Contain("AzureDevOpsRepository", _normalizedTestAzdoRepoUri);
        }