Example #1
0
 public PackageStatusOutdatedCheck(
     FeedPackageIdentity identity,
     DateTime commitTimestamp)
 {
     Identity  = identity;
     Timestamp = commitTimestamp;
 }
Example #2
0
        public void UpdateFromExistingUpdatesExistingStatus(PackageState previousState, AccessCondition accessCondition, PackageState newState)
        {
            // Arrange
            var feedPackageIdentity = new FeedPackageIdentity("howdy", "3.4.6");

            var existingStatus = PackageMonitoringStatusTestUtility.CreateStatusWithPackageValidationResult(
                feedPackageIdentity.Id,
                feedPackageIdentity.Version,
                PackageMonitoringStatusTestUtility.GetTestResultFromPackageState(previousState));

            existingStatus.AccessCondition = accessCondition;

            var newStatus = PackageMonitoringStatusTestUtility.CreateStatusWithPackageValidationResult(
                feedPackageIdentity.Id,
                feedPackageIdentity.Version,
                PackageMonitoringStatusTestUtility.GetTestResultFromPackageState(newState));

            // Act
            PackageMonitoringStatusAccessConditionHelper.UpdateFromExisting(newStatus, existingStatus);

            // Assert
            foreach (var state in Enum.GetValues(typeof(PackageState)).Cast <PackageState>())
            {
                PackageMonitoringStatusTestUtility.AssertAccessCondition(
                    state == previousState ? accessCondition : AccessCondition.GenerateIfNotExistsCondition(),
                    newStatus.ExistingState[state]);
            }
        }
 public PackageMonitoringStatus(FeedPackageIdentity package, PackageValidationResult validationResult, Exception validationException)
     : this()
 {
     Package             = package;
     ValidationResult    = validationResult;
     ValidationException = validationException;
 }
        public async Task UpdateSavesNewStatus()
        {
            // Arrange
            var feedPackageIdentity     = new FeedPackageIdentity("howdy", "3.4.6");
            var packageValidationResult = new PackageValidationResult(
                new PackageIdentity(feedPackageIdentity.Id, new NuGetVersion(feedPackageIdentity.Version)),
                null,
                null,
                Enumerable.Empty <AggregateValidationResult>());

            var status = new PackageMonitoringStatus(packageValidationResult);

            var storageFactory = new MemoryStorageFactory();

            var statusService = new PackageMonitoringStatusService(
                storageFactory,
                new Mock <ILogger <PackageMonitoringStatusService> >().Object);

            // Act
            await statusService.UpdateAsync(status, CancellationToken.None);

            // Assert
            Assert.True(
                storageFactory.Create(
                    PackageState.Valid.ToString().ToLowerInvariant())
                .Exists(GetPackageFileName(feedPackageIdentity.Id, feedPackageIdentity.Version)));
        }
        private async Task <IEnumerable <CatalogIndexEntry> > FetchCatalogIndexEntriesFromRegistrationAsync(
            FeedPackageIdentity feedPackage,
            CancellationToken token)
        {
            var id       = feedPackage.Id;
            var version  = NuGetVersion.Parse(feedPackage.Version);
            var leafBlob = await _regResource.GetPackageMetadata(
                new PackageIdentity(id, version),
                NullSourceCacheContext.Instance,
                Logger.AsCommon(),
                token);

            if (leafBlob == null)
            {
                throw new Exception("Package is missing from registration!");
            }

            var catalogPageUri = new Uri(leafBlob["@id"].ToString());
            var catalogPage    = await _client.GetJObjectAsync(catalogPageUri, token);

            return(new CatalogIndexEntry[]
            {
                new CatalogIndexEntry(
                    catalogPageUri,
                    Schema.DataTypes.PackageDetails.ToString(),
                    catalogPage["catalog:commitId"].ToString(),
                    DateTime.Parse(catalogPage["catalog:commitTimeStamp"].ToString()),
                    id,
                    version)
            });
        }
