Skip to content

Commit c3f3d0d

Browse files
fix: add missing Vulnerability comparator for sorting (#246)
Partial fix for #245. Signed-off-by: Rodney Richardson <[email protected]>
1 parent 48ea951 commit c3f3d0d

File tree

2 files changed

+44
-0
lines changed

2 files changed

+44
-0
lines changed

cyclonedx/model/vulnerability.py

+8
Original file line numberDiff line numberDiff line change
@@ -1062,6 +1062,14 @@ def __eq__(self, other: object) -> bool:
10621062
return hash(other) == hash(self)
10631063
return False
10641064

1065+
def __lt__(self, other: Any) -> bool:
1066+
if isinstance(other, Vulnerability):
1067+
return ComparableTuple(
1068+
(self.id, self.description, self.detail, self.source, self.created, self.published)) < \
1069+
ComparableTuple(
1070+
(other.id, other.description, other.detail, other.source, other.created, other.published))
1071+
return NotImplemented
1072+
10651073
def __hash__(self) -> int:
10661074
return hash((
10671075
self.id, self.source, tuple(self.references), tuple(self.ratings), tuple(self.cwes), self.description,

tests/test_model_vulnerability.py

+36
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
# Copyright (c) OWASP Foundation. All Rights Reserved.
1919

2020
import unittest
21+
from datetime import datetime, timedelta
2122
from decimal import Decimal
2223
from unittest import TestCase
2324
from unittest.mock import Mock, patch
@@ -206,6 +207,41 @@ def test_empty_vulnerability(self, mock_uuid: Mock) -> None:
206207
self.assertIsNone(v.analysis)
207208
self.assertFalse(v.affects)
208209

210+
def test_sort(self) -> None:
211+
source1 = VulnerabilitySource(name='a')
212+
source2 = VulnerabilitySource(name='b')
213+
datetime1 = datetime.utcnow()
214+
datetime2 = datetime1 + timedelta(seconds=5)
215+
216+
# expected sort order: (id, description, detail, source, created, published)
217+
expected_order = [0, 6, 1, 7, 2, 8, 3, 9, 4, 10, 5, 11]
218+
vulnerabilities = [
219+
Vulnerability(bom_ref='0', id='a', description='a', detail='a',
220+
source=source1, created=datetime1, published=datetime1),
221+
Vulnerability(bom_ref='1', id='a', description='a', detail='a',
222+
source=source1, created=datetime1),
223+
Vulnerability(bom_ref='2', id='a', description='a', detail='a',
224+
source=source1),
225+
Vulnerability(bom_ref='3', id='a', description='a', detail='a'),
226+
Vulnerability(bom_ref='4', id='a', description='a'),
227+
Vulnerability(bom_ref='5', id='a'),
228+
Vulnerability(bom_ref='6', id='a', description='a', detail='a',
229+
source=source1, created=datetime1, published=datetime2),
230+
Vulnerability(bom_ref='7', id='a', description='a', detail='a',
231+
source=source1, created=datetime2, published=datetime1),
232+
Vulnerability(bom_ref='8', id='a', description='a', detail='a',
233+
source=source2, created=datetime1, published=datetime1),
234+
Vulnerability(bom_ref='9', id='a', description='a', detail='b',
235+
source=source1, created=datetime1, published=datetime1),
236+
Vulnerability(bom_ref='10', id='a', description='b', detail='b',
237+
source=source1, created=datetime1, published=datetime1),
238+
Vulnerability(bom_ref='11', id='b', description='a', detail='a',
239+
source=source1, created=datetime1, published=datetime1),
240+
]
241+
sorted_vulnerabilities = sorted(vulnerabilities)
242+
expected_vulnerabilities = reorder(vulnerabilities, expected_order)
243+
self.assertListEqual(sorted_vulnerabilities, expected_vulnerabilities)
244+
209245

210246
class TestModelVulnerabilityAdvisory(TestCase):
211247

0 commit comments

Comments
 (0)