diff --git a/tests/unit/test_analyzers.py b/tests/unit/test_analyzers.py new file mode 100644 index 0000000..c746203 --- /dev/null +++ b/tests/unit/test_analyzers.py @@ -0,0 +1,170 @@ +"""Tests for CVE and version analyzers.""" + +import pytest + +from depcheck.analyzers.cve import CVEAnalyzer, load_cve_database +from depcheck.analyzers.version import VersionAnalyzer +from depcheck.models import Dependency, PackageManager, Severity, Vulnerability + + +class TestCVEAnalyzer: + """Tests for CVE analyzer.""" + + def setup_method(self): + """Set up test fixtures.""" + self.db = { + "cves": [ + { + "package": "lodash", + "cve_id": "CVE-2021-23337", + "severity": "high", + "description": "Command Injection", + "affected_versions": "<4.17.21", + "fixed_version": "4.17.21", + }, + { + "package": "requests", + "cve_id": "CVE-2024-35195", + "severity": "medium", + "description": "Auth bypass", + "affected_versions": "<2.32.0", + "fixed_version": "2.32.0", + }, + ], + "version_warnings": [ + { + "package": "moment", + "message": "Consider migrating", + "min_safe": "2.29.4", + } + ], + } + self.analyzer = CVEAnalyzer(self.db) + + def test_detects_vulnerable_version(self): + """Test that vulnerable versions are detected.""" + dep = Dependency( + name="lodash", + current_version="4.17.20", + package_manager=PackageManager.NPM, + ) + + vulns = self.analyzer.analyze(dep) + + assert len(vulns) == 1 + assert vulns[0].cve_id == "CVE-2021-23337" + assert vulns[0].severity == Severity.HIGH + + def test_detects_safe_version(self): + """Test that safe versions are not flagged.""" + dep = Dependency( + name="lodash", + current_version="4.17.21", + package_manager=PackageManager.NPM, + ) + + vulns = self.analyzer.analyze(dep) + + assert len(vulns) == 0 + + def test_unknown_package_returns_empty(self): + """Test that unknown packages return no vulnerabilities.""" + dep = Dependency( + name="unknown-package", + current_version="1.0.0", + package_manager=PackageManager.NPM, + ) + + vulns = self.analyzer.analyze(dep) + + assert len(vulns) == 0 + + def test_load_bundled_database(self): + """Test loading bundled CVE database.""" + db = load_cve_database() + assert "cves" in db + assert "version_warnings" in db + + def test_version_warning(self): + """Test version warning check.""" + dep = Dependency( + name="moment", + current_version="2.29.3", + package_manager=PackageManager.NPM, + ) + + warning = self.analyzer.check_version_warning(dep) + + assert warning is not None + assert "migrating" in warning.lower() + + def test_safe_version_no_warning(self): + """Test that safe versions don't trigger warnings.""" + dep = Dependency( + name="moment", + current_version="2.29.4", + package_manager=PackageManager.NPM, + ) + + warning = self.analyzer.check_version_warning(dep) + + assert warning is None + + +class TestVersionAnalyzer: + """Tests for version analyzer.""" + + def setup_method(self): + """Set up test fixtures.""" + self.analyzer = VersionAnalyzer() + + def test_update_type_major(self): + """Test major version bump detection.""" + result = self.analyzer.get_update_type("1.0.0", "2.0.0") + assert result == "major" + + def test_update_type_minor(self): + """Test minor version bump detection.""" + result = self.analyzer.get_update_type("1.0.0", "1.1.0") + assert result == "minor" + + def test_update_type_patch(self): + """Test patch version bump detection.""" + result = self.analyzer.get_update_type("1.0.0", "1.0.1") + assert result == "patch" + + def test_compare_versions_greater(self): + """Test version comparison - v1 > v2.""" + result = self.analyzer.compare_versions("2.0.0", "1.0.0") + assert result == 1 + + def test_compare_versions_less(self): + """Test version comparison - v1 < v2.""" + result = self.analyzer.compare_versions("1.0.0", "2.0.0") + assert result == -1 + + def test_compare_versions_equal(self): + """Test version comparison - equal.""" + result = self.analyzer.compare_versions("1.0.0", "1.0.0") + assert result == 0 + + def test_suggest_safe_upgrade_major(self): + """Test major upgrade suggestion.""" + result = self.analyzer.suggest_safe_upgrade("1.0.0", "major") + assert result == "2.0.0" + + def test_suggest_safe_upgrade_minor(self): + """Test minor upgrade suggestion.""" + result = self.analyzer.suggest_safe_upgrade("1.0.0", "minor") + assert result == "1.1.0" + + def test_suggest_safe_upgrade_patch(self): + """Test patch upgrade suggestion.""" + result = self.analyzer.suggest_safe_upgrade("1.0.0", "patch") + assert result == "1.0.1" + + def test_severity_for_update(self): + """Test mapping update type to severity.""" + assert self.analyzer.get_severity_for_update("major") == Severity.HIGH + assert self.analyzer.get_severity_for_update("minor") == Severity.MEDIUM + assert self.analyzer.get_severity_for_update("patch") == Severity.LOW