Skip to content

Commit eeff049

Browse files
committed
Add tests
Signed-off-by: Tushar Goel <tushar.goel.dav@gmail.com>
1 parent 72a58e6 commit eeff049

File tree

1 file changed

+151
-0
lines changed

1 file changed

+151
-0
lines changed
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
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.models import SSVC
13+
from vulnerabilities.models import AdvisorySeverity
14+
from vulnerabilities.models import AdvisoryV2
15+
from vulnerabilities.pipelines.v2_importers.vulnrichment_importer import VulnrichImporterPipeline
16+
from vulnerabilities.pipelines.v2_improvers.collect_ssvc_trees import CollectSSVCPipeline
17+
from vulnerabilities.pipelines.v2_improvers.collect_ssvc_trees import (
18+
convert_vector_to_tree_and_decision,
19+
)
20+
from vulnerabilities.severity_systems import SCORING_SYSTEMS
21+
from datetime import datetime
22+
23+
24+
@pytest.fixture
25+
def ssvc_scoring_system():
26+
return SCORING_SYSTEMS["ssvc"]
27+
28+
29+
@pytest.fixture
30+
def vulnrichment_advisory(db):
31+
return AdvisoryV2.objects.create(
32+
datasource_id=VulnrichImporterPipeline.pipeline_id,
33+
advisory_id="TEST-2024-0001",
34+
avid="vulnrichment/TEST-2024-0001",
35+
url="https://example.com/advisory/TEST-2024-0001",
36+
unique_content_id="unique-1234",
37+
date_collected=datetime.now(),
38+
)
39+
40+
41+
@pytest.fixture
42+
def ssvc_severity(vulnrichment_advisory, ssvc_scoring_system):
43+
severity = AdvisorySeverity.objects.create(
44+
scoring_system=ssvc_scoring_system,
45+
scoring_elements="SSVCv2/E:A/A:Y/T:T/P:E/B:I/M:H/D:C",
46+
)
47+
vulnrichment_advisory.severities.add(severity)
48+
vulnrichment_advisory.save()
49+
return severity
50+
51+
52+
@pytest.fixture
53+
def related_advisory(db):
54+
return AdvisoryV2.objects.create(
55+
datasource_id="other_importer",
56+
advisory_id="TEST-2024-0001",
57+
avid="other/TEST-2024-0001",
58+
url="https://example.com/related/TEST-2024-0001",
59+
unique_content_id="unique-5678",
60+
date_collected=datetime.now(),
61+
)
62+
63+
64+
def test_convert_vector_valid():
65+
vector = "SSVCv2/E:A/A:Y/T:T/P:E/B:I/M:H/D:C"
66+
67+
tree, decision = convert_vector_to_tree_and_decision(vector)
68+
69+
assert decision == "Act"
70+
71+
assert tree == [
72+
{"Exploitation": "active"},
73+
{"Automatable": "yes"},
74+
{"Technical Impact": "total"},
75+
{"Mission Prevalence": "essential"},
76+
{"Public Well-being Impact": "irreversible"},
77+
{"Mission & Well-being": "high"},
78+
]
79+
80+
81+
def test_convert_vector_missing_decision():
82+
vector = "SSVCv2/E:N/A:N/T:P/P:M/B:M/M:L"
83+
84+
tree, decision = convert_vector_to_tree_and_decision(vector)
85+
86+
assert decision is None
87+
assert len(tree) == 6
88+
89+
90+
def test_convert_vector_invalid_prefix():
91+
with pytest.raises(ValueError):
92+
convert_vector_to_tree_and_decision("INVALID/E:A/D:C")
93+
94+
95+
def test_convert_vector_unknown_keys_ignored():
96+
vector = "SSVCv2/E:A/X:Z/D:T"
97+
98+
tree, decision = convert_vector_to_tree_and_decision(vector)
99+
100+
assert decision == "Track"
101+
assert tree == [{"Exploitation": "active"}]
102+
103+
104+
@pytest.mark.django_db
105+
def test_collect_ssvc_creates_ssvc_object(
106+
vulnrichment_advisory,
107+
ssvc_severity,
108+
):
109+
pipeline = CollectSSVCPipeline()
110+
111+
pipeline.collect_ssvc_data()
112+
113+
ssvc_qs = SSVC.objects.filter(source_advisory=vulnrichment_advisory)
114+
115+
assert ssvc_qs.count() == 1
116+
117+
ssvc = ssvc_qs.first()
118+
assert ssvc.decision == "Act"
119+
assert ssvc.vector == ssvc_severity.scoring_elements
120+
assert isinstance(ssvc.options, list)
121+
assert len(ssvc.options) == 6
122+
123+
124+
@pytest.mark.django_db
125+
def test_collect_ssvc_links_related_advisories(
126+
vulnrichment_advisory,
127+
ssvc_severity,
128+
related_advisory,
129+
):
130+
pipeline = CollectSSVCPipeline()
131+
pipeline.collect_ssvc_data()
132+
133+
ssvc = SSVC.objects.get(source_advisory=vulnrichment_advisory)
134+
135+
related_ids = list(ssvc.related_advisories.values_list("id", flat=True))
136+
137+
assert related_advisory.id in related_ids
138+
assert vulnrichment_advisory.id not in related_ids
139+
140+
141+
@pytest.mark.django_db
142+
def test_collect_ssvc_idempotent(
143+
vulnrichment_advisory,
144+
ssvc_severity,
145+
):
146+
pipeline = CollectSSVCPipeline()
147+
148+
pipeline.collect_ssvc_data()
149+
pipeline.collect_ssvc_data()
150+
151+
assert SSVC.objects.filter(source_advisory=vulnrichment_advisory).count() == 1

0 commit comments

Comments
 (0)