Skip to content

Commit 3ea12c3

Browse files
committed
Add test for base and pypa importer pipeline
Signed-off-by: Keshav Priyadarshi <git@keshav.space>
1 parent 29d96d3 commit 3ea12c3

7 files changed

Lines changed: 172 additions & 26 deletions

File tree

vulnerabilities/import_runner.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818

1919
from vulnerabilities.importer import AdvisoryData
2020
from vulnerabilities.importer import Importer
21-
from vulnerabilities.importers import IMPORTERS_REGISTRY
2221
from vulnerabilities.improver import Inference
2322
from vulnerabilities.improvers.default import DefaultImporter
2423
from vulnerabilities.models import Advisory

vulnerabilities/pipelines/__init__.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33
# VulnerableCode is a trademark of nexB Inc.
44
# SPDX-License-Identifier: Apache-2.0
55
# See http://www.apache.org/licenses/LICENSE-2.0 for the license text.
6-
# See https://github.com/nexB/vulnerablecode for support or download.
6+
# See https://github.com/aboutcode-org/vulnerablecode for support or download.
77
# See https://aboutcode.org for more information about nexB OSS projects.
88
#
9+
910
import logging
1011
from datetime import datetime
1112
from datetime import timezone
@@ -17,8 +18,8 @@
1718

1819
from vulnerabilities.importer import AdvisoryData
1920
from vulnerabilities.improver import MAX_CONFIDENCE
20-
from vulnerabilities.pipelines.pipes.importer import import_advisory
21-
from vulnerabilities.pipelines.pipes.importer import insert_advisory
21+
from vulnerabilities.pipes.importer import import_advisory
22+
from vulnerabilities.pipes.importer import insert_advisory
2223
from vulnerabilities.utils import classproperty
2324

2425
module_logger = logging.getLogger(__name__)

vulnerabilities/pipelines/pipes/importer.py renamed to vulnerabilities/pipes/importer.py

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33
# VulnerableCode is a trademark of nexB Inc.
44
# SPDX-License-Identifier: Apache-2.0
55
# See http://www.apache.org/licenses/LICENSE-2.0 for the license text.
6-
# See https://github.com/nexB/vulnerablecode for support or download.
6+
# See https://github.com/aboutcode-org/vulnerablecode for support or download.
77
# See https://aboutcode.org for more information about nexB OSS projects.
88
#
9+
910
import logging
1011
from datetime import datetime
1112
from datetime import timezone
@@ -14,10 +15,8 @@
1415

1516
from django.db import transaction
1617

17-
from vulnerabilities import import_runner
1818
from vulnerabilities.importer import AdvisoryData
1919
from vulnerabilities.improver import MAX_CONFIDENCE
20-
from vulnerabilities.improvers import default
2120
from vulnerabilities.models import Advisory
2221
from vulnerabilities.models import Package
2322
from vulnerabilities.models import PackageRelatedVulnerability
@@ -55,18 +54,21 @@ def insert_advisory(advisory: AdvisoryData, pipeline_name: str, logger: Callable
5554
def import_advisory(
5655
advisory: Advisory,
5756
pipeline_name: str,
58-
logger: Callable,
5957
confidence: int = MAX_CONFIDENCE,
58+
logger: Callable = None,
6059
):
6160
"""
6261
Create initial Vulnerability Package relationships for the advisory,
6362
including references and severity scores.
6463
6564
Package relationships are established only for resolved (concrete) versions.
6665
"""
66+
from vulnerabilities import import_runner
67+
from vulnerabilities.improvers import default
6768

6869
advisory_data: AdvisoryData = advisory.to_advisory_data()
69-
logger(f"Importing advisory id: {advisory.id}", level=logging.DEBUG)
70+
if logger:
71+
logger(f"Importing advisory id: {advisory.id}", level=logging.DEBUG)
7072

7173
affected_purls = []
7274
fixed_purls = []
@@ -85,7 +87,8 @@ def import_advisory(
8587
)
8688

8789
if not vulnerability:
88-
logger(f"Unable to get vulnerability for advisory: {advisory!r}", level=logging.WARNING)
90+
if logger:
91+
logger(f"Unable to get vulnerability for advisory: {advisory!r}", level=logging.WARNING)
8992
return
9093

9194
for ref in advisory_data.references:
@@ -118,16 +121,18 @@ def import_advisory(
118121
},
119122
)
120123
except:
121-
logger(
122-
f"Failed to create VulnerabilitySeverity for: {severity} with error:\n{traceback_format_exc()}",
123-
level=logging.ERROR,
124-
)
124+
if logger:
125+
logger(
126+
f"Failed to create VulnerabilitySeverity for: {severity} with error:\n{traceback_format_exc()}",
127+
level=logging.ERROR,
128+
)
125129
if not created:
126-
logger(
127-
f"Severity updated for reference {ref!r} to value: {severity.value!r} "
128-
f"and scoring_elements: {severity.scoring_elements!r}",
129-
level=logging.DEBUG,
130-
)
130+
if logger:
131+
logger(
132+
f"Severity updated for reference {ref!r} to value: {severity.value!r} "
133+
f"and scoring_elements: {severity.scoring_elements!r}",
134+
level=logging.DEBUG,
135+
)
131136

132137
for affected_purl in affected_purls or []:
133138
vulnerable_package, _ = Package.objects.get_or_create_from_purl(purl=affected_purl)

vulnerabilities/tests/__init__.py

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,52 @@
33
# VulnerableCode is a trademark of nexB Inc.
44
# SPDX-License-Identifier: Apache-2.0
55
# See http://www.apache.org/licenses/LICENSE-2.0 for the license text.
6-
# See https://github.com/nexB/vulnerablecode for support or download.
6+
# See https://github.com/aboutcode-org/vulnerablecode for support or download.
77
# See https://aboutcode.org for more information about nexB OSS projects.
88
#
9+
10+
from django.utils import timezone
11+
from packageurl import PackageURL
12+
from univers.version_range import VersionRange
13+
14+
from vulnerabilities import models
15+
from vulnerabilities.importer import AdvisoryData
16+
from vulnerabilities.importer import AffectedPackage
17+
from vulnerabilities.importer import Reference
18+
19+
advisory_data1 = AdvisoryData(
20+
aliases=["CVE-2020-13371337"],
21+
summary="vulnerability description here",
22+
affected_packages=[
23+
AffectedPackage(
24+
package=PackageURL(type="pypi", name="dummy"),
25+
affected_version_range=VersionRange.from_string("vers:pypi/>=1.0.0|<=2.0.0"),
26+
)
27+
],
28+
references=[Reference(url="https://example.com/with/more/info/CVE-2020-13371337")],
29+
date_published=timezone.now(),
30+
url="https://test.com",
31+
)
32+
33+
34+
advisory1 = models.Advisory(
35+
aliases=advisory_data1.aliases,
36+
summary=advisory_data1.summary,
37+
affected_packages=[pkg.to_dict() for pkg in advisory_data1.affected_packages],
38+
references=[ref.to_dict() for ref in advisory_data1.references],
39+
url=advisory_data1.url,
40+
created_by="tests",
41+
date_collected=timezone.now(),
42+
)
43+
44+
45+
def get_all_vulnerability_relationships_objects():
46+
return {
47+
"vulnerabilities": list(models.Vulnerability.objects.all()),
48+
"aliases": list(models.Alias.objects.all()),
49+
"references": list(models.VulnerabilityReference.objects.all()),
50+
"advisories": list(models.Advisory.objects.all()),
51+
"packages": list(models.Package.objects.all()),
52+
"references": list(models.VulnerabilityReference.objects.all()),
53+
"severity": list(models.VulnerabilitySeverity.objects.all()),
54+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
#
2+
# Copyright (c) nexB Inc. and others. All rights reserved.
3+
# VulnerableCode is a trademark of nexB Inc.
4+
# SPDX-License-Identifier: Apache-2.0
5+
# See http://www.apache.org/licenses/LICENSE-2.0 for the license text.
6+
# See https://github.com/aboutcode-org/vulnerablecode for support or download.
7+
# See https://aboutcode.org for more information about nexB OSS projects.
8+
#
9+
10+
from unittest.mock import patch
11+
12+
from django.test import TestCase
13+
14+
from vulnerabilities import models
15+
from vulnerabilities.pipelines import VulnerableCodeBaseImporterPipeline
16+
from vulnerabilities.tests import advisory1
17+
from vulnerabilities.tests import advisory_data1
18+
19+
20+
class TestVulnerableCodeBaseImporterPipeline(TestCase):
21+
@patch.object(
22+
VulnerableCodeBaseImporterPipeline,
23+
"collect_advisories",
24+
return_value=[advisory_data1],
25+
)
26+
@patch.object(
27+
VulnerableCodeBaseImporterPipeline,
28+
"advisories_count",
29+
return_value=1,
30+
)
31+
def test_collect_and_store_advisories(self, mock_advisories_count, mock_collect_advisories):
32+
self.assertEqual(0, models.Advisory.objects.count())
33+
34+
base_pipeline = VulnerableCodeBaseImporterPipeline()
35+
base_pipeline.collect_and_store_advisories()
36+
37+
mock_advisories_count.assert_called_once()
38+
mock_collect_advisories.assert_called_once()
39+
40+
self.assertEqual(1, models.Advisory.objects.count())
41+
42+
collected_advisory = models.Advisory.objects.first()
43+
result_aliases = collected_advisory.aliases
44+
expected_aliases = advisory_data1.aliases
45+
46+
self.assertEqual(expected_aliases, result_aliases)
47+
self.assertEqual(base_pipeline.qualified_name, collected_advisory.created_by)
48+
49+
def test_import_new_advisories(self):
50+
self.assertEqual(0, models.Vulnerability.objects.count())
51+
52+
base_pipeline = VulnerableCodeBaseImporterPipeline()
53+
base_pipeline.new_advisories = [advisory1]
54+
base_pipeline.import_new_advisories()
55+
56+
self.assertEqual(1, models.Vulnerability.objects.count())
57+
58+
imported_vulnerability = models.Vulnerability.objects.first()
59+
60+
self.assertEqual(1, imported_vulnerability.aliases.count())
61+
62+
expected_alias = imported_vulnerability.aliases.first()
63+
self.assertEqual(advisory1.aliases[0], expected_alias.alias)

vulnerabilities/tests/pipelines/test_pypa_importer_pipeline.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,27 @@
33
# VulnerableCode is a trademark of nexB Inc.
44
# SPDX-License-Identifier: Apache-2.0
55
# See http://www.apache.org/licenses/LICENSE-2.0 for the license text.
6-
# See https://github.com/nexB/vulnerablecode for support or download.
6+
# See https://github.com/aboutcode-org/vulnerablecode for support or download.
77
# See https://aboutcode.org for more information about nexB OSS projects.
88
#
9+
910
import os
11+
from pathlib import Path
1012
from unittest import TestCase
1113

1214
import saneyaml
1315

1416
from vulnerabilities.importers.osv import parse_advisory_data
1517
from vulnerabilities.tests import util_tests
1618

17-
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
18-
TEST_DATA = os.path.join(BASE_DIR, "test_data/pypa")
19+
TEST_DATA = data = Path(__file__).parent.parent / "test_data" / "pypa"
1920

2021

21-
class TestPyPaImporter(TestCase):
22+
class TestPyPaImporterPipeline(TestCase):
2223
def test_to_advisories_with_summary(self):
23-
with open(os.path.join(TEST_DATA, "pypa_test.yaml")) as f:
24-
mock_response = saneyaml.load(f)
24+
pypa_advisory_path = TEST_DATA / "pypa_test.yaml"
25+
26+
mock_response = saneyaml.load(pypa_advisory_path.read_text())
2527
expected_file = os.path.join(TEST_DATA, "pypa-expected.json")
2628
imported_data = parse_advisory_data(
2729
mock_response,
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#
2+
# Copyright (c) nexB Inc. and others. All rights reserved.
3+
# VulnerableCode is a trademark of nexB Inc.
4+
# SPDX-License-Identifier: Apache-2.0
5+
# See http://www.apache.org/licenses/LICENSE-2.0 for the license text.
6+
# See https://github.com/aboutcode-org/vulnerablecode for support or download.
7+
# See https://aboutcode.org for more information about nexB OSS projects.
8+
#
9+
10+
import pytest
11+
12+
from vulnerabilities.pipes.importer import import_advisory
13+
from vulnerabilities.tests import advisory1
14+
from vulnerabilities.tests import get_all_vulnerability_relationships_objects
15+
16+
17+
@pytest.mark.django_db
18+
def test_vulnerability_pipes_importer_import_advisory():
19+
import_advisory(advisory=advisory1, pipeline_name="test_importer_pipeline")
20+
all_vulnerability_relation_objects = get_all_vulnerability_relationships_objects()
21+
import_advisory(advisory=advisory1, pipeline_name="test_importer_pipeline")
22+
assert all_vulnerability_relation_objects == get_all_vulnerability_relationships_objects()
23+
24+
25+
@pytest.mark.django_db
26+
def test_vulnerability_pipes_importer_import_advisory_different_pipelines():
27+
import_advisory(advisory=advisory1, pipeline_name="test_importer1_pipeline")
28+
all_vulnerability_relation_objects = get_all_vulnerability_relationships_objects()
29+
import_advisory(advisory=advisory1, pipeline_name="test_importer2_pipeline")
30+
assert all_vulnerability_relation_objects == get_all_vulnerability_relationships_objects()

0 commit comments

Comments
 (0)