Skip to content

Commit a948895

Browse files
committed
add unit tests
Signed-off-by: tdruez <tdruez@aboutcode.org>
1 parent db6fffc commit a948895

3 files changed

Lines changed: 295 additions & 0 deletions

File tree

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
#
2+
# Copyright (c) nexB Inc. and others. All rights reserved.
3+
# DejaCode is a trademark of nexB Inc.
4+
# SPDX-License-Identifier: AGPL-3.0-only
5+
# See https://github.com/aboutcode-org/dejacode for support or download.
6+
# See https://aboutcode.org for more information about AboutCode FOSS projects.
7+
#
8+
9+
from django.test import TestCase
10+
11+
from component_catalog.tests import make_package
12+
from dje.models import Dataspace
13+
from license_library.models import License
14+
from organization.models import Owner
15+
from product_portfolio.filters import ProductPackageFilterSet
16+
from product_portfolio.models import ProductPackage
17+
from product_portfolio.tests import make_product
18+
19+
20+
class ProductPackageFilterSetTestCase(TestCase):
21+
def setUp(self):
22+
self.dataspace = Dataspace.objects.create(name="Reference")
23+
self.owner = Owner.objects.create(name="Owner1", dataspace=self.dataspace)
24+
self.license1 = License.objects.create(
25+
key="mit",
26+
name="MIT",
27+
short_name="MIT",
28+
owner=self.owner,
29+
dataspace=self.dataspace,
30+
)
31+
self.license2 = License.objects.create(
32+
key="apache-2.0",
33+
name="Apache 2.0",
34+
short_name="Apache 2.0",
35+
owner=self.owner,
36+
dataspace=self.dataspace,
37+
)
38+
39+
self.product = make_product(self.dataspace)
40+
self.package1 = make_package(self.dataspace)
41+
self.package2 = make_package(self.dataspace)
42+
self.package3 = make_package(self.dataspace)
43+
44+
self.pp1 = ProductPackage.objects.create(
45+
product=self.product,
46+
package=self.package1,
47+
license_expression=self.license1.key,
48+
dataspace=self.dataspace,
49+
)
50+
self.pp2 = ProductPackage.objects.create(
51+
product=self.product,
52+
package=self.package2,
53+
license_expression=self.license2.key,
54+
dataspace=self.dataspace,
55+
)
56+
self.pp3 = ProductPackage.objects.create(
57+
product=self.product,
58+
package=self.package3,
59+
license_expression="",
60+
dataspace=self.dataspace,
61+
)
62+
63+
def test_product_package_filterset_licenses(self):
64+
data = {"licenses": [self.license1.key]}
65+
filterset = ProductPackageFilterSet(dataspace=self.dataspace, data=data)
66+
self.assertQuerySetEqual(filterset.qs, [self.pp1])
67+
68+
data = {"licenses": [self.license2.key]}
69+
filterset = ProductPackageFilterSet(dataspace=self.dataspace, data=data)
70+
self.assertQuerySetEqual(filterset.qs, [self.pp2])
71+
72+
data = {"licenses": [self.license1.key, self.license2.key]}
73+
filterset = ProductPackageFilterSet(dataspace=self.dataspace, data=data)
74+
self.assertQuerySetEqual(filterset.qs, [self.pp1, self.pp2], ordered=False)
75+
76+
def test_product_package_filterset_has_licenses(self):
77+
data = {"has_licenses": "yes"}
78+
filterset = ProductPackageFilterSet(dataspace=self.dataspace, data=data)
79+
self.assertQuerySetEqual(filterset.qs, [self.pp1, self.pp2], ordered=False)
80+
81+
data = {"has_licenses": "no"}
82+
filterset = ProductPackageFilterSet(dataspace=self.dataspace, data=data)
83+
self.assertQuerySetEqual(filterset.qs, [self.pp3])

