tests/test_cli.py
| 1 | """CLI tests using click's CliRunner.""" |
| 2 | |
| 3 | from __future__ import annotations |
| 4 | |
| 5 | import json |
| 6 | |
| 7 | from click.testing import CliRunner |
| 8 | |
| 9 | from pqc_lint.cli import main |
| 10 | |
| 11 | |
| 12 | def _write(path, content): |
| 13 | path.parent.mkdir(parents=True, exist_ok=True) |
| 14 | path.write_text(content, encoding="utf-8") |
| 15 | |
| 16 | |
| 17 | def test_rules_command_lists_rules(): |
| 18 | runner = CliRunner() |
| 19 | result = runner.invoke(main, ["rules"]) |
| 20 | assert result.exit_code == 0 |
| 21 | assert "PQC001" in result.output |
| 22 | assert "PQC301" in result.output |
| 23 | |
| 24 | |
| 25 | def test_scan_clean_dir_exits_zero(tmp_path): |
| 26 | _write(tmp_path / "clean.py", "def add(a, b):\n return a + b\n") |
| 27 | runner = CliRunner() |
| 28 | result = runner.invoke(main, ["scan", str(tmp_path)]) |
| 29 | assert result.exit_code == 0 |
| 30 | |
| 31 | |
| 32 | def test_scan_finds_rsa_exits_one_with_fail_on_high(tmp_path): |
| 33 | _write(tmp_path / "bad.py", ( |
| 34 | "from cryptography.hazmat.primitives.asymmetric import rsa\n" |
| 35 | "k = rsa.generate_private_key(public_exponent=65537, key_size=2048)\n" |
| 36 | )) |
| 37 | runner = CliRunner() |
| 38 | result = runner.invoke(main, ["scan", str(tmp_path), "--fail-on", "high"]) |
| 39 | assert result.exit_code == 1 |
| 40 | |
| 41 | |
| 42 | def test_scan_finds_medium_exits_zero_with_fail_on_critical(tmp_path): |
| 43 | # MD5 is medium severity. --fail-on critical should NOT fail. |
| 44 | _write(tmp_path / "h.py", "import hashlib\nhashlib.md5(b'x')\n") |
| 45 | runner = CliRunner() |
| 46 | result = runner.invoke(main, ["scan", str(tmp_path), "--fail-on", "critical"]) |
| 47 | assert result.exit_code == 0 |
| 48 | |
| 49 | |
| 50 | def test_scan_json_output(tmp_path): |
| 51 | _write(tmp_path / "bad.py", ( |
| 52 | "from cryptography.hazmat.primitives.asymmetric import rsa\n" |
| 53 | "k = rsa.generate_private_key(65537, 2048)\n" |
| 54 | )) |
| 55 | runner = CliRunner() |
| 56 | result = runner.invoke(main, ["scan", str(tmp_path), "--format", "json", "--fail-on", "info"]) |
| 57 | # parse stdout as JSON |
| 58 | data = json.loads(result.output) |
| 59 | assert data["schema_version"] == "1.0" |
| 60 | assert len(data["findings"]) > 0 |
| 61 | |
| 62 | |
| 63 | def test_scan_sarif_output(tmp_path): |
| 64 | _write(tmp_path / "bad.py", ( |
| 65 | "from cryptography.hazmat.primitives.asymmetric import rsa\n" |
| 66 | "k = rsa.generate_private_key(65537, 2048)\n" |
| 67 | )) |
| 68 | runner = CliRunner() |
| 69 | result = runner.invoke(main, ["scan", str(tmp_path), "--format", "sarif", "--fail-on", "info"]) |
| 70 | data = json.loads(result.output) |
| 71 | assert "$schema" in data |
| 72 | assert data["version"] == "2.1.0" |
| 73 | |