Example #6
0
        public async Task <PackageMonitoringStatus> GetAsync(FeedPackageIdentity package, CancellationToken token)
        {
            var statusTasks =
                _packageStateNames
                .Select(state => GetPackageAsync(GetStorage(state), package, token))
                .ToList();

            var statuses =
                (await Task.WhenAll(statusTasks))
                .Where(s => s != null);

            if (!statuses.Any())
            {
                return(null);
            }

            // If more than one status exist for a single package, find the status with the latest timestamp.
            var statusesWithTimeStamps = statuses.Where(s => s.ValidationResult != null && s.ValidationResult.CatalogEntries != null && s.ValidationResult.CatalogEntries.Any());

            if (statusesWithTimeStamps.Any())
            {
                return(statusesWithTimeStamps.OrderByDescending(s => s.ValidationResult.CatalogEntries.Max(c => c.CommitTimeStamp)).First());
            }
            else
            {
                // No statuses have timestamps (they all failed to process).
                // Because they are all in a bad state, choose an arbitrary one.
                return(statuses.First());
            }
        }
        public async Task GetByPackageDeletesOutdatedStatuses(PackageState latest, PackageState outdated)
        {
            // Arrange
            var storageFactory = new MemoryStorageFactory();
            var statusService  = new PackageMonitoringStatusService(
                storageFactory,
                new Mock <ILogger <PackageMonitoringStatusService> >().Object);

            var id             = "howdyFriend";
            var version        = "5.5.5";
            var package        = new FeedPackageIdentity(id, version);
            var outdatedStatus = PackageMonitoringStatusTestUtility.CreateStatusWithPackageValidationResult(
                id,
                version,
                PackageMonitoringStatusTestUtility.GetTestResultFromPackageState(latest),
                new DateTime(2019, 6, 10));

            var latestStatus = PackageMonitoringStatusTestUtility.CreateStatusWithPackageValidationResult(
                id,
                version,
                PackageMonitoringStatusTestUtility.GetTestResultFromPackageState(outdated),
                new DateTime(2019, 6, 11));

            await SaveToStorage(storageFactory, outdatedStatus);
            await SaveToStorage(storageFactory, latestStatus);

            // Act
            var status = await statusService.GetAsync(package, CancellationToken.None);

            // Assert
            PackageMonitoringStatusTestUtility.AssertStatus(latestStatus, status);
            Assert.Equal(latest == outdated, DoesPackageExists(storageFactory, outdatedStatus.State, package));
            Assert.True(DoesPackageExists(storageFactory, latestStatus.State, package));
        }
        private string GetPackageFileName(FeedPackageIdentity package)
        {
            var idString      = package.Id.ToLowerInvariant();
            var versionString = package.Version.ToLowerInvariant();

            return($"{idString}/" +
                   $"{idString}.{versionString}.json");
        }
Example #9
0
        public void FeedPackageIdentityEquals(string idA, string versionA, string idB, string versionB, bool success)
        {
            var packageA = new FeedPackageIdentity(idA, versionA);
            var packageB = new FeedPackageIdentity(idB, versionB);

            Assert.Equal(success, packageA.Equals(packageB));
            Assert.Equal(success, packageB.Equals(packageA));

            Assert.Equal(success, packageA.GetHashCode() == packageB.GetHashCode());
        }
Example #10
0
        private async Task DeleteAsync(FeedPackageIdentity package, PackageState state, CancellationToken token)
        {
            var storage = GetStorage(state);

            if (!storage.Exists(GetPackageFileName(package)))
            {
                return;
            }

            await storage.DeleteAsync(GetPackageUri(storage, package), token);
        }
        private async Task SaveFailedPackageMonitoringStatusAsync(
            PackageValidatorContext queuedContext,
            Exception exception,
            CancellationToken token)
        {
            var feedPackage = new FeedPackageIdentity(queuedContext.Package.Id, queuedContext.Package.Version);

            await _notificationService.OnPackageValidationFailedAsync(feedPackage.Id, feedPackage.Version, exception, token);

            var status = new PackageMonitoringStatus(feedPackage, exception);
            await _statusService.UpdateAsync(status, token);
        }
        public async Task UpdateDeletesOldStatuses(PackageState?previousState)
        {
            // Arrange
            var feedPackageIdentity = new FeedPackageIdentity("howdy", "3.4.6");

            var packageValidationResult = new PackageValidationResult(
                new PackageIdentity(feedPackageIdentity.Id, new NuGetVersion(feedPackageIdentity.Version)),
                null,
                null,
                Enumerable.Empty <AggregateValidationResult>());
            var status = new PackageMonitoringStatus(packageValidationResult);

            var storageFactory = new MemoryStorageFactory();

            var statusService = new PackageMonitoringStatusService(
                storageFactory,
                new Mock <ILogger <PackageMonitoringStatusService> >().Object);

            var etag = "theETag";

            foreach (var state in Enum.GetValues(typeof(PackageState)).Cast <PackageState>())
            {
                if (previousState != state)
                {
                    status.ExistingState[state] = AccessCondition.GenerateIfNotExistsCondition();
                    continue;
                }

                var content = new StringStorageContentWithETag("{}", etag);
                await SaveToStorage(storageFactory, state, feedPackageIdentity, content);

                status.ExistingState[state] = AccessCondition.GenerateIfMatchCondition(etag);
            }

            // Act
            await statusService.UpdateAsync(status, CancellationToken.None);

            // Assert
            foreach (var state in Enum.GetValues(typeof(PackageState)).Cast <PackageState>())
            {
                Assert.Equal(
                    state == status.State,
                    DoesPackageExists(storageFactory, state, feedPackageIdentity));
            }

            PackageMonitoringStatusTestUtility.AssertStatus(
                status,
                await statusService.GetAsync(feedPackageIdentity, CancellationToken.None));
        }
        private async Task DeleteAsync(FeedPackageIdentity package, PackageState state, AccessCondition accessCondition, CancellationToken token)
        {
            var storage = GetStorage(state);

            if (!storage.Exists(GetPackageFileName(package)))
            {
                return;
            }

            await storage.DeleteAsync(
                GetPackageUri(storage, package),
                token,
                new DeleteRequestOptionsWithAccessCondition(
                    accessCondition));
        }
