"""Tests for tools/security/check_results.py.""" from __future__ import annotations import json import sys from pathlib import Path import pytest # Add tools/security to path so we can import check_results sys.path.insert(0, str(Path(__file__).resolve().parents[2] / "tools" / "security")) import check_results class TestCheckBandit: def test_missing_file(self, tmp_path: Path) -> None: result = check_results.check_bandit(tmp_path / "nonexistent.json") assert result == [] def test_empty_results(self, tmp_path: Path) -> None: f = tmp_path / "bandit.json" f.write_text(json.dumps({"results": []})) assert check_results.check_bandit(f) == [] def test_low_severity_ignored(self, tmp_path: Path) -> None: f = tmp_path / "bandit.json" f.write_text(json.dumps({"results": [ {"issue_severity": "LOW", "issue_confidence": "HIGH", "issue_text": "test", "filename": "x.py", "line_number": 1} ]})) assert check_results.check_bandit(f) == [] def test_high_severity_high_confidence(self, tmp_path: Path) -> None: finding = {"issue_severity": "HIGH", "issue_confidence": "HIGH", "issue_text": "shell=True", "filename": "x.py", "line_number": 5} f = tmp_path / "bandit.json" f.write_text(json.dumps({"results": [finding]})) result = check_results.check_bandit(f) assert len(result) == 1 assert result[0]["issue_text"] == "shell=True" def test_high_severity_low_confidence_ignored(self, tmp_path: Path) -> None: f = tmp_path / "bandit.json" f.write_text(json.dumps({"results": [ {"issue_severity": "HIGH", "issue_confidence": "LOW", "issue_text": "test", "filename": "x.py", "line_number": 1} ]})) assert check_results.check_bandit(f) == [] def test_critical_severity(self, tmp_path: Path) -> None: f = tmp_path / "bandit.json" f.write_text(json.dumps({"results": [ {"issue_severity": "CRITICAL", "issue_confidence": "MEDIUM", "issue_text": "eval", "filename": "y.py", "line_number": 10} ]})) result = check_results.check_bandit(f) assert len(result) == 1 class TestCheckSemgrep: def test_missing_file(self, tmp_path: Path) -> None: assert check_results.check_semgrep(tmp_path / "nope.json") == [] def test_empty_results(self, tmp_path: Path) -> None: f = tmp_path / "semgrep.json" f.write_text(json.dumps({"results": []})) assert check_results.check_semgrep(f) == [] def test_warning_ignored(self, tmp_path: Path) -> None: f = tmp_path / "semgrep.json" f.write_text(json.dumps({"results": [ {"check_id": "test", "path": "x.py", "start": {"line": 1}, "extra": {"severity": "WARNING"}} ]})) assert check_results.check_semgrep(f) == [] def test_error_captured(self, tmp_path: Path) -> None: f = tmp_path / "semgrep.json" f.write_text(json.dumps({"results": [ {"check_id": "no-eval", "path": "x.py", "start": {"line": 3}, "extra": {"severity": "ERROR", "message": "no eval"}} ]})) result = check_results.check_semgrep(f) assert len(result) == 1 class TestCheckPipAudit: def test_missing_file(self, tmp_path: Path) -> None: assert check_results.check_pip_audit(tmp_path / "nope.json") == [] def test_no_vulns(self, tmp_path: Path) -> None: f = tmp_path / "audit.json" f.write_text(json.dumps({"dependencies": [ {"name": "cryptography", "version": "42.0", "vulns": []} ]})) assert check_results.check_pip_audit(f) == [] def test_vuln_found(self, tmp_path: Path) -> None: f = tmp_path / "audit.json" f.write_text(json.dumps({"dependencies": [ {"name": "requests", "version": "2.28.0", "vulns": [ {"id": "CVE-2023-1234", "description": "bad thing"} ]} ]})) result = check_results.check_pip_audit(f) assert len(result) == 1 assert result[0]["name"] == "requests" def test_build_tools_excluded(self, tmp_path: Path) -> None: f = tmp_path / "audit.json" f.write_text(json.dumps({"dependencies": [ {"name": "pip", "version": "24.0", "vulns": [ {"id": "CVE-2025-8869", "description": "tar issue"} ]}, {"name": "setuptools", "version": "69.0", "vulns": [ {"id": "CVE-2024-5678", "description": "another issue"} ]}, {"name": "wheel", "version": "0.45", "vulns": [ {"id": "CVE-2026-2049", "description": "path traversal"} ]}, ]})) assert check_results.check_pip_audit(f) == [] class TestMain: def test_all_clean(self, tmp_path: Path) -> None: bandit_f = tmp_path / "bandit.json" bandit_f.write_text(json.dumps({"results": []})) audit_f = tmp_path / "audit.json" audit_f.write_text(json.dumps({"dependencies": []})) sys.argv = ["check_results.py", "--bandit", str(bandit_f), "--pip-audit", str(audit_f)] assert check_results.main() == 0 def test_failure_on_high(self, tmp_path: Path) -> None: bandit_f = tmp_path / "bandit.json" bandit_f.write_text(json.dumps({"results": [ {"issue_severity": "HIGH", "issue_confidence": "HIGH", "issue_text": "bad", "filename": "x.py", "line_number": 1} ]})) sys.argv = ["check_results.py", "--bandit", str(bandit_f)] assert check_results.main() == 1