|
1 | | -import logging |
2 | 1 | import pytest |
3 | | -from itertools import product |
4 | 2 | from unittest.mock import patch |
5 | 3 | from pathlib import Path |
6 | 4 | import subprocess |
7 | 5 | import sys |
8 | 6 |
|
9 | 7 | from cpp_linter_hooks.util import ( |
10 | | - ensure_installed, |
11 | | - is_installed, |
12 | 8 | get_version_from_dependency, |
13 | 9 | _resolve_version, |
14 | | - _get_runtime_version, |
15 | 10 | _install_tool, |
16 | 11 | _resolve_install, |
17 | 12 | CLANG_FORMAT_VERSIONS, |
|
25 | 20 | TOOLS = ["clang-format", "clang-tidy"] |
26 | 21 |
|
27 | 22 |
|
28 | | -@pytest.mark.benchmark |
29 | | -@pytest.mark.parametrize(("tool", "version"), list(product(TOOLS, VERSIONS))) |
30 | | -def test_ensure_installed(tool, version, tmp_path, monkeypatch, caplog): |
31 | | - """Test that ensure_installed returns the tool name for wheel packages.""" |
32 | | - with monkeypatch.context(): |
33 | | - # Mock shutil.which to simulate the tool being available |
34 | | - with patch("shutil.which", return_value=str(tmp_path / tool)): |
35 | | - # Mock _get_runtime_version to return a matching version |
36 | | - mock_version = "20.1.7" if tool == "clang-format" else "20.1.0" |
37 | | - with patch( |
38 | | - "cpp_linter_hooks.util._get_runtime_version", return_value=mock_version |
39 | | - ): |
40 | | - caplog.clear() |
41 | | - caplog.set_level(logging.INFO, logger="cpp_linter_hooks.util") |
42 | | - |
43 | | - if version is None: |
44 | | - result = ensure_installed(tool) |
45 | | - else: |
46 | | - result = ensure_installed(tool, version=version) |
47 | | - |
48 | | - # Should return the tool name for direct execution |
49 | | - assert result == tool |
50 | | - |
51 | | - # Check that we logged ensuring the tool is installed |
52 | | - assert any("Ensuring" in record.message for record in caplog.records) |
53 | | - |
54 | | - |
55 | | -@pytest.mark.benchmark |
56 | | -def test_is_installed_with_shutil_which(tmp_path): |
57 | | - """Test is_installed when tool is found via shutil.which.""" |
58 | | - tool_path = tmp_path / "clang-format" |
59 | | - tool_path.touch() |
60 | | - |
61 | | - with patch("shutil.which", return_value=str(tool_path)): |
62 | | - result = is_installed("clang-format") |
63 | | - assert result == tool_path |
64 | | - |
65 | | - |
66 | | -@pytest.mark.benchmark |
67 | | -def test_is_installed_not_found(): |
68 | | - """Test is_installed when tool is not found anywhere.""" |
69 | | - with ( |
70 | | - patch("shutil.which", return_value=None), |
71 | | - patch("sys.executable", "/nonexistent/python"), |
72 | | - ): |
73 | | - result = is_installed("clang-format") |
74 | | - assert result is None |
75 | | - |
76 | | - |
77 | | -@pytest.mark.benchmark |
78 | | -def test_ensure_installed_tool_not_found(caplog): |
79 | | - """Test ensure_installed when tool is not found.""" |
80 | | - with ( |
81 | | - patch("shutil.which", return_value=None), |
82 | | - patch("cpp_linter_hooks.util._install_tool", return_value=None), |
83 | | - ): |
84 | | - caplog.clear() |
85 | | - caplog.set_level(logging.WARNING, logger="cpp_linter_hooks.util") |
86 | | - |
87 | | - result = ensure_installed("clang-format") |
88 | | - |
89 | | - # Should still return the tool name |
90 | | - assert result == "clang-format" |
91 | | - |
92 | | - # Should log a warning |
93 | | - assert any( |
94 | | - "not found and could not be installed" in record.message |
95 | | - for record in caplog.records |
96 | | - ) |
97 | | - |
98 | | - |
99 | 23 | # Tests for get_version_from_dependency |
100 | 24 | @pytest.mark.benchmark |
101 | 25 | def test_get_version_from_dependency_success(): |
102 | 26 | """Test get_version_from_dependency with valid pyproject.toml.""" |
103 | 27 | mock_toml_content = { |
104 | 28 | "project": { |
105 | | - "optional-dependencies": { |
106 | | - "tools": [ |
| 29 | + "build-system": { |
| 30 | + "requires": [ |
107 | 31 | "clang-format==20.1.7", |
108 | 32 | "clang-tidy==20.1.0", |
109 | 33 | "other-package==1.0.0", |
@@ -135,7 +59,7 @@ def test_get_version_from_dependency_missing_file(): |
135 | 59 | def test_get_version_from_dependency_missing_dependency(): |
136 | 60 | """Test get_version_from_dependency with missing dependency.""" |
137 | 61 | mock_toml_content = { |
138 | | - "project": {"optional-dependencies": {"tools": ["other-package==1.0.0"]}} |
| 62 | + "project": {"build-system": {"requires": ["other-package==1.0.0"]}} |
139 | 63 | } |
140 | 64 |
|
141 | 65 | with ( |
@@ -198,48 +122,6 @@ def test_resolve_version_clang_tidy(user_input, expected): |
198 | 122 | assert result == expected |
199 | 123 |
|
200 | 124 |
|
201 | | -# Tests for _get_runtime_version |
202 | | -@pytest.mark.benchmark |
203 | | -def test_get_runtime_version_clang_format(): |
204 | | - """Test _get_runtime_version for clang-format.""" |
205 | | - mock_output = "Ubuntu clang-format version 20.1.7-1ubuntu1\n" |
206 | | - |
207 | | - with patch("subprocess.check_output", return_value=mock_output): |
208 | | - result = _get_runtime_version("clang-format") |
209 | | - assert result == "20.1.7-1ubuntu1" |
210 | | - |
211 | | - |
212 | | -@pytest.mark.benchmark |
213 | | -def test_get_runtime_version_clang_tidy(): |
214 | | - """Test _get_runtime_version for clang-tidy.""" |
215 | | - mock_output = "LLVM (http://llvm.org/):\n LLVM version 20.1.0\n" |
216 | | - |
217 | | - with patch("subprocess.check_output", return_value=mock_output): |
218 | | - result = _get_runtime_version("clang-tidy") |
219 | | - assert result == "20.1.0" |
220 | | - |
221 | | - |
222 | | -@pytest.mark.benchmark |
223 | | -def test_get_runtime_version_exception(): |
224 | | - """Test _get_runtime_version when subprocess fails.""" |
225 | | - with patch( |
226 | | - "subprocess.check_output", |
227 | | - side_effect=subprocess.CalledProcessError(1, ["clang-format"]), |
228 | | - ): |
229 | | - result = _get_runtime_version("clang-format") |
230 | | - assert result is None |
231 | | - |
232 | | - |
233 | | -@pytest.mark.benchmark |
234 | | -def test_get_runtime_version_clang_tidy_single_line(): |
235 | | - """Test _get_runtime_version for clang-tidy with single line output.""" |
236 | | - mock_output = "LLVM version 20.1.0\n" |
237 | | - |
238 | | - with patch("subprocess.check_output", return_value=mock_output): |
239 | | - result = _get_runtime_version("clang-tidy") |
240 | | - assert result is None # Should return None for single line |
241 | | - |
242 | | - |
243 | 125 | # Tests for _install_tool |
244 | 126 | @pytest.mark.benchmark |
245 | 127 | def test_install_tool_success(): |
@@ -376,40 +258,6 @@ def test_resolve_install_invalid_version(): |
376 | 258 | ) |
377 | 259 |
|
378 | 260 |
|
379 | | -# Tests for ensure_installed edge cases |
380 | | -@pytest.mark.benchmark |
381 | | -def test_ensure_installed_version_mismatch(caplog): |
382 | | - """Test ensure_installed with version mismatch scenario.""" |
383 | | - mock_path = "/usr/bin/clang-format" |
384 | | - |
385 | | - with ( |
386 | | - patch("shutil.which", return_value=mock_path), |
387 | | - patch("cpp_linter_hooks.util._get_runtime_version", return_value="18.1.8"), |
388 | | - patch("cpp_linter_hooks.util._install_tool", return_value=Path(mock_path)), |
389 | | - ): |
390 | | - caplog.clear() |
391 | | - caplog.set_level(logging.INFO, logger="cpp_linter_hooks.util") |
392 | | - |
393 | | - result = ensure_installed("clang-format", "20.1.7") |
394 | | - assert result == "clang-format" |
395 | | - |
396 | | - # Should log version mismatch |
397 | | - assert any("version mismatch" in record.message for record in caplog.records) |
398 | | - |
399 | | - |
400 | | -@pytest.mark.benchmark |
401 | | -def test_ensure_installed_no_runtime_version(): |
402 | | - """Test ensure_installed when runtime version cannot be determined.""" |
403 | | - mock_path = "/usr/bin/clang-format" |
404 | | - |
405 | | - with ( |
406 | | - patch("shutil.which", return_value=mock_path), |
407 | | - patch("cpp_linter_hooks.util._get_runtime_version", return_value=None), |
408 | | - ): |
409 | | - result = ensure_installed("clang-format", "20.1.7") |
410 | | - assert result == "clang-format" |
411 | | - |
412 | | - |
413 | 261 | # Tests for constants and defaults |
414 | 262 | @pytest.mark.benchmark |
415 | 263 | def test_default_versions(): |
|
0 commit comments