Example #14
0
        private async Task SaveFailedPackageMonitoringStatusAsync(
            PackageValidatorContext queuedContext,
            Exception exception,
            CancellationToken token)
        {
            var queuedVersion = queuedContext.Package.Version;
            var version       = NuGetVersion.TryParse(queuedVersion, out var parsedVersion)
                ? parsedVersion.ToFullString() : queuedVersion;

            var feedPackage = new FeedPackageIdentity(queuedContext.Package.Id, version);
            await _notificationService.OnPackageValidationFailedAsync(feedPackage.Id, feedPackage.Version, exception, token);

            var status = new PackageMonitoringStatus(feedPackage, exception);
            await _statusService.UpdateAsync(status, token);
        }
        protected override async Task ProcessSortedBatchAsync(CollectorHttpClient client, KeyValuePair <FeedPackageIdentity, IList <JObject> > sortedBatch, JToken context, CancellationToken cancellationToken)
        {
            var packageId      = sortedBatch.Key.Id;
            var packageVersion = sortedBatch.Key.Version;
            var feedPackage    = new FeedPackageIdentity(packageId, packageVersion);

            _logger.LogInformation("Processing catalog entries for {PackageId} {PackageVersion}.", packageId, packageVersion);

            var catalogEntries = sortedBatch.Value.Select(c => new CatalogIndexEntry(c));

            _logger.LogInformation("Adding {MostRecentCatalogEntryUri} to queue.", catalogEntries.OrderByDescending(c => c.CommitTimeStamp).First().Uri);

            await _queue.AddAsync(
                new PackageValidatorContext(feedPackage, catalogEntries),
                cancellationToken);
        }
        public async Task UpdateDeletesOldStatuses()
        {
            // Arrange
            var feedPackageIdentity = new FeedPackageIdentity("howdy", "3.4.6");
            var packageFileName     = GetPackageFileName(feedPackageIdentity.Id, feedPackageIdentity.Version);

            var packageValidationResult = new PackageValidationResult(
                new PackageIdentity(feedPackageIdentity.Id, new NuGetVersion(feedPackageIdentity.Version)),
                null,
                null,
                Enumerable.Empty <AggregateValidationResult>());
            var status = new PackageMonitoringStatus(packageValidationResult);

            var storageFactory = new MemoryStorageFactory();

            var statusService = new PackageMonitoringStatusService(
                storageFactory,
                new Mock <ILogger <PackageMonitoringStatusService> >().Object);

            foreach (var state in Enum.GetNames(typeof(PackageState)))
            {
                var storage = storageFactory.Create(state.ToLowerInvariant());
                await storage.SaveAsync(storage.ResolveUri(packageFileName), new StringStorageContent("{}"), CancellationToken.None);

                Assert.True(storage.Exists(packageFileName));
            }

            // Act
            await statusService.UpdateAsync(status, CancellationToken.None);

            // Assert
            foreach (var state in Enum.GetNames(typeof(PackageState)))
            {
                var storage = storageFactory.Create(state.ToLowerInvariant());

                if ((PackageState)Enum.Parse(typeof(PackageState), state) == status.State)
                {
                    Assert.True(storage.Exists(packageFileName));
                }
                else
                {
                    Assert.False(storage.Exists(packageFileName));
                }
            }

            AssertStatus(status, await statusService.GetAsync(feedPackageIdentity, CancellationToken.None));
        }