product_portfolio/tests/test_views.py

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3417,3 +3417,151 @@ def test_product_portfolio_vulnerability_analysis_form_view(self):
34173417
self.assertEqual(product_package, analysis.product_package)
34183418
self.assertEqual(vulnerability1, analysis.vulnerability)
34193419
self.assertEqual("resolved", analysis.state)
3420+
3421+
def test_product_portfolio_tab_compliance_view_empty(self):
3422+
self.client.login(username="nexb_user", password="secret")
3423+
url = self.product1.get_url("tab_compliance")
3424+
response = self.client.get(url)
3425+
self.assertEqual(200, response.status_code)
3426+
self.assertEqual(0, response.context["total_packages"])
3427+
self.assertEqual(100, response.context["license_compliance_pct"])
3428+
self.assertEqual(100, response.context["license_coverage_pct"])
3429+
self.assertEqual(0, response.context["vulnerability_count"])
3430+
3431+
def test_product_portfolio_tab_compliance_view_package_compliance(self):
3432+
self.client.login(username="nexb_user", password="secret")
3433+
3434+
owner1 = Owner.objects.create(name="Owner1", dataspace=self.dataspace)
3435+
license1 = License.objects.create(
3436+
key="l1", name="L1", short_name="L1", owner=owner1, dataspace=self.dataspace
3437+
)
3438+
package_policy = UsagePolicy.objects.create(
3439+
label="PackagePolicy",
3440+
icon="icon",
3441+
content_type=ContentType.objects.get_for_model(Package),
3442+
compliance_alert=UsagePolicy.Compliance.ERROR,
3443+
dataspace=self.dataspace,
3444+
)
3445+
3446+
package2 = make_package(self.dataspace, usage_policy=package_policy)
3447+
package3 = make_package(self.dataspace)
3448+
3449+
# package2 has a policy issue, package3 does not
3450+
ProductPackage.objects.create(
3451+
product=self.product1,
3452+
package=package2,
3453+
dataspace=self.dataspace,
3454+
license_expression=license1.key,
3455+
)
3456+
ProductPackage.objects.create(
3457+
product=self.product1,
3458+
package=package3,
3459+
dataspace=self.dataspace,
3460+
)
3461+
3462+
url = self.product1.get_url("tab_compliance")
3463+
response = self.client.get(url)
3464+
self.assertEqual(2, response.context["total_packages"])
3465+
self.assertEqual(1, response.context["package_issues_count"])
3466+
# One package without license expression
3467+
self.assertEqual(1, response.context["package_without_license_count"])
3468+
self.assertEqual(50, response.context["license_coverage_pct"])
3469+
3470+
def test_product_portfolio_tab_compliance_view_license_compliance(self):
3471+
self.client.login(username="nexb_user", password="secret")
3472+
3473+
owner1 = Owner.objects.create(name="Owner1", dataspace=self.dataspace)
3474+
license_policy_error = UsagePolicy.objects.create(
3475+
label="LicensePolicyError",
3476+
icon="icon",
3477+
content_type=ContentType.objects.get_for_model(License),
3478+
compliance_alert=UsagePolicy.Compliance.ERROR,
3479+
dataspace=self.dataspace,
3480+
)
3481+
license_policy_warning = UsagePolicy.objects.create(
3482+
label="LicensePolicyWarning",
3483+
icon="icon",
3484+
content_type=ContentType.objects.get_for_model(License),
3485+
compliance_alert=UsagePolicy.Compliance.WARNING,
3486+
dataspace=self.dataspace,
3487+
)
3488+
license1 = License.objects.create(
3489+
key="l1",
3490+
name="L1",
3491+
short_name="L1",
3492+
owner=owner1,
3493+
usage_policy=license_policy_error,
3494+
dataspace=self.dataspace,
3495+
)
3496+
license2 = License.objects.create(
3497+
key="l2",
3498+
name="L2",
3499+
short_name="L2",
3500+
owner=owner1,
3501+
usage_policy=license_policy_warning,
3502+
dataspace=self.dataspace,
3503+
)
3504+
3505+
package2 = make_package(self.dataspace)
3506+
package3 = make_package(self.dataspace)
3507+
ProductPackage.objects.create(
3508+
product=self.product1,
3509+
package=package2,
3510+
dataspace=self.dataspace,
3511+
license_expression=license1.key,
3512+
)
3513+
ProductPackage.objects.create(
3514+
product=self.product1,
3515+
package=package3,
3516+
dataspace=self.dataspace,
3517+
license_expression=license2.key,
3518+
)
3519+
3520+
url = self.product1.get_url("tab_compliance")
3521+
response = self.client.get(url)
3522+
self.assertEqual(2, response.context["license_issues_count"])
3523+
self.assertEqual(1, response.context["license_error_count"])
3524+
self.assertEqual(1, response.context["license_warning_count"])
3525+
# Both packages have license issues, so 0% compliance
3526+
self.assertEqual(0, response.context["license_compliance_pct"])
3527+
3528+
def test_product_portfolio_tab_compliance_view_security_compliance(self):
3529+
self.client.login(username="nexb_user", password="secret")
3530+
3531+
p1 = make_package(self.dataspace)
3532+
p2 = make_package(self.dataspace)
3533+
p3 = make_package(self.dataspace)
3534+
make_vulnerability(self.dataspace, affecting=[p1], risk_score=9.0)
3535+
make_vulnerability(self.dataspace, affecting=[p2], risk_score=6.5)
3536+
make_vulnerability(self.dataspace, affecting=[p3], risk_score=2.0)
3537+
3538+
product1 = make_product(self.dataspace, inventory=[p1, p2, p3])
3539+
url = product1.get_url("tab_compliance")
3540+
response = self.client.get(url)
3541+
3542+
self.assertEqual(3, response.context["vulnerability_count"])
3543+
self.assertEqual(3, response.context["above_threshold_count"])
3544+
self.assertEqual("critical", response.context["max_vulnerability_severity"])
3545+
self.assertEqual(1, response.context["critical_count"])
3546+
self.assertEqual(1, response.context["high_count"])
3547+
self.assertEqual(0, response.context["medium_count"])
3548+
self.assertEqual(1, response.context["low_count"])
3549+
3550+
def test_product_portfolio_tab_compliance_view_security_with_risk_threshold(self):
3551+
self.client.login(username="nexb_user", password="secret")
3552+
3553+
p1 = make_package(self.dataspace)
3554+
p2 = make_package(self.dataspace)
3555+
make_vulnerability(self.dataspace, affecting=[p1], risk_score=9.0)
3556+
make_vulnerability(self.dataspace, affecting=[p2], risk_score=2.0)
3557+
3558+
product1 = make_product(self.dataspace, inventory=[p1, p2])
3559+
product1.update(vulnerabilities_risk_threshold=6.0)
3560+
3561+
url = product1.get_url("tab_compliance")
3562+
response = self.client.get(url)
3563+
3564+
self.assertEqual(2, response.context["vulnerability_count"])
3565+
self.assertEqual(1, response.context["above_threshold_count"])
3566+
self.assertEqual("high", response.context["risk_threshold"])
3567+
self.assertEqual(6.0, response.context["risk_threshold_number"])

vulnerabilities/tests/test_models.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
from product_portfolio.tests import make_product_package
2525
from vulnerabilities.models import Vulnerability
2626
from vulnerabilities.models import VulnerabilityAnalysis
27+
from vulnerabilities.models import get_risk_level
2728
from vulnerabilities.tests import make_vulnerability
2829
from vulnerabilities.tests import make_vulnerability_analysis
2930

@@ -369,3 +370,66 @@ def test_vulnerability_model_vulnerability_propagate(self):
369370
analysis1.update(state=VulnerabilityAnalysis.State.EXPLOITABLE)
370371
new_analysis = analysis1.propagate(product2.uuid, self.super_user)
371372
self.assertEqual(VulnerabilityAnalysis.State.EXPLOITABLE, new_analysis.state)
373+
374+
def test_vulnerability_model_get_risk_level(self):
375+
self.assertEqual("", get_risk_level(None))
376+
self.assertEqual("", get_risk_level(0.0))
377+
self.assertEqual("low", get_risk_level(0.1))
378+
self.assertEqual("low", get_risk_level(2.9))
379+
self.assertEqual("medium", get_risk_level(3.0))
380+
self.assertEqual("medium", get_risk_level(5.9))
381+
self.assertEqual("high", get_risk_level(6.0))
382+
self.assertEqual("high", get_risk_level(7.9))
383+
self.assertEqual("critical", get_risk_level(8.0))
384+
self.assertEqual("critical", get_risk_level(10.0))
385+
self.assertEqual("", get_risk_level(10.1))
386+
self.assertEqual("high", get_risk_level("7.5"))
387+
388+
def test_vulnerability_model_risk_level_generated_field(self):
389+
vulnerability1 = make_vulnerability(dataspace=self.dataspace, risk_score=None)
390+
self.assertEqual("", vulnerability1.risk_level)
391+
392+
vulnerability1.risk_score = 0.0
393+
vulnerability1.save()
394+
vulnerability1.refresh_from_db()
395+
self.assertEqual("", vulnerability1.risk_level)
396+
397+
vulnerability1.risk_score = 0.1
398+
vulnerability1.save()
399+
vulnerability1.refresh_from_db()
400+
self.assertEqual("low", vulnerability1.risk_level)
401+
402+
vulnerability1.risk_score = 2.9
403+
vulnerability1.save()
404+
vulnerability1.refresh_from_db()
405+
self.assertEqual("low", vulnerability1.risk_level)
406+
407+
vulnerability1.risk_score = 3.0
408+
vulnerability1.save()
409+
vulnerability1.refresh_from_db()
410+
self.assertEqual("medium", vulnerability1.risk_level)
411+
412+
vulnerability1.risk_score = 5.9
413+
vulnerability1.save()
414+
vulnerability1.refresh_from_db()
415+
self.assertEqual("medium", vulnerability1.risk_level)
416+
417+
vulnerability1.risk_score = 6.0
418+
vulnerability1.save()
419+
vulnerability1.refresh_from_db()
420+
self.assertEqual("high", vulnerability1.risk_level)
421+
422+
vulnerability1.risk_score = 7.9
423+
vulnerability1.save()
424+
vulnerability1.refresh_from_db()
425+
self.assertEqual("high", vulnerability1.risk_level)
426+
427+
vulnerability1.risk_score = 8.0
428+
vulnerability1.save()
429+
vulnerability1.refresh_from_db()
430+
self.assertEqual("critical", vulnerability1.risk_level)
431+
432+
vulnerability1.risk_score = 10.0
433+
vulnerability1.save()
434+
vulnerability1.refresh_from_db()
435+
self.assertEqual("critical", vulnerability1.risk_level)

0 commit comments

Comments
 (0)