public async Task UpdateStateAsync(IProgress <IItemLoaderState> progress, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); SearchResultContextInfo searchResult = await _searchService.RefreshSearchAsync(cancellationToken); cancellationToken.ThrowIfCancellationRequested(); await UpdateStateAndReportAsync(searchResult, progress, cancellationToken); }
public async Task GetCurrent_WithAnySearchResults_PreservesSearchResultsOrderAsync(string[] inputIds) { // Arrange var psmContextInfos = new List <PackageSearchMetadataContextInfo>(); foreach (var id in inputIds) { psmContextInfos.Add(PackageSearchMetadataContextInfo.Create(new PackageSearchMetadataBuilder.ClonedPackageSearchMetadata() { Identity = new PackageIdentity(id, new NuGetVersion("1.0")), })); } var searchResult = new SearchResultContextInfo(psmContextInfos, new Dictionary <string, LoadingStatus> { { "Search", LoadingStatus.Loading } }, hasMoreItems: false); var serviceBroker = Mock.Of <IServiceBroker>(); var packageFileService = new Mock <INuGetPackageFileService>(); var searchService = new Mock <IReconnectingNuGetSearchService>(MockBehavior.Strict); searchService.Setup(s => s.SearchAsync(It.IsAny <IReadOnlyCollection <IProjectContextInfo> >(), It.IsAny <IReadOnlyCollection <PackageSourceContextInfo> >(), It.IsAny <IReadOnlyCollection <string> >(), It.IsAny <string>(), It.IsAny <SearchFilter>(), It.IsAny <NuGet.VisualStudio.Internal.Contracts.ItemFilter>(), It.IsAny <bool>(), It.IsAny <bool>(), It.IsAny <CancellationToken>())) .Returns(new ValueTask <SearchResultContextInfo>(searchResult)); var uiContext = new Mock <INuGetUIContext>(); uiContext.Setup(ui => ui.ServiceBroker).Returns(serviceBroker); var context = new PackageLoadContext(isSolution: false, uiContext.Object); var mockProgress = Mock.Of <IProgress <IItemLoaderState> >(); using var localFeedDir = TestDirectory.Create(); // local feed var localSource = new PackageSource(localFeedDir); var loader = await PackageItemLoader.CreateAsync( serviceBroker, context, new List <PackageSourceContextInfo>() { PackageSourceContextInfo.Create(localSource) }, NuGet.VisualStudio.Internal.Contracts.ItemFilter.All, searchService.Object, packageFileService.Object, TestSearchTerm); // Act await loader.LoadNextAsync(progress : mockProgress, CancellationToken.None); IEnumerable <PackageItemViewModel> items = loader.GetCurrent(); // Assert string[] result = items.Select(pkg => pkg.Id).ToArray(); Assert.Equal(inputIds, result); }
public async Task UpdateStateAsync(IProgress <IItemLoaderState> progress, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); NuGetEventTrigger.Instance.TriggerEvent(NuGetEvent.PackageLoadBegin); progress?.Report(_state); SearchResultContextInfo searchResult = await _searchService.RefreshSearchAsync(cancellationToken); cancellationToken.ThrowIfCancellationRequested(); await UpdateStateAndReportAsync(searchResult, progress, cancellationToken); NuGetEventTrigger.Instance.TriggerEvent(NuGetEvent.PackageLoadEnd); }
public void SerializeThenDeserialize_WithValidArguments_RoundTrips(SearchResultContextInfo expectedResult) { var formatters = new IMessagePackFormatter[] { PackageSearchMetadataContextInfoFormatter.Instance, PackageVulnerabilityMetadataContextInfoFormatter.Instance, }; var resolvers = new IFormatterResolver[] { MessagePackSerializerOptions.Standard.Resolver }; var options = MessagePackSerializerOptions.Standard.WithSecurity(MessagePackSecurity.UntrustedData).WithResolver(CompositeResolver.Create(formatters, resolvers)); SearchResultContextInfo actualResult = SerializeThenDeserialize(SearchResultContextInfoFormatter.Instance, expectedResult, options); Assert.Equal(expectedResult.OperationId, actualResult.OperationId); Assert.Equal(expectedResult.HasMoreItems, actualResult.HasMoreItems); Assert.Equal(expectedResult.SourceLoadingStatus, actualResult.SourceLoadingStatus); Assert.Equal(expectedResult.PackageSearchItems.Count, actualResult.PackageSearchItems.Count); }
public async Task LoadNextAsync(IProgress <IItemLoaderState> progress, CancellationToken cancellationToken) { ActivityCorrelationId.StartNew(); cancellationToken.ThrowIfCancellationRequested(); await UpdateStateAndReportAsync( new SearchResultContextInfo(Array.Empty <PackageSearchMetadataContextInfo>(), ImmutableDictionary <string, LoadingStatus> .Empty, hasMoreItems : _state.Results?.HasMoreItems ?? false), progress, cancellationToken); SearchResultContextInfo searchResult = await SearchAsync(cancellationToken); cancellationToken.ThrowIfCancellationRequested(); await UpdateStateAndReportAsync(searchResult, progress, cancellationToken); }
public async ValueTask <IReadOnlyCollection <PackageSearchMetadataContextInfo> > GetAllPackagesAsync(SearchFilter searchFilter, CancellationToken cancellationToken) { var packages = new List <PackageSearchMetadataContextInfo>(); do { SearchResultContextInfo searchResult = _lastMainFeedSearchResult?.NextToken != null ? await ContinueSearchAsync(cancellationToken) : await SearchAsync(string.Empty, searchFilter, useRecommender : false, cancellationToken); if (_lastMainFeedSearchResult?.RefreshToken != null) { searchResult = await RefreshSearchAsync(cancellationToken); } packages.AddRange(searchResult.PackageSearchItems); } while (_lastMainFeedSearchResult?.NextToken != null); return(packages); }
public async Task UpdateStateAndReportAsync(SearchResultContextInfo searchResult, IProgress <IItemLoaderState> progress, CancellationToken cancellationToken) { // cache installed packages here for future use _installedPackages = await _context.GetInstalledPackagesAsync(); // fetch package references from all the projects and cache locally // for solution view, we'll always show the highest available version // but for project view, get the allowed version range and pass it to package item view model to choose the latest version based on that if (_packageReferences == null && !_context.IsSolution) { IEnumerable <Task <IReadOnlyCollection <IPackageReferenceContextInfo> > > tasks = _context.Projects .Select(project => project.GetInstalledPackagesAsync( _context.ServiceBroker, cancellationToken).AsTask()); _packageReferences = (await Task.WhenAll(tasks)).SelectMany(p => p).Where(p => p != null); } var state = new PackageFeedSearchState(searchResult); _state = state; progress?.Report(state); }
public async Task MultipleSourcesPrefixReserved_Works() { var solutionManager = Mock.Of <INuGetSolutionManagerService>(); var uiContext = new Mock <INuGetUIContext>(); var searchService = new Mock <INuGetSearchService>(MockBehavior.Strict); var packageSearchMetadata = new PackageSearchMetadataBuilder.ClonedPackageSearchMetadata() { Identity = new PackageIdentity("NuGet.org", new NuGetVersion("1.0")), PrefixReserved = true }; var packageSearchMetadataContextInfo = new List <PackageSearchMetadataContextInfo>() { PackageSearchMetadataContextInfo.Create(packageSearchMetadata) }; var searchResult = new SearchResultContextInfo(packageSearchMetadataContextInfo, new Dictionary <string, LoadingStatus> { { "Completed", LoadingStatus.Ready } }, false); searchService.Setup(x => x.SearchAsync( It.IsAny <IReadOnlyCollection <IProjectContextInfo> >(), It.IsAny <IReadOnlyCollection <PackageSourceContextInfo> >(), It.IsAny <IReadOnlyCollection <string> >(), It.IsAny <string>(), It.IsAny <SearchFilter>(), It.IsAny <NuGet.VisualStudio.Internal.Contracts.ItemFilter>(), It.IsAny <bool>(), It.IsAny <CancellationToken>())) .Returns(new ValueTask <SearchResultContextInfo>(searchResult)); searchService.Setup(x => x.RefreshSearchAsync(It.IsAny <CancellationToken>())) .Returns(new ValueTask <SearchResultContextInfo>(searchResult)); uiContext.Setup(x => x.SolutionManagerService) .Returns(solutionManager); uiContext.Setup(x => x.ServiceBroker) .Returns(Mock.Of <IServiceBroker>()); var source1 = new PackageSourceContextInfo("https://pkgs.dev.azure.com/dnceng/public/_packaging/nuget-build/nuget/v3/index.json", "NuGetBuild"); var source2 = new PackageSourceContextInfo("https://api.nuget.org/v3/index.json", "NuGet.org"); var context = new PackageLoadContext(false, uiContext.Object); var loader = await PackageItemLoader.CreateAsync( Mock.Of <IServiceBroker>(), context, new List <PackageSourceContextInfo> { source1, source2 }, NuGet.VisualStudio.Internal.Contracts.ItemFilter.All, searchService.Object, TestSearchTerm); await loader.LoadNextAsync(null, CancellationToken.None); var items = loader.GetCurrent(); Assert.NotEmpty(items); // All items should not have a prefix reserved because the feed is multisource foreach (var item in items) { Assert.False(item.PrefixReserved); } }
public async Task PackageReader_NotNull() { // Prepare var solutionManager = Mock.Of <INuGetSolutionManagerService>(); var uiContext = new Mock <INuGetUIContext>(); uiContext.Setup(x => x.SolutionManagerService) .Returns(solutionManager); var searchService = new Mock <INuGetSearchService>(MockBehavior.Strict); var packageSearchMetadata = new PackageSearchMetadataBuilder.ClonedPackageSearchMetadata() { Identity = new PackageIdentity("NuGet.org", new NuGetVersion("1.0")), PrefixReserved = true }; var packageSearchMetadataContextInfo = new List <PackageSearchMetadataContextInfo>() { PackageSearchMetadataContextInfo.Create(packageSearchMetadata) }; var searchResult = new SearchResultContextInfo(packageSearchMetadataContextInfo, new Dictionary <string, LoadingStatus> { { "Search", LoadingStatus.Loading } }, false); searchService.Setup(x => x.SearchAsync( It.IsAny <IReadOnlyCollection <IProjectContextInfo> >(), It.IsAny <IReadOnlyCollection <PackageSourceContextInfo> >(), It.IsAny <IReadOnlyCollection <string> >(), It.IsAny <string>(), It.IsAny <SearchFilter>(), It.IsAny <NuGet.VisualStudio.Internal.Contracts.ItemFilter>(), It.IsAny <bool>(), It.IsAny <CancellationToken>())) .Returns(new ValueTask <SearchResultContextInfo>(searchResult)); uiContext.Setup(x => x.ServiceBroker) .Returns(Mock.Of <IServiceBroker>()); using (var localFeedDir = TestDirectory.Create()) // local feed { // create test package var pkgId = new PackageIdentity("nuget.lpsm.test", new NuGetVersion(0, 0, 1)); var pkg = new SimpleTestPackageContext(pkgId.Id, pkgId.Version.ToNormalizedString()); await SimpleTestPackageUtility.CreatePackagesAsync(localFeedDir.Path, pkg); // local test source var localUri = new Uri(localFeedDir.Path, UriKind.Absolute); var localSource = new PackageSource(localUri.ToString(), "LocalSource"); var sourceRepositoryProvider = TestSourceRepositoryUtility.CreateSourceRepositoryProvider(new[] { localSource }); var repositories = sourceRepositoryProvider.GetRepositories(); var context = new PackageLoadContext(isSolution: false, uiContext.Object); var packageFeed = new MultiSourcePackageFeed(repositories, logger: null, telemetryService: null); var loader = await PackageItemLoader.CreateAsync( Mock.Of <IServiceBroker>(), context, new List <PackageSourceContextInfo> { PackageSourceContextInfo.Create(localSource) }, NuGet.VisualStudio.Internal.Contracts.ItemFilter.All, searchService.Object, TestSearchTerm); // Act await loader.LoadNextAsync(progress : null, CancellationToken.None); var results = loader.GetCurrent(); // Assert Assert.Single(results); Assert.NotNull(results.First().PackageReader); } }
public PackageFeedSearchState(SearchResultContextInfo results) { _results = results ?? throw new ArgumentNullException(nameof(results)); }
public async Task PackagePrefixReservation_FromMultiSource() { var solutionManager = Mock.Of <INuGetSolutionManagerService>(); var uiContext = new Mock <INuGetUIContext>(); var searchService = Mock.Of <INuGetSearchService>(); var packageFileService = Mock.Of <INuGetPackageFileService>(); uiContext.Setup(x => x.SolutionManagerService) .Returns(solutionManager); uiContext.Setup(x => x.ServiceBroker) .Returns(Mock.Of <IServiceBroker>()); // Arrange var responses = new Dictionary <string, string> { { "https://api-v3search-0.nuget.org/query?q=EntityFramework&skip=0&take=26&prerelease=false&semVerLevel=2.0.0", ProtocolUtility.GetResource("NuGet.PackageManagement.UI.Test.compiler.resources.EntityFrameworkSearch.json", GetType()) }, { "http://testsource.com/v3/index.json", JsonData.IndexWithoutFlatContainer }, { "http://othersource.com/v3/index.json", JsonData.IndexWithoutFlatContainer } }; var repo = StaticHttpHandler.CreateSource("http://testsource.com/v3/index.json", Repository.Provider.GetCoreV3(), responses); var repo1 = StaticHttpHandler.CreateSource("http://othersource.com/v3/index.json", Repository.Provider.GetCoreV3(), responses); var context = new PackageLoadContext(isSolution: false, uiContext.Object); var loader = await PackageItemLoader.CreateAsync( Mock.Of <IServiceBroker>(), context, new List <PackageSourceContextInfo> { PackageSourceContextInfo.Create(repo.PackageSource), PackageSourceContextInfo.Create(repo1.PackageSource) }, NuGet.VisualStudio.Internal.Contracts.ItemFilter.All, searchService, packageFileService, "EntityFramework", includePrerelease : false); var packageSearchMetadata = new PackageSearchMetadataBuilder.ClonedPackageSearchMetadata() { Identity = new PackageIdentity("NuGet.org", new NuGetVersion("1.0")), PrefixReserved = true }; var packageSearchMetadataContextInfo = new List <PackageSearchMetadataContextInfo>() { PackageSearchMetadataContextInfo.Create(packageSearchMetadata) }; var searchResult = new SearchResultContextInfo( packageSearchMetadataContextInfo, new Dictionary <string, LoadingStatus> { { "Completed", LoadingStatus.Ready } }, hasMoreItems: false); await loader.UpdateStateAndReportAsync(searchResult, progress : null, CancellationToken.None); var items = loader.GetCurrent(); // Resource only has one item var item = items.First(); // Assert that a multisource always has prefixreserved set to false Assert.False(item.PrefixReserved); }
public async Task ContinueSearchAsync_WhenSearchIsContinuable_Continues() { var telemetryService = new Mock <INuGetTelemetryService>(); var eventsQueue = new ConcurrentQueue <TelemetryEvent>(); telemetryService .Setup(x => x.EmitTelemetryEvent(It.IsAny <TelemetryEvent>())) .Callback <TelemetryEvent>(e => eventsQueue.Enqueue(e)); TelemetryActivity.NuGetTelemetryService = telemetryService.Object; using (NuGetPackageSearchService searchService = SetupSearchService()) { SearchResultContextInfo searchResult = await searchService.SearchAsync( _projects, new List <PackageSourceContextInfo> { PackageSourceContextInfo.Create(_sourceRepository.PackageSource) }, targetFrameworks : new List <string>() { "net45", "net5.0" }, searchText : "nuget", new SearchFilter(includePrerelease : true), NuGet.VisualStudio.Internal.Contracts.ItemFilter.All, useRecommender : true, CancellationToken.None); SearchResultContextInfo continueSearchResult = await searchService.ContinueSearchAsync(CancellationToken.None); Assert.True(searchResult.PackageSearchItems.First().Title.Equals("NuGet.Core1", StringComparison.OrdinalIgnoreCase)); Assert.True(continueSearchResult.PackageSearchItems.First().Title.Equals("NuGet.Core27", StringComparison.OrdinalIgnoreCase)); TelemetryEvent[] events = eventsQueue.ToArray(); Assert.True(4 == events.Length, string.Join(Environment.NewLine, events.Select(e => e.Name))); TelemetryEvent search = Assert.Single(events, e => e.Name == "Search"); Assert.Equal(true, search["IncludePrerelease"]); Assert.Equal("nuget", search.GetPiiData().First(p => p.Key == "Query").Value); string operationId = Assert.IsType <string>(search["OperationId"]); Guid parsedOperationId = Guid.ParseExact(operationId, "D"); TelemetryEvent sources = Assert.Single(events, e => e.Name == "SearchPackageSourceSummary"); Assert.Equal(1, sources["NumHTTPv3Feeds"]); Assert.Equal("NotPresent", sources["NuGetOrg"]); Assert.Equal(operationId, sources["ParentId"]); TelemetryEvent page0 = Assert.Single(events, e => e.Name == "SearchPage" && e["PageIndex"] is int && (int)e["PageIndex"] == 0); Assert.Equal("Ready", page0["LoadingStatus"]); Assert.Equal(operationId, page0["ParentId"]); Assert.IsType <int>(page0["ResultCount"]); Assert.IsType <double>(page0["Duration"]); Assert.IsType <double>(page0["ResultsAggregationDuration"]); Assert.IsType <string>(page0["IndividualSourceDurations"]); Assert.Equal(1, ((JArray)JsonConvert.DeserializeObject((string)page0["IndividualSourceDurations"])).Values <double>().Count()); TelemetryEvent page1 = Assert.Single(events, e => e.Name == "SearchPage" && e["PageIndex"] is int && (int)e["PageIndex"] == 1); Assert.Equal("Ready", page1["LoadingStatus"]); Assert.Equal(operationId, page1["ParentId"]); Assert.IsType <int>(page1["ResultCount"]); Assert.IsType <double>(page1["Duration"]); Assert.IsType <double>(page1["ResultsAggregationDuration"]); Assert.IsType <string>(page1["IndividualSourceDurations"]); Assert.Equal(1, ((JArray)JsonConvert.DeserializeObject((string)page1["IndividualSourceDurations"])).Values <double>().Count()); } }