From 9200646c1631e5afb705d4db3a2294f27c04e2c5 Mon Sep 17 00:00:00 2001 From: Scott Bommarito Date: Fri, 7 Jun 2019 17:20:41 -0700 Subject: [PATCH] Deprecation metadata should only be present in SemVer 2.0.0 hive (#546) --- .../Registration/RegistrationCollector.cs | 36 ++++++++-- src/Catalog/Registration/RegistrationMaker.cs | 4 +- .../RegistrationMakerCatalogItem.cs | 25 +++++-- .../Registration/RegistrationPersistence.cs | 72 +++++++++++++++---- src/Ng/Jobs/LightningJob.cs | 25 ++++--- .../RegistrationMakerCatalogItemTests.cs | 67 ++++++++++------- .../Registration/RegistrationMakerTests.cs | 60 +++++++++++----- 7 files changed, 215 insertions(+), 74 deletions(-) diff --git a/src/Catalog/Registration/RegistrationCollector.cs b/src/Catalog/Registration/RegistrationCollector.cs index d3f783f15..40123f56c 100644 --- a/src/Catalog/Registration/RegistrationCollector.cs +++ b/src/Catalog/Registration/RegistrationCollector.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Net.Http; using System.Threading; using System.Threading.Tasks; @@ -24,7 +25,8 @@ public class RegistrationCollector : SortingGraphCollector private readonly StorageFactory _legacyStorageFactory; private readonly StorageFactory _semVer2StorageFactory; - private readonly ShouldIncludeRegistrationPackage _shouldIncludeSemVer2; + private readonly ShouldIncludeRegistrationPackage _shouldIncludeSemVer2ForLegacyStorageFactory; + private readonly RegistrationMakerCatalogItem.PostProcessGraph _postProcessGraphForLegacyStorageFactory; private readonly int _maxConcurrentBatches; private readonly ILogger _logger; @@ -49,7 +51,8 @@ public RegistrationCollector( _legacyStorageFactory = legacyStorageFactory ?? throw new ArgumentNullException(nameof(legacyStorageFactory)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _semVer2StorageFactory = semVer2StorageFactory; - _shouldIncludeSemVer2 = GetShouldIncludeRegistrationPackage(_semVer2StorageFactory); + _shouldIncludeSemVer2ForLegacyStorageFactory = GetShouldIncludeRegistrationPackageForLegacyStorageFactory(_semVer2StorageFactory); + _postProcessGraphForLegacyStorageFactory = GetPostProcessGraphForLegacyStorageFactory(_semVer2StorageFactory); ContentBaseAddress = contentBaseAddress; GalleryBaseAddress = galleryBaseAddress; @@ -145,8 +148,9 @@ protected override async Task ProcessGraphsAsync( var legacyTask = RegistrationMaker.ProcessAsync( registrationKey: new RegistrationKey(sortedGraphs.Key), newItems: sortedGraphs.Value, - shouldInclude: _shouldIncludeSemVer2, + shouldInclude: _shouldIncludeSemVer2ForLegacyStorageFactory, storageFactory: _legacyStorageFactory, + postProcessGraph: _postProcessGraphForLegacyStorageFactory, contentBaseAddress: ContentBaseAddress, galleryBaseAddress: GalleryBaseAddress, partitionSize: PartitionSize, @@ -174,7 +178,7 @@ protected override async Task ProcessGraphsAsync( } } - public static ShouldIncludeRegistrationPackage GetShouldIncludeRegistrationPackage(StorageFactory semVer2StorageFactory) + public static ShouldIncludeRegistrationPackage GetShouldIncludeRegistrationPackageForLegacyStorageFactory(StorageFactory semVer2StorageFactory) { // If SemVer 2.0.0 storage is disabled, put SemVer 2.0.0 registration in the legacy storage factory. In no // case should a package be completely ignored. That is, if a package is SemVer 2.0.0 but SemVer 2.0.0 @@ -187,6 +191,30 @@ public static ShouldIncludeRegistrationPackage GetShouldIncludeRegistrationPacka return (k, u, g) => !NuGetVersionUtility.IsGraphSemVer2(k.Version, u, g); } + public static RegistrationMakerCatalogItem.PostProcessGraph GetPostProcessGraphForLegacyStorageFactory(StorageFactory semVer2StorageFactory) + { + // If SemVer 2.0.0 storage is disabled, put deprecation metadata in the legacy storage. + // A package's deprecation metadata should never be completely ignored. + // If a package contains deprecation metadata but SemVer 2.0.0 storage is not enabled, + // our only choice is to put deprecation metadata in the legacy storage. + if (semVer2StorageFactory == null) + { + return g => g; + } + + return FilterOutDeprecationInformation; + } + + public static RegistrationMakerCatalogItem.PostProcessGraph FilterOutDeprecationInformation = g => + { + var deprecationTriples = g + .GetTriplesWithPredicate(g.CreateUriNode(Schema.Predicates.Deprecation)) + .ToList(); + + g.Retract(deprecationTriples); + return g; + }; + private async Task ProcessBatchAsync( CollectorHttpClient client, JToken context, diff --git a/src/Catalog/Registration/RegistrationMaker.cs b/src/Catalog/Registration/RegistrationMaker.cs index 8573bb3b5..dde53187b 100644 --- a/src/Catalog/Registration/RegistrationMaker.cs +++ b/src/Catalog/Registration/RegistrationMaker.cs @@ -29,6 +29,7 @@ await ProcessAsync( newItems, (k, u, g) => true, storageFactory, + g => g, contentBaseAddress, galleryBaseAddress, partitionSize, @@ -42,6 +43,7 @@ public static async Task ProcessAsync( IReadOnlyDictionary newItems, ShouldIncludeRegistrationPackage shouldInclude, StorageFactory storageFactory, + RegistrationMakerCatalogItem.PostProcessGraph postProcessGraph, Uri contentBaseAddress, Uri galleryBaseAddress, int partitionSize, @@ -51,7 +53,7 @@ public static async Task ProcessAsync( { Trace.TraceInformation("RegistrationMaker.Process: registrationKey = {0} newItems: {1}", registrationKey, newItems.Count); - IRegistrationPersistence registration = new RegistrationPersistence(storageFactory, registrationKey, partitionSize, packageCountThreshold, contentBaseAddress, galleryBaseAddress); + IRegistrationPersistence registration = new RegistrationPersistence(storageFactory, postProcessGraph, registrationKey, partitionSize, packageCountThreshold, contentBaseAddress, galleryBaseAddress); IDictionary existing = await registration.Load(cancellationToken); diff --git a/src/Catalog/Registration/RegistrationMakerCatalogItem.cs b/src/Catalog/Registration/RegistrationMakerCatalogItem.cs index 77d425f64..ce61b5634 100644 --- a/src/Catalog/Registration/RegistrationMakerCatalogItem.cs +++ b/src/Catalog/Registration/RegistrationMakerCatalogItem.cs @@ -15,6 +15,8 @@ namespace NuGet.Services.Metadata.Catalog.Registration { public class RegistrationMakerCatalogItem : CatalogItem { + public delegate IGraph PostProcessGraph(IGraph graph); + private readonly Uri _catalogUri; private readonly IGraph _catalogItem; private Uri _itemAddress; @@ -25,17 +27,26 @@ public class RegistrationMakerCatalogItem : CatalogItem private Uri _registrationAddress; private DateTime _publishedDate; private bool _listed; + private readonly PostProcessGraph _postProcessGraph; // This should be set before class is instantiated public static IPackagePathProvider PackagePathProvider = null; - public RegistrationMakerCatalogItem(Uri catalogUri, IGraph catalogItem, Uri registrationBaseAddress, bool isExistingItem, Uri packageContentBaseAddress = null, Uri galleryBaseAddress = null) + public RegistrationMakerCatalogItem( + Uri catalogUri, + IGraph catalogItem, + Uri registrationBaseAddress, + bool isExistingItem, + PostProcessGraph postProcessGraph, + Uri packageContentBaseAddress = null, + Uri galleryBaseAddress = null) { _catalogUri = catalogUri; _catalogItem = catalogItem; _packageContentBaseAddress = packageContentBaseAddress; _galleryBaseAddress = galleryBaseAddress; _registrationBaseAddress = registrationBaseAddress; + _postProcessGraph = postProcessGraph; IsExistingItem = isExistingItem; } @@ -108,9 +119,7 @@ private DateTime GetPublishedDate() if (pubTriple != null) { - ILiteralNode node = pubTriple.Object as ILiteralNode; - - if (node != null) + if (pubTriple.Object is ILiteralNode node) { _publishedDate = DateTime.Parse(node.Value, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind); } @@ -194,8 +203,10 @@ public override IGraph CreatePageContent(CatalogContext context) { store.Add(_catalogItem, true); - SparqlParameterizedString sparql = new SparqlParameterizedString(); - sparql.CommandText = Utils.GetResource("sparql.ConstructRegistrationPageContentGraph.rq"); + SparqlParameterizedString sparql = new SparqlParameterizedString + { + CommandText = Utils.GetResource("sparql.ConstructRegistrationPageContentGraph.rq") + }; sparql.SetUri("package", GetItemAddress()); sparql.SetUri("catalogEntry", _catalogUri); @@ -207,7 +218,7 @@ public override IGraph CreatePageContent(CatalogContext context) content = SparqlHelpers.Construct(store, sparql.ToString()); } - return content; + return _postProcessGraph(content); } catch (Exception e) { diff --git a/src/Catalog/Registration/RegistrationPersistence.cs b/src/Catalog/Registration/RegistrationPersistence.cs index deb5bc1e4..e3acf8385 100644 --- a/src/Catalog/Registration/RegistrationPersistence.cs +++ b/src/Catalog/Registration/RegistrationPersistence.cs @@ -21,13 +21,22 @@ public class RegistrationPersistence : IRegistrationPersistence private readonly int _packageCountThreshold; private readonly int _partitionSize; private readonly RecordingStorage _storage; + private readonly RegistrationMakerCatalogItem.PostProcessGraph _postProcessGraph; private readonly Uri _registrationBaseAddress; private readonly Uri _contentBaseAddress; private readonly Uri _galleryBaseAddress; - public RegistrationPersistence(StorageFactory storageFactory, RegistrationKey registrationKey, int partitionSize, int packageCountThreshold, Uri contentBaseAddress, Uri galleryBaseAddress) + public RegistrationPersistence( + StorageFactory storageFactory, + RegistrationMakerCatalogItem.PostProcessGraph postProcessGraph, + RegistrationKey registrationKey, + int partitionSize, + int packageCountThreshold, + Uri contentBaseAddress, + Uri galleryBaseAddress) { _storage = new RecordingStorage(storageFactory.Create(registrationKey.ToString())); + _postProcessGraph = postProcessGraph; _registrationUri = _storage.ResolveUri("index.json"); _packageCountThreshold = packageCountThreshold; _partitionSize = partitionSize; @@ -43,7 +52,7 @@ public Task> Load(Ca public async Task Save(IDictionary registration, CancellationToken cancellationToken) { - await Save(_storage, _registrationBaseAddress, registration, _partitionSize, _packageCountThreshold, _contentBaseAddress, _galleryBaseAddress, cancellationToken); + await Save(_storage, _postProcessGraph, _registrationBaseAddress, registration, _partitionSize, _packageCountThreshold, _contentBaseAddress, _galleryBaseAddress, cancellationToken); await Cleanup(_storage, cancellationToken); } @@ -100,8 +109,11 @@ private static void AddExistingItem(IDictionary LoadCatalogPage(IStorage storage, Uri pageUri, } // Save implementation - private static async Task Save(IStorage storage, Uri registrationBaseAddress, IDictionary registration, int partitionSize, int packageCountThreshold, Uri contentBaseAddress, Uri galleryBaseAddress, CancellationToken cancellationToken) + private static async Task Save( + IStorage storage, + RegistrationMakerCatalogItem.PostProcessGraph preprocessGraph, + Uri registrationBaseAddress, + IDictionary registration, + int partitionSize, + int packageCountThreshold, + Uri contentBaseAddress, + Uri galleryBaseAddress, + CancellationToken cancellationToken) { Trace.TraceInformation("RegistrationPersistence.Save"); @@ -170,15 +191,22 @@ private static async Task Save(IStorage storage, Uri registrationBaseAddress, ID if (items.Count < packageCountThreshold) { - await SaveSmallRegistration(storage, registrationBaseAddress, items, partitionSize, contentBaseAddress, galleryBaseAddress, cancellationToken); + await SaveSmallRegistration(storage, preprocessGraph, registrationBaseAddress, items, partitionSize, contentBaseAddress, galleryBaseAddress, cancellationToken); } else { - await SaveLargeRegistration(storage, registrationBaseAddress, items, partitionSize, contentBaseAddress, galleryBaseAddress, cancellationToken); + await SaveLargeRegistration(storage, preprocessGraph, registrationBaseAddress, items, partitionSize, contentBaseAddress, galleryBaseAddress, cancellationToken); } } - private static async Task SaveSmallRegistration(IStorage storage, Uri registrationBaseAddress, IList items, int partitionSize, Uri contentBaseAddress, Uri galleryBaseAddress, CancellationToken cancellationToken) + private static async Task SaveSmallRegistration( + IStorage storage, + RegistrationMakerCatalogItem.PostProcessGraph preprocessGraph, + Uri registrationBaseAddress, + IList items, + int partitionSize, Uri contentBaseAddress, + Uri galleryBaseAddress, + CancellationToken cancellationToken) { Trace.TraceInformation("RegistrationPersistence.SaveSmallRegistration"); @@ -186,7 +214,7 @@ private static async Task SaveSmallRegistration(IStorage storage, Uri registrati //await graphPersistence.Initialize(); - await SaveRegistration(storage, registrationBaseAddress, items, null, graphPersistence, partitionSize, contentBaseAddress, galleryBaseAddress, cancellationToken); + await SaveRegistration(storage, preprocessGraph, registrationBaseAddress, items, null, graphPersistence, partitionSize, contentBaseAddress, galleryBaseAddress, cancellationToken); // now the commit has happened the graphPersistence.Graph should contain all the data @@ -195,16 +223,34 @@ private static async Task SaveSmallRegistration(IStorage storage, Uri registrati await storage.SaveAsync(graphPersistence.ResourceUri, content, cancellationToken); } - private static async Task SaveLargeRegistration(IStorage storage, Uri registrationBaseAddress, IList items, int partitionSize, Uri contentBaseAddress, Uri galleryBaseAddress, CancellationToken cancellationToken) + private static async Task SaveLargeRegistration( + IStorage storage, + RegistrationMakerCatalogItem.PostProcessGraph preprocessGraph, + Uri registrationBaseAddress, + IList items, + int partitionSize, + Uri contentBaseAddress, + Uri galleryBaseAddress, + CancellationToken cancellationToken) { Trace.TraceInformation("RegistrationPersistence.SaveLargeRegistration: registrationBaseAddress = {0} items: {1}", registrationBaseAddress, items.Count); IList cleanUpList = new List(); - await SaveRegistration(storage, registrationBaseAddress, items, cleanUpList, null, partitionSize, contentBaseAddress, galleryBaseAddress, cancellationToken); + await SaveRegistration(storage, preprocessGraph, registrationBaseAddress, items, cleanUpList, null, partitionSize, contentBaseAddress, galleryBaseAddress, cancellationToken); } - private static async Task SaveRegistration(IStorage storage, Uri registrationBaseAddress, IList items, IList cleanUpList, SingleGraphPersistence graphPersistence, int partitionSize, Uri contentBaseAddress, Uri galleryBaseAddress, CancellationToken cancellationToken) + private static async Task SaveRegistration( + IStorage storage, + RegistrationMakerCatalogItem.PostProcessGraph postProcessGraph, + Uri registrationBaseAddress, + IList items, + IList cleanUpList, + SingleGraphPersistence graphPersistence, + int partitionSize, + Uri contentBaseAddress, + Uri galleryBaseAddress, + CancellationToken cancellationToken) { Trace.TraceInformation("RegistrationPersistence.SaveRegistration: registrationBaseAddress = {0} items: {1}", registrationBaseAddress, items.Count); @@ -212,7 +258,7 @@ private static async Task SaveRegistration(IStorage storage, Uri registrationBas { foreach (var item in items) { - writer.Add(new RegistrationMakerCatalogItem(new Uri(item.ResourceUri), item.Graph, registrationBaseAddress, item.IsExistingItem, contentBaseAddress, galleryBaseAddress)); + writer.Add(new RegistrationMakerCatalogItem(new Uri(item.ResourceUri), item.Graph, registrationBaseAddress, item.IsExistingItem, postProcessGraph, contentBaseAddress, galleryBaseAddress)); } await writer.Commit(DateTime.UtcNow, null, cancellationToken); } diff --git a/src/Ng/Jobs/LightningJob.cs b/src/Ng/Jobs/LightningJob.cs index c4dd32ca9..094d7d24f 100644 --- a/src/Ng/Jobs/LightningJob.cs +++ b/src/Ng/Jobs/LightningJob.cs @@ -135,7 +135,8 @@ public override string GetUsage() private string _contentBaseAddress; private string _galleryBaseAddress; private RegistrationStorageFactories _storageFactories; - private ShouldIncludeRegistrationPackage _shouldIncludeSemVer2; + private ShouldIncludeRegistrationPackage _shouldIncludeSemVer2ForLegacyStorageFactory; + private RegistrationMakerCatalogItem.PostProcessGraph _postProcessGraphForLegacyStorageFactory; private IDictionary _arguments; #endregion @@ -176,7 +177,8 @@ protected override void Init(IDictionary arguments, Cancellation _contentBaseAddress = arguments.GetOrThrow(Arguments.ContentBaseAddress); _galleryBaseAddress = arguments.GetOrThrow(Arguments.GalleryBaseAddress); _storageFactories = CommandHelpers.CreateRegistrationStorageFactories(arguments, _verbose); - _shouldIncludeSemVer2 = RegistrationCollector.GetShouldIncludeRegistrationPackage(_storageFactories.SemVer2StorageFactory); + _shouldIncludeSemVer2ForLegacyStorageFactory = RegistrationCollector.GetShouldIncludeRegistrationPackageForLegacyStorageFactory(_storageFactories.SemVer2StorageFactory); + _postProcessGraphForLegacyStorageFactory = RegistrationCollector.GetPostProcessGraphForLegacyStorageFactory(_storageFactories.SemVer2StorageFactory); // We save the arguments because the "prepare" command generates "strike" commands. Some of the arguments // used by "prepare" should be used when executing "strike". _arguments = arguments; @@ -289,8 +291,11 @@ private async Task PrepareAsync() // Write cursor to storage _log.WriteLine("Start writing new cursor..."); var storage = _storageFactories.LegacyStorageFactory.Create(); - var cursor = new DurableCursor(storage.ResolveUri("cursor.json"), storage, latestCommit); - cursor.Value = latestCommit; + var cursor = new DurableCursor(storage.ResolveUri("cursor.json"), storage, latestCommit) + { + Value = latestCommit + }; + await cursor.SaveAsync(CancellationToken.None); _log.WriteLine("Finished writing new cursor."); @@ -340,16 +345,19 @@ private async Task PrepareAsync() string optionalArguments = string.Empty; if (_arguments.ContainsKey(Arguments.StorageSuffix)) { - optionalArguments = optionalArguments + $" -{Arguments.StorageSuffix} {_arguments[Arguments.StorageSuffix]}"; + optionalArguments += $" -{Arguments.StorageSuffix} {_arguments[Arguments.StorageSuffix]}"; } + if (_arguments.ContainsKey(Arguments.ContentIsFlatContainer)) { - optionalArguments = optionalArguments + $" -{Arguments.ContentIsFlatContainer} {_arguments[Arguments.ContentIsFlatContainer]}"; + optionalArguments += $" -{Arguments.ContentIsFlatContainer} {_arguments[Arguments.ContentIsFlatContainer]}"; } + if (_arguments.ContainsKey(Arguments.FlatContainerName)) { - optionalArguments = optionalArguments + $" -{Arguments.FlatContainerName} {_arguments[Arguments.FlatContainerName]}"; + optionalArguments += $" -{Arguments.FlatContainerName} {_arguments[Arguments.FlatContainerName]}"; } + commandStreamContents = commandStreamContents .Replace($"[{optionalArgumentsTemplate}]", optionalArguments); @@ -485,8 +493,9 @@ private async Task ProcessGraphsAsync(string packageId, IReadOnlyDictionary g, packageContentBaseAddress: packageContentBaseAddress) { BaseAddress = new Uri("http://example/registration/mypackage/"), @@ -72,8 +74,7 @@ public void CreateContent_SetsListedProperly(string published, bool expectedList private static string GetContentString(StorageContent content) { - var stringStorageContent = content as StringStorageContent; - if (stringStorageContent != null) + if (content is StringStorageContent stringStorageContent) { return stringStorageContent.Content; } @@ -90,7 +91,7 @@ public class TheCreatePageContentMethod private readonly Uri _registrationBaseAddress = new Uri("http://example/registration/"); private readonly Uri _packageContentBaseAddress = new Uri("http://example/content/"); private readonly Uri _baseAddress = new Uri("http://example/registration/mypackage/"); - private Graph _graph; + private readonly Graph _graph; public TheCreatePageContentMethod() { @@ -158,11 +159,13 @@ public void CreatePageContent_SetsLicenseUrlAndExpressionProperly( _graph, _registrationBaseAddress, isExistingItem: false, + postProcessGraph: g => g, packageContentBaseAddress: _packageContentBaseAddress, galleryBaseAddress: new Uri(galleryBaseAddress)) { BaseAddress = _baseAddress, }; + RegistrationMakerCatalogItem.PackagePathProvider = new PackagesFolderPackagePathProvider(); var context = new CatalogContext(); @@ -188,17 +191,20 @@ public static IEnumerable CreatePageContent_SetsDeprecationInformation { get { - foreach (var reason in - new [] - { + foreach (var shouldPostProcess in new[] { false, true }) + { + foreach (var reason in + new[] + { new[] { "first" }, new[] { "first", "second" } - }) - { - foreach (var message in new[] { null, "this is the message" }) + }) { - yield return new object[] { reason, message, null, null }; - yield return new object[] { reason, message, "theId", "homeOnTheRange" }; + foreach (var message in new[] { null, "this is the message" }) + { + yield return new object[] { shouldPostProcess, reason, message, null, null }; + yield return new object[] { shouldPostProcess, reason, message, "theId", "homeOnTheRange" }; + } } } } @@ -207,6 +213,7 @@ public static IEnumerable CreatePageContent_SetsDeprecationInformation [Theory] [MemberData(nameof(CreatePageContent_SetsDeprecationInformationProperly_Data))] public void CreatePageContent_SetsDeprecationInformationProperly( + bool shouldPostProcess, IEnumerable reasons, string message, string alternatePackageId, @@ -265,10 +272,12 @@ public void CreatePageContent_SetsDeprecationInformationProperly( _graph, _registrationBaseAddress, isExistingItem: false, + postProcessGraph: shouldPostProcess ? RegistrationCollector.FilterOutDeprecationInformation : g => g, packageContentBaseAddress: _packageContentBaseAddress) { BaseAddress = _baseAddress, }; + RegistrationMakerCatalogItem.PackagePathProvider = new PackagesFolderPackagePathProvider(); var context = new CatalogContext(); @@ -276,56 +285,64 @@ public void CreatePageContent_SetsDeprecationInformationProperly( var content = item.CreatePageContent(context); // Assert - var deprecationObjectNode = _graph + var deprecationPredicateTriples = content .GetTriplesWithSubjectPredicate( - _graph.CreateUriNode(_catalogUri), - _graph.CreateUriNode(Schema.Predicates.Deprecation)) + content.CreateUriNode(_catalogUri), + content.CreateUriNode(Schema.Predicates.Deprecation)); + + if (shouldPostProcess) + { + Assert.Empty(deprecationPredicateTriples); + return; + } + + var deprecationObjectNode = deprecationPredicateTriples .Single() .Object; - var deprecationTriples = _graph.GetTriplesWithSubject(deprecationObjectNode); + var deprecationTriples = content.GetTriplesWithSubject(deprecationObjectNode); var reasonTriples = deprecationTriples - .Where(t => t.HasPredicate(_graph.CreateUriNode(Schema.Predicates.Reasons))); + .Where(t => t.HasPredicate(content.CreateUriNode(Schema.Predicates.Reasons))); foreach (var reason in reasons) { - Assert.Contains(reasonTriples, t => t.HasObject(_graph.CreateLiteralNode(reason))); + Assert.Contains(reasonTriples, t => t.HasObject(content.CreateLiteralNode(reason))); } if (message == null) { Assert.DoesNotContain( deprecationTriples, - t => t.HasPredicate(_graph.CreateUriNode(Schema.Predicates.Message))); + t => t.HasPredicate(content.CreateUriNode(Schema.Predicates.Message))); } else { Assert.Contains( deprecationTriples, - t => t.HasPredicate(_graph.CreateUriNode(Schema.Predicates.Message)) && t.HasObject(_graph.CreateLiteralNode(message))); + t => t.HasPredicate(content.CreateUriNode(Schema.Predicates.Message)) && t.HasObject(content.CreateLiteralNode(message))); } if (alternatePackageId == null) { Assert.DoesNotContain( deprecationTriples, - t => t.HasPredicate(_graph.CreateUriNode(Schema.Predicates.AlternatePackage))); + t => t.HasPredicate(content.CreateUriNode(Schema.Predicates.AlternatePackage))); } else { - var alternatePackageObjectNode = _graph + var alternatePackageObjectNode = content .GetTriplesWithSubjectPredicate( deprecationObjectNode, - _graph.CreateUriNode(Schema.Predicates.AlternatePackage)) + content.CreateUriNode(Schema.Predicates.AlternatePackage)) .Single() .Object; - var alternatePackageTriples = _graph.GetTriplesWithSubject(alternatePackageObjectNode); + var alternatePackageTriples = content.GetTriplesWithSubject(alternatePackageObjectNode); Assert.Contains(alternatePackageTriples, - t => t.HasPredicate(_graph.CreateUriNode(Schema.Predicates.Id)) && t.HasObject(_graph.CreateLiteralNode(alternatePackageId))); + t => t.HasPredicate(content.CreateUriNode(Schema.Predicates.Id)) && t.HasObject(content.CreateLiteralNode(alternatePackageId))); Assert.Contains(alternatePackageTriples, - t => t.HasPredicate(_graph.CreateUriNode(Schema.Predicates.Range)) && t.HasObject(_graph.CreateLiteralNode(alternatePackageRange))); + t => t.HasPredicate(content.CreateUriNode(Schema.Predicates.Range)) && t.HasObject(content.CreateLiteralNode(alternatePackageRange))); } } } diff --git a/tests/CatalogTests/Registration/RegistrationMakerTests.cs b/tests/CatalogTests/Registration/RegistrationMakerTests.cs index 717afb599..8c80dec04 100644 --- a/tests/CatalogTests/Registration/RegistrationMakerTests.cs +++ b/tests/CatalogTests/Registration/RegistrationMakerTests.cs @@ -167,8 +167,10 @@ public async Task ProcessAsync_WithCustomPackageCountThreshold_TransitionsToPage } } - [Fact] - public async Task ProcessAsync_WithDeprecationInformation_FormatsPageCorrectly() + [Theory] + [InlineData(false)] + [InlineData(true)] + public async Task ProcessAsync_WithDeprecationInformation_FormatsPageCorrectly(bool filterOutDeprecation) { const int partitionSize = 1; var pages = new List(); @@ -220,13 +222,21 @@ public async Task ProcessAsync_WithDeprecationInformation_FormatsPageCorrectly() foreach (var packageDetails in packageDetailsList) { newItem = CreateNewItem(packageDetails); - storage = await ProcessAsync(newItem, packageDetails.Id, partitionSize); + storage = await ProcessAsync( + newItem, + packageDetails.Id, + partitionSize, + filterOutDeprecation: filterOutDeprecation); pages.Add(new ExpectedPage(packageDetails)); expectedPages = Repaginate(pages, partitionSize); - Verify(storage, expectedPages, partitionSize); + Verify( + storage, + expectedPages, + partitionSize, + filterOutDeprecation: filterOutDeprecation); } } @@ -252,14 +262,17 @@ private async Task ProcessAsync( IReadOnlyDictionary newItems, string packageId, int partitionSize, - int packageCountThreshold = _defaultPackageCountThreshold) + int packageCountThreshold = _defaultPackageCountThreshold, + bool filterOutDeprecation = false) { var registrationKey = new RegistrationKey(packageId?.ToLowerInvariant() ?? string.Empty); await RegistrationMaker.ProcessAsync( registrationKey, newItems, + (g, u, k) => true, _storageFactory, + filterOutDeprecation ? RegistrationCollector.FilterOutDeprecationInformation : g => g, _contentBaseAddress, _galleryBaseAddress, partitionSize, @@ -274,7 +287,8 @@ private void Verify( MemoryStorage registrationStorage, IReadOnlyList expectedPages, int partitionSize, - int packageCountThreshold = _defaultPackageCountThreshold) + int packageCountThreshold = _defaultPackageCountThreshold, + bool filterOutDeprecation = false) { var expectedStorageContentCount = expectedPages.SelectMany(page => page.Details).Count(); @@ -296,7 +310,8 @@ private void Verify( packageId, expectedPages, partitionSize, - packageCountThreshold); + packageCountThreshold, + filterOutDeprecation); } private void VerifyRegistrationIndex( @@ -306,7 +321,8 @@ private void VerifyRegistrationIndex( string packageId, IReadOnlyList expectedPages, int partitionSize, - int packageCountThreshold) + int packageCountThreshold, + bool filterOutDeprecation) { Assert.Equal(indexUri.AbsoluteUri, index.IdKeyword); Assert.Equal( @@ -341,7 +357,8 @@ private void VerifyRegistrationIndex( packageId, expectedPage, index.CommitId, - index.CommitTimeStamp); + index.CommitTimeStamp, + filterOutDeprecation); } else { @@ -354,7 +371,8 @@ private void VerifyRegistrationIndex( packageId, expectedPage, index.CommitId, - index.CommitTimeStamp); + index.CommitTimeStamp, + filterOutDeprecation); } } @@ -419,7 +437,8 @@ private void VerifyRegistrationPage( string packageId, ExpectedPage expectedPage, string commitId, - string commitTimeStamp) + string commitTimeStamp, + bool filterOutDeprecation) { var packageIndexUri = GetRegistrationPackageIndexUri(registrationStorage.BaseAddress); @@ -437,7 +456,13 @@ private void VerifyRegistrationPage( var item = page.Items[i]; var packageDetails = expectedPage.Details[i]; - VerifyRegistrationPackage(registrationStorage, item, packageDetails, commitId, commitTimeStamp); + VerifyRegistrationPackage( + registrationStorage, + item, + packageDetails, + commitId, + commitTimeStamp, + filterOutDeprecation); } } @@ -447,7 +472,8 @@ private void VerifyRegistrationPageReference( string packageId, ExpectedPage expectedPage, string commitId, - string commitTimeStamp) + string commitTimeStamp, + bool filterOutDeprecation) { var pageUri = GetRegistrationPageReferenceUri(packageId, expectedPage); @@ -470,7 +496,8 @@ private void VerifyRegistrationPageReference( packageId, expectedPage, commitId, - commitTimeStamp); + commitTimeStamp, + filterOutDeprecation); JObject expectedContext = GetExpectedIndexOrPageContext(); @@ -482,7 +509,8 @@ private void VerifyRegistrationPackage( RegistrationPackage package, CatalogIndependentPackageDetails packageDetails, string commitId, - string commitTimeStamp) + string commitTimeStamp, + bool filterOutDeprecation) { var packageId = packageDetails.Id.ToLowerInvariant(); var packageVersion = packageDetails.Version.ToLowerInvariant(); @@ -514,7 +542,7 @@ private void VerifyRegistrationPackage( var actualDeprecation = package.CatalogEntry.Deprecation; var expectedDeprecation = packageDetails.Deprecation; - if (expectedDeprecation == null) + if (filterOutDeprecation || expectedDeprecation == null) { Assert.Null(actualDeprecation); }