Example #17
0
        public void PackageIdentityConstructorUsesFullString()
        {
            const string id            = "id";
            const string versionString = "1.0.0+buildmetadata";
            var          package       = new PackageIdentity(id, NuGetVersion.Parse(versionString));

            var feedPackage            = new FeedPackageIdentity(package);
            var equivalentFeedPackage1 = new FeedPackageIdentity(id, versionString);
            var equivalentFeedPackage2 = new FeedPackageIdentity(package.Id, package.Version.ToFullString());
            var differentFeedPackage   = new FeedPackageIdentity(package.Id, package.Version.ToNormalizedString());

            foreach (var equivalentFeedPackage in new FeedPackageIdentity[] { equivalentFeedPackage1, equivalentFeedPackage2 })
            {
                Assert.True(feedPackage.Equals(equivalentFeedPackage));
                Assert.Equal(feedPackage.GetHashCode(), equivalentFeedPackage.GetHashCode());
            }

            Assert.False(feedPackage.Equals(differentFeedPackage));
            Assert.NotEqual(feedPackage.GetHashCode(), differentFeedPackage.GetHashCode());
        }
        public async Task <PackageMonitoringStatus> GetAsync(FeedPackageIdentity package, CancellationToken token)
        {
            var statusTasks =
                _packageStateNames
                .Select(state => GetPackageAsync(GetStorage(state), package, token))
                .ToList();

            var statuses =
                (await Task.WhenAll(statusTasks))
                .Where(s => s != null);

            if (!statuses.Any())
            {
                return(null);
            }

            // If more than one status exist for a single package, find the status with the latest timestamp.
            // We then must delete the other statuses, so that we can later update the storage safely.
            var statusesWithTimeStamps = statuses.Where(s => s.ValidationResult != null && s.ValidationResult.CatalogEntries != null && s.ValidationResult.CatalogEntries.Any());
            IEnumerable <PackageMonitoringStatus> orderedStatuses;

            if (statusesWithTimeStamps.Any())
            {
                orderedStatuses = statusesWithTimeStamps.OrderByDescending(s => s.ValidationResult.CatalogEntries.Max(c => c.CommitTimeStamp));
            }
            else
            {
                // No statuses have timestamps (they all failed to process).
                // Because they are all in a bad state, choose an arbitrary one.
                orderedStatuses = statuses;
            }

            var result = orderedStatuses.First();

            foreach (var statusToDelete in orderedStatuses.Skip(1))
            {
                await DeleteAsync(statusToDelete.Package, statusToDelete.State, statusToDelete.AccessCondition, token);
            }

            return(result);
        }
        private bool DoesPackageExists(MemoryStorageFactory storageFactory, PackageState state, FeedPackageIdentity package)
        {
            var stateName       = Enum.GetName(typeof(PackageState), state);
            var storage         = storageFactory.Create(stateName.ToLowerInvariant());
            var packageFileName = GetPackageFileName(package.Id, package.Version);

            return(storage.Exists(packageFileName));
        }
 public PackageValidatorContext(FeedPackageIdentity package, IEnumerable <CatalogIndexEntry> catalogEntries)
 {
     Package        = package ?? throw new ArgumentNullException(nameof(package));
     CatalogEntries = catalogEntries ?? throw new ArgumentNullException(nameof(catalogEntries));
 }
 private Task <PackageMonitoringStatus> GetPackageAsync(CatalogStorage storage, FeedPackageIdentity package, CancellationToken token)
 {
     return(GetPackageAsync(storage, GetPackageFileName(package), token));
 }
 public PackageMonitoringStatus(PackageValidationResult result)
 {
     ValidationResult = result ?? throw new ArgumentNullException(nameof(result));
     Package          = new FeedPackageIdentity(result.Package);
 }
 private Uri GetPackageUri(CatalogStorage storage, FeedPackageIdentity package)
 {
     return(storage.ResolveUri(GetPackageFileName(package)));
 }
 public PackageMonitoringStatus(FeedPackageIdentity package, Exception exception)
 {
     Package             = package ?? throw new ArgumentNullException(nameof(package));
     ValidationException = exception ?? throw new ArgumentNullException(nameof(exception));
 }
Example #25
0
 public PackageMonitoringStatusListItem(FeedPackageIdentity package, PackageState state)
 {
     Package = package;
     State   = state;
 }
 public PackageValidatorContext(FeedPackageIdentity package, IEnumerable <CatalogIndexEntry> catalogEntries)
 {
     Package        = package;
     CatalogEntries = catalogEntries;
 }
        private Task SaveToStorage(MemoryStorageFactory storageFactory, PackageState state, FeedPackageIdentity package, StorageContent content)
        {
            var stateName       = Enum.GetName(typeof(PackageState), state);
            var storage         = storageFactory.Create(stateName.ToLowerInvariant());
            var packageFileName = GetPackageFileName(package.Id, package.Version);

            return(storage.SaveAsync(storage.ResolveUri(packageFileName), content, CancellationToken.None));
        }