Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixing the vulnerability order inside the dictionary cache #8780

Merged
merged 4 commits into from
Sep 8, 2021

Conversation

sipmann
Copy link
Contributor

@sipmann sipmann commented Sep 1, 2021

Fixes #8703
I'm not sure how much this will impact the performance. Do we have an environment to do any kind of performance test?

I've tried to put the order inside the query but without success.
Accept any tips on this ❤

@sipmann sipmann requested a review from a team as a code owner September 1, 2021 19:23
@loic-sharma
Copy link
Contributor

loic-sharma commented Sep 1, 2021

Thanks for starting this! The PackageVulnerabilitiesCacheService loads all vulnerabilities into memory using a massive Entity Framework query. This query is already known to be quite slow, hence the caching. It may be better to avoid further complicating this query to avoid performance regressions.

This vulnerabilities information is later passed by the PackagesController to the factory that creates the view model. What do you think of sorting the vulnerabilities inside of this view model factory? The drawback I see is that we will do redundant sorting, however, this should be acceptable as most packages don't have vulnerabilities.

@sipmann
Copy link
Contributor Author

sipmann commented Sep 1, 2021

Sounds good to me. I'll do the change ;)

@sipmann
Copy link
Contributor Author

sipmann commented Sep 2, 2021

Do you think this needs a test @loic-sharma ?

@loic-sharma
Copy link
Contributor

Yup please add unit tests. It looks like we have a test gap currently, but you should be able to mirror the test on the deprecations here:

[Theory]
[MemberData(nameof(DeprecationFieldsAreSetAsExpected_Data))]
public void DeprecationFieldsAreSetAsExpected(
PackageDeprecationStatus status,
bool hasAlternateRegistration,
bool hasAlternatePackage)
{
// Arrange
var deprecation = new PackageDeprecation
{
Status = status,
CustomMessage = "hello",
};
var alternateRegistrationId = "alternateRegistrationId";
if (hasAlternateRegistration)
{
var registration = new PackageRegistration
{
Id = alternateRegistrationId
};
deprecation.AlternatePackageRegistration = registration;
}
var alternatePackageRegistrationId = "alternatePackageRegistration";
var alternatePackageVersion = "1.0.0-alt";
if (hasAlternatePackage)
{
var alternatePackageRegistration = new PackageRegistration
{
Id = alternatePackageRegistrationId
};
var alternatePackage = new Package
{
Version = alternatePackageVersion,
PackageRegistration = alternatePackageRegistration
};
deprecation.AlternatePackage = alternatePackage;
}
var package = CreateTestPackage("1.0.0");
var packageKeyToDeprecation = new Dictionary<int, PackageDeprecation>
{
{ 123, deprecation }
};
// Act
var model = CreateDisplayPackageViewModel(
package,
currentUser: null,
packageKeyToDeprecation: packageKeyToDeprecation,
readmeHtml: null);
// Assert
Assert.Equal(status, model.DeprecationStatus);
Assert.Equal(deprecation.CustomMessage, model.CustomMessage);
if (hasAlternatePackage)
{
Assert.Equal(alternatePackageRegistrationId, model.AlternatePackageId);
Assert.Equal(alternatePackageVersion, model.AlternatePackageVersion);
}
else if (hasAlternateRegistration)
{
Assert.Equal(alternateRegistrationId, model.AlternatePackageId);
Assert.Null(model.AlternatePackageVersion);
}
else
{
Assert.Null(model.AlternatePackageId);
Assert.Null(model.AlternatePackageVersion);
}
var versionModel = model.PackageVersions.Single();
Assert.Equal(status, versionModel.DeprecationStatus);
Assert.Null(versionModel.AlternatePackageId);
Assert.Null(versionModel.AlternatePackageVersion);
Assert.Null(versionModel.CustomMessage);
}

A test like "arrange 3 vulnerabilities with different severities out-of-order and assert the resulting model's vulnerabilities are in order" should be perfect. Let us know if you have questions!

@dnfgituser
Copy link

dnfgituser commented Sep 6, 2021

CLA assistant check
All CLA requirements met.

var versionModel = model.PackageVersions.Single();
Assert.Null(versionModel.CustomMessage);
Assert.NotNull(model.Vulnerabilities);
Assert.Equal(model.Vulnerabilities, packageKeyToVulnerabilities[package.Key].OrderByDescending(p => p.Severity).ToList().AsReadOnly());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm worried someone could break this logic if they re-order the PackageVulnerabilitySeverity enum. To prevent this mistake, we could manually verify the order here:

Suggested change
Assert.Equal(model.Vulnerabilities, packageKeyToVulnerabilities[package.Key].OrderByDescending(p => p.Severity).ToList().AsReadOnly());
Assert.Equal(PackageVulnerabilitySeverity.Critical, model.Vulnerabilities[0].Severity);
Assert.Equal(PackageVulnerabilitySeverity.High, model.Vulnerabilities[1].Severity);
Assert.Equal(PackageVulnerabilitySeverity.Low, model.Vulnerabilities[2].Severity);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For sure :)

@joelverhagen
Copy link
Member

@agr (on-call) or @loic-sharma (point of contact), could you shepherd this PR into a merged state?

@loic-sharma loic-sharma merged commit 7041064 into NuGet:dev Sep 8, 2021
@loic-sharma
Copy link
Contributor

@sipmann Thanks for the contribution! This will be included in our next nuget.org deployment. You can track our progress using this work item: #8703

@joelverhagen Yup can do.

@sipmann sipmann deleted the sipmann-8703 branch September 10, 2021 14:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants