From ae7d1873f227177b895c475fad4a5d387538e7e8 Mon Sep 17 00:00:00 2001 From: J08nY Date: Sun, 26 Dec 2021 17:14:56 +0100 Subject: Add slots to CVE and CPE objects. Fixes #109. Also adds a test loading the CVE database from the web. --- tests/test_cve.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 tests/test_cve.py (limited to 'tests/test_cve.py') diff --git a/tests/test_cve.py b/tests/test_cve.py new file mode 100644 index 00000000..3bf9c4bb --- /dev/null +++ b/tests/test_cve.py @@ -0,0 +1,14 @@ +from unittest import TestCase + +import pytest + +from sec_certs.dataset.cve import CVEDataset + + +class TestCVE(TestCase): + @pytest.mark.slow + def test_from_web(self): + dset = CVEDataset.from_web() + assert dset is not None + assert "CVE-2019-15809" in dset.cves + assert "CVE-2017-15361" in dset.cves -- cgit v1.3.1 From 62847616bd4d13c3d2e60e0b5c9ce67bd787d8e2 Mon Sep 17 00:00:00 2001 From: J08nY Date: Sun, 26 Dec 2021 17:52:05 +0100 Subject: Add pytest-monitor and pytest-profiling to dev deps. --- .gitignore | 2 ++ dev_requirements.txt | 4 ++++ tests/test_cve.py | 5 ++--- 3 files changed, 8 insertions(+), 3 deletions(-) (limited to 'tests/test_cve.py') diff --git a/.gitignore b/.gitignore index f6054f09..3176de71 100644 --- a/.gitignore +++ b/.gitignore @@ -54,6 +54,8 @@ coverage.xml *.cover .hypothesis/ .pytest_cache/ +prof/ +.pymon # Translations *.mo diff --git a/dev_requirements.txt b/dev_requirements.txt index edb5f93a..f2cceafd 100644 --- a/dev_requirements.txt +++ b/dev_requirements.txt @@ -2,6 +2,10 @@ mypy types-PyYAML types-python-dateutil types-requests +pytest==6.2.5 +pytest-cov==3.0.0 +pytest-monitor==1.6.3 +pytest-profiling==1.7.0 black isort==5.10.1 flake8==4.0.1 diff --git a/tests/test_cve.py b/tests/test_cve.py index 3bf9c4bb..6c84ace3 100644 --- a/tests/test_cve.py +++ b/tests/test_cve.py @@ -1,12 +1,11 @@ -from unittest import TestCase - import pytest from sec_certs.dataset.cve import CVEDataset -class TestCVE(TestCase): +class TestCVE: @pytest.mark.slow + @pytest.mark.monitor_test def test_from_web(self): dset = CVEDataset.from_web() assert dset is not None -- cgit v1.3.1 From 35b77a2f1cd891d18c5984068c2f45fdcc1656ce Mon Sep 17 00:00:00 2001 From: J08nY Date: Mon, 3 Jan 2022 20:19:04 +0100 Subject: Fix broken serialization of CVE and CPE objects. --- sec_certs/sample/cve.py | 8 ++++++++ sec_certs/serialization/json.py | 6 ++++++ tests/test_cpe.py | 14 ++++++++++++++ tests/test_cve.py | 27 +++++++++++++++++++++++++++ 4 files changed, 55 insertions(+) (limited to 'tests/test_cve.py') diff --git a/sec_certs/sample/cve.py b/sec_certs/sample/cve.py index 080a4e51..e6332785 100644 --- a/sec_certs/sample/cve.py +++ b/sec_certs/sample/cve.py @@ -97,6 +97,14 @@ class CVE(PandasSerializableType, ComplexSerializableType): self.published_date, ) + def to_dict(self): + return { + "cve_id": self.cve_id, + "impact": self.impact, + "vulnerable_cpes": self.vulnerable_cpes, + "published_date": self.published_date.isoformat(), + } + @classmethod def from_nist_dict(cls, dct: Dict) -> "CVE": """ diff --git a/sec_certs/serialization/json.py b/sec_certs/serialization/json.py index 8c229f65..c64c2fc8 100644 --- a/sec_certs/serialization/json.py +++ b/sec_certs/serialization/json.py @@ -10,9 +10,15 @@ class ComplexSerializableType: # to achieve without using metaclasses. Not to complicate the code, we choose instance variable. @property def serialized_attributes(self) -> List[str]: + if hasattr(self, "__slots__") and self.__slots__: + return list(self.__slots__) return list(self.__dict__.keys()) def to_dict(self): + if hasattr(self, "__slots__") and self.__slots__: + return { + key: copy.deepcopy(getattr(self, key)) for key in self.__slots__ if key in self.serialized_attributes + } return {key: val for key, val in copy.deepcopy(self.__dict__).items() if key in self.serialized_attributes} @classmethod diff --git a/tests/test_cpe.py b/tests/test_cpe.py index e2f1fdb9..aebde5e8 100644 --- a/tests/test_cpe.py +++ b/tests/test_cpe.py @@ -4,6 +4,7 @@ from tempfile import TemporaryDirectory import pytest from sec_certs.dataset.cpe import CPEDataset +from sec_certs.sample.cpe import CPE class TestCPE: @@ -14,3 +15,16 @@ class TestCPE: dset = CPEDataset.from_web(Path(tmpdir) / "cpe.json") assert dset is not None assert "cpe:2.3:o:infineon:trusted_platform_firmware:6.40:*:*:*:*:*:*:*" in dset.cpes + + def test_from_to_dict(self): + data = { + "uri": "cpe:2.3:o:freebsd:freebsd:1.0:*:*:*:*:*:*:*", + "title": None, + "start_version": None, + "end_version": None, + } + cpe = CPE.from_dict(data) + ret = cpe.to_dict() + assert data == ret + other_cpe = CPE.from_dict(ret) + assert cpe == other_cpe diff --git a/tests/test_cve.py b/tests/test_cve.py index 6c84ace3..f64d6754 100644 --- a/tests/test_cve.py +++ b/tests/test_cve.py @@ -1,6 +1,7 @@ import pytest from sec_certs.dataset.cve import CVEDataset +from sec_certs.sample.cve import CVE class TestCVE: @@ -11,3 +12,29 @@ class TestCVE: assert dset is not None assert "CVE-2019-15809" in dset.cves assert "CVE-2017-15361" in dset.cves + + def test_from_to_dict(self): + data = { + "cve_id": "CVE-1999-0001", + "vulnerable_cpes": [ + { + "uri": "cpe:2.3:o:freebsd:freebsd:1.0:*:*:*:*:*:*:*", + "title": None, + "start_version": None, + "end_version": None, + } + ], + "impact": { + "_type": "Impact", + "base_score": 5, + "severity": "MEDIUM", + "explotability_score": 10, + "impact_score": 2.9, + }, + "published_date": "1999-12-30T05:00:00+00:00", + } + cve = CVE.from_dict(data) + ret = cve.to_dict() + assert ret == data + other_cve = CVE.from_dict(ret) + assert cve == other_cve -- cgit v1.3.1