public async Task SearchAsync_WithLocalMetadata_SucceedsAsync()
        {
            // Arrange
            IEnumerable <PackageCollectionItem> installedPackages = new List <PackageCollectionItem>()
            {
                new PackageCollectionItem("packageA", NuGetVersion.Parse("1.0.0"), new List <IPackageReferenceContextInfo>()
                {
                    new PackageReferenceContextInfo(new PackageIdentity("packageA", NuGetVersion.Parse("1.0.0")), NuGetFramework.Parse("net6.0"))
                })
            };
            IEnumerable <PackageCollectionItem> transitivePackages = new List <PackageCollectionItem>()
            {
                new PackageCollectionItem("transitivePackageA", NuGetVersion.Parse("0.0.1"), new List <IPackageReferenceContextInfo>()
                {
                    new PackageReferenceContextInfo(new PackageIdentity("transitivePackageA", NuGetVersion.Parse("0.0.1")), NuGetFramework.Parse("net6.0"))
                })
            };
            var provider = Mock.Of <IPackageMetadataProvider>();

            Mock.Get(provider)
            .Setup(x => x.GetLocalPackageMetadataAsync(It.IsAny <PackageIdentity>(), It.IsAny <bool>(), It.IsAny <CancellationToken>()))
            .Returns(() => Task.FromResult(FromIdentity(new PackageIdentity("packageA", NuGetVersion.Parse("1.0.0"))).Build()));
            var feed = new InstalledAndTransitivePackageFeed(installedPackages, transitivePackages, provider);

            // Act
            SearchResult <IPackageSearchMetadata> result = await feed.SearchAsync(string.Empty, new SearchFilter(false), CancellationToken.None);

            // Assert
            Assert.Equal(1, result.Items.Count); // Transitive packages with no transitive origins data are not included in search results
        }
        public void Constructor_WithNullArgument_Throws()
        {
            Assert.Throws <ArgumentNullException>(() =>
            {
                var feed = new InstalledAndTransitivePackageFeed(
                    installedPackages: null,
                    transitivePackages: It.IsAny <IEnumerable <PackageCollectionItem> >(),
                    metadataProvider: It.IsAny <IPackageMetadataProvider>());
            });

            Assert.Throws <ArgumentNullException>(() =>
            {
                var feed = new InstalledAndTransitivePackageFeed(
                    installedPackages: It.IsAny <IEnumerable <PackageCollectionItem> >(),
                    transitivePackages: null,
                    metadataProvider: It.IsAny <IPackageMetadataProvider>());
            });

            Assert.Throws <ArgumentNullException>(() =>
            {
                var feed = new InstalledAndTransitivePackageFeed(
                    installedPackages: It.IsAny <IEnumerable <PackageCollectionItem> >(),
                    transitivePackages: It.IsAny <IEnumerable <PackageCollectionItem> >(),
                    metadataProvider: null);
            });
        }
        public async Task GetPackageMetadataAsync_WithCancellationToken_ThrowsAsync()
        {
            var testPackageIdentity    = new PackageCollectionItem("FakePackage", new NuGetVersion("1.0.0"), null);
            var testTransitiveIdentity = new PackageCollectionItem("TransitiveFakePackage", new NuGetVersion("1.0.0"), null);
            var _target = new InstalledAndTransitivePackageFeed(new[] { testPackageIdentity }, new[] { testTransitiveIdentity }, _packageMetadataProvider);

            using CancellationTokenSource cts = new CancellationTokenSource();
            cts.Cancel();
            await Assert.ThrowsAsync <OperationCanceledException>(async() => await _target.GetPackageMetadataAsync(It.IsAny <PackageIdentity>(), It.IsAny <bool>(), cts.Token));

            await Assert.ThrowsAsync <OperationCanceledException>(async() => await _target.GetPackageMetadataAsync(It.IsAny <PackageCollectionItem>(), It.IsAny <bool>(), cts.Token));
        }
        public async Task SearchAsync_WithTransitiveData_SucceedsAsync()
        {
            IEnumerable <PackageCollectionItem> installedPackages = new List <PackageCollectionItem>()
            {
                new PackageCollectionItem("packageA", NuGetVersion.Parse("1.0.0"), new List <IPackageReferenceContextInfo>()
                {
                    new PackageReferenceContextInfo(new PackageIdentity("packageA", NuGetVersion.Parse("1.0.0")), NuGetFramework.Parse("net6.0"))
                })
            };

            IEnumerable <PackageCollectionItem> transitivePackages = new List <PackageCollectionItem>()
            {
                new PackageCollectionItem("transitivePackageA", NuGetVersion.Parse("0.0.1"), new List <IPackageReferenceContextInfo>()
                {
                    new TransitivePackageReferenceContextInfo(new PackageIdentity("transitivePackageA", NuGetVersion.Parse("0.0.1")), NuGetFramework.Parse("net6.0"))
                    {
                        TransitiveOrigins = new[]
                        {
                            new PackageReferenceContextInfo(new PackageIdentity("packageA", NuGetVersion.Parse("1.0.0")), NuGetFramework.Parse("net6.0")),
                        }
                    }
                }),
            };

            var metadataProvider = Mock.Of <IPackageMetadataProvider>();

            Mock.Get(metadataProvider)
            .Setup(x => x.GetLocalPackageMetadataAsync(It.IsAny <PackageIdentity>(), It.IsAny <bool>(), It.IsAny <CancellationToken>()))
            .Returns(() => Task.FromResult(FromIdentity(new PackageIdentity("packageA", NuGetVersion.Parse("1.0.0"))).Build()));
            Mock.Get(metadataProvider)
            .Setup(m => m.GetPackageMetadataAsync(It.IsAny <PackageIdentity>(), It.IsAny <bool>(), It.IsAny <CancellationToken>()))
            .Returns(() => Task.FromResult(FromIdentity(new PackageIdentity("transitivePackageA", NuGetVersion.Parse("0.0.1"))).Build()));

            var feed = new InstalledAndTransitivePackageFeed(installedPackages, transitivePackages, metadataProvider);

            // Act
            SearchResult <IPackageSearchMetadata> result = await feed.SearchAsync("", new SearchFilter(false), CancellationToken.None);

            // Asert
            Assert.Equal(2, result.Items.Count);

            Assert.Collection(result.Items,
                              elem => Assert.IsType <ClonedPackageSearchMetadata>(elem),
                              elem => Assert.IsType <TransitivePackageSearchMetadata>(elem));
        }
        public async Task SearchAsync_WithInstalledAndTransitivePackages_AlwaysInstalledPackagesFirstThenTransitivePackagesAsync(string[] installedPkgs, string[] transitivePkgs, string query, int expectedInstalledCount, int expectedTransitiveCount)
        {
            // Arrange
            var installedCollection = installedPkgs
                                      .Select(p => new PackageCollectionItem(p, new NuGetVersion("0.0.1"), installedReferences: null));
            var transitiveCollection = transitivePkgs
                                       .Select(p => new PackageCollectionItem(p, new NuGetVersion("1.0.0"), installedReferences: new[]
            {
                new TransitivePackageReferenceContextInfo(new PackageIdentity(p, new NuGetVersion("1.0.0")), NuGetFramework.AnyFramework)
                {
                    TransitiveOrigins = new[]
                    {
                        new PackageReferenceContextInfo(new PackageIdentity("pkgOrigin", new NuGetVersion("1.1.1")), NuGetFramework.AnyFramework)
                    }
                }
            }));
            var _target = new InstalledAndTransitivePackageFeed(installedCollection, transitiveCollection, _packageMetadataProvider);

            // Act
            SearchResult <IPackageSearchMetadata> results = await _target.SearchAsync(query, new SearchFilter(includePrerelease : false), CancellationToken.None);

            // Assert
            Assert.Equal(results.Items.Count, results.RawItemsCount);
            Assert.Equal(expectedInstalledCount + expectedTransitiveCount, results.Items.Count);

            var idComparer = Comparer <IPackageSearchMetadata> .Create((a, b) => a.Identity.Id.CompareTo(b.Identity.Id));

            // First elements should be Installed/Top-level packaages
            IEnumerable <IPackageSearchMetadata> firstItems = results.Take(expectedInstalledCount);

            firstItems.Should().HaveCount(expectedInstalledCount);
            firstItems.Should().BeInAscendingOrder(idComparer);
            firstItems.Should().NotBeAssignableTo <TransitivePackageSearchMetadata>();

            // Then, last elements should be Transitive packaages
            IEnumerable <IPackageSearchMetadata> lastItems = results.Skip(expectedInstalledCount);

            lastItems.Should().HaveCount(expectedTransitiveCount);
            lastItems.Should().BeInAscendingOrder(idComparer);
            lastItems.Should().AllBeOfType <TransitivePackageSearchMetadata>();
        }
        public async Task SearchAsync_WithRemoteMetadata_SucceedsAsync()
        {
            // Arrange
            IEnumerable <PackageCollectionItem> installedPackages = new List <PackageCollectionItem>()
            {
                new PackageCollectionItem("packageA", NuGetVersion.Parse("1.0.0"), new List <IPackageReferenceContextInfo>()
                {
                    new PackageReferenceContextInfo(new PackageIdentity("packageA", NuGetVersion.Parse("1.0.0")), NuGetFramework.Parse("net6.0"))
                })
            };

            IEnumerable <PackageCollectionItem> transitivePackages = Array.Empty <PackageCollectionItem>();

            var feed = new InstalledAndTransitivePackageFeed(installedPackages, transitivePackages, _packageMetadataProvider);

            // Act
            SearchResult <IPackageSearchMetadata> result = await feed.SearchAsync("", new SearchFilter(false), CancellationToken.None);

            // Asert
            Assert.Equal(1, result.Items.Count);
        }