Skip to content

Commit b896a7d

Browse files
committed
add tests for Anchore NVD Override advisory parsing and collection
1 parent 0bc427c commit b896a7d

1 file changed

Lines changed: 141 additions & 0 deletions

File tree

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
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+
import json
10+
import logging
11+
import pytest
12+
13+
from vulnerabilities.importer import AdvisoryDataV2
14+
from vulnerabilities.pipelines.v2_importers.anchore_importer import AnchoreImporterPipeline
15+
from vulnerabilities.pipelines.v2_importers.anchore_importer import parse_anchore_advisory
16+
17+
18+
class DummyVCSResponse:
19+
''' A dummy class to simulate the response from fetch_via_vcs for testing purposes.
20+
'''
21+
def __init__(self, dest_dir):
22+
self.dest_dir = str(dest_dir)
23+
24+
@pytest.fixture
25+
def pipeline():
26+
return AnchoreImporterPipeline() # the actual pipeline instance used in tests
27+
28+
29+
def test_parse_anchore_advisory_maps_basic_fields(tmp_path):
30+
'''
31+
Parse an Anchore advisory, the basic information gets put into the right places
32+
'''
33+
file_path = tmp_path / "data" / "nested" / "CVE-2024-0001.json"
34+
file_path.parent.mkdir(parents=True)
35+
36+
# fake raw data
37+
raw_data = {
38+
"description": "A sample advisory",
39+
"_annotation": {
40+
"description": "Ignored annotation description",
41+
"references": ["https://example.com/annotation"],
42+
},
43+
"cve": {
44+
"references": {
45+
"reference_data": [{"url": "https://example.com/cve-reference"}],
46+
}
47+
},
48+
}
49+
50+
advisory = parse_anchore_advisory(
51+
raw_data=raw_data,
52+
file_path=file_path,
53+
base_path=tmp_path,
54+
logger=logging.getLogger(__name__),
55+
)
56+
57+
assert isinstance(advisory, AdvisoryDataV2)
58+
assert advisory.advisory_id == "anchore/CVE-2024-0001"
59+
assert advisory.aliases == ["CVE-2024-0001"]
60+
assert advisory.summary == "A sample advisory"
61+
assert [ref.url for ref in advisory.references] == [
62+
"https://example.com/annotation",
63+
"https://example.com/cve-reference",
64+
]
65+
assert advisory.url == (
66+
"https://github.com/anchore/nvd-data-overrides/blob/main/data/nested/CVE-2024-0001.json"
67+
)
68+
69+
70+
def test_collect_advisories_yields_advisories_from_data_directory(tmp_path, pipeline):
71+
'''
72+
Test if it extracts advisories from the data directory
73+
- Find the data directory
74+
- Find the JSON files
75+
- Open the files
76+
- Read the JSON.
77+
- Parse the data
78+
- Create AdvisoryDataV2 objects
79+
- Return those advisories
80+
'''
81+
data_dir = tmp_path / "data"
82+
data_dir.mkdir(parents=True)
83+
84+
first = data_dir / "CVE-2024-0001.json"
85+
first.write_text(
86+
json.dumps(
87+
{
88+
"description": "First advisory",
89+
"_annotation": {"references": ["https://example.com/one"]},
90+
"cve": {"references": {"reference_data": [{"url": "https://example.com/one-bis"}]}}
91+
}
92+
)
93+
)
94+
95+
second = data_dir / "CVE-2024-0002.json"
96+
second.write_text(
97+
json.dumps(
98+
{
99+
"description": "Second advisory",
100+
"_annotation": {"references": ["https://example.com/two"]},
101+
"cve": {"references": {"reference_data": []}},
102+
}
103+
)
104+
)
105+
106+
pipeline.vcs_response = DummyVCSResponse(tmp_path)
107+
108+
advisories = list(pipeline.collect_advisories())
109+
advisory_ids = sorted(advisory.advisory_id for advisory in advisories)
110+
111+
assert advisory_ids == ["anchore/CVE-2024-0001", "anchore/CVE-2024-0002"]
112+
assert advisories[0].summary == "First advisory"
113+
assert advisories[1].summary == "Second advisory"
114+
115+
116+
def test_collect_advisories_returns_no_results_for_empty_data_directory(tmp_path, pipeline):
117+
'''
118+
Test that if the data directory is empty, no advisories are returned.
119+
'''
120+
data_dir = tmp_path / "data"
121+
data_dir.mkdir(parents=True)
122+
pipeline.vcs_response = DummyVCSResponse(tmp_path)
123+
124+
assert list(pipeline.collect_advisories()) == []
125+
126+
127+
def test_collect_advisories_handles_malformed_json(tmp_path, pipeline):
128+
'''
129+
Test a broken JSON file in the data directory, it should log a warning and continue.
130+
'''
131+
data_dir = tmp_path / "data"
132+
data_dir.mkdir(parents=True)
133+
(data_dir / "CVE-2024-0003.json").write_text("{not valid json")
134+
135+
pipeline.vcs_response = DummyVCSResponse(tmp_path)
136+
messages = []
137+
pipeline.log = lambda message, level=logging.INFO: messages.append((message, level))
138+
139+
assert list(pipeline.collect_advisories()) == []
140+
assert any("Failed to process advisory" in message for message, _ in messages)
141+

0 commit comments

Comments
 (0)