|
1 | 1 | import pytest |
2 | 2 | from pathlib import Path |
| 3 | +from unittest.mock import patch, MagicMock |
3 | 4 |
|
4 | | -from cpp_linter_hooks.clang_format import run_clang_format |
| 5 | +from cpp_linter_hooks.clang_format import run_clang_format, main |
5 | 6 |
|
6 | 7 |
|
7 | 8 | @pytest.mark.parametrize( |
@@ -64,3 +65,97 @@ def test_run_clang_format_dry_run(args, expected_retval, tmp_path): |
64 | 65 | test_file = tmp_path / "main.c" |
65 | 66 | ret, _ = run_clang_format(["--dry-run", str(test_file)]) |
66 | 67 | assert ret == -1 # Dry run should not fail |
| 68 | + |
| 69 | + |
| 70 | +def test_main_empty_output(): |
| 71 | + """Test main() function when clang-format returns error with empty output""" |
| 72 | + with patch( |
| 73 | + "cpp_linter_hooks.clang_format.run_clang_format" |
| 74 | + ) as mock_run_clang_format: |
| 75 | + # Mock failed run with empty output |
| 76 | + mock_run_clang_format.return_value = (1, "") |
| 77 | + |
| 78 | + with patch("builtins.print") as mock_print: |
| 79 | + result = main() |
| 80 | + |
| 81 | + # Should return 1 and print empty string |
| 82 | + assert result == 1 |
| 83 | + mock_print.assert_called_once_with("") |
| 84 | + |
| 85 | + |
| 86 | +def test_verbose_output(tmp_path, capsys): |
| 87 | + """Test that verbose mode produces debug output to stderr""" |
| 88 | + test_file = tmp_path / "test.c" |
| 89 | + test_file.write_text("#include <stdio.h>\nint main(){return 0;}") |
| 90 | + |
| 91 | + with patch("cpp_linter_hooks.clang_format.ensure_installed") as mock_ensure: |
| 92 | + mock_ensure.return_value = "/fake/clang-format" |
| 93 | + with patch("subprocess.run") as mock_run: |
| 94 | + mock_run.return_value = MagicMock(returncode=0, stdout="", stderr="") |
| 95 | + |
| 96 | + # Test verbose mode |
| 97 | + retval, output = run_clang_format( |
| 98 | + ["--verbose", "--style=Google", str(test_file)] |
| 99 | + ) |
| 100 | + |
| 101 | + # Check that debug messages were printed to stderr |
| 102 | + captured = capsys.readouterr() |
| 103 | + assert "[DEBUG] clang-format command:" in captured.err |
| 104 | + assert "[DEBUG] clang-format version:" in captured.err |
| 105 | + assert "[DEBUG] clang-format executable:" in captured.err |
| 106 | + assert "[DEBUG] Exit code:" in captured.err |
| 107 | + |
| 108 | + |
| 109 | +def test_verbose_with_error(tmp_path, capsys): |
| 110 | + """Test verbose output when there's an error""" |
| 111 | + test_file = tmp_path / "test.c" |
| 112 | + |
| 113 | + with patch("cpp_linter_hooks.clang_format.ensure_installed") as mock_ensure: |
| 114 | + mock_ensure.return_value = "/fake/clang-format" |
| 115 | + with patch("subprocess.run") as mock_run: |
| 116 | + mock_run.return_value = MagicMock( |
| 117 | + returncode=1, stdout="error output", stderr="error in stderr" |
| 118 | + ) |
| 119 | + |
| 120 | + # Test verbose mode with error |
| 121 | + retval, output = run_clang_format( |
| 122 | + ["--verbose", "--style=Google", str(test_file)] |
| 123 | + ) |
| 124 | + |
| 125 | + # Check return values |
| 126 | + assert retval == 1 |
| 127 | + assert "error output" in output |
| 128 | + assert "error in stderr" in output |
| 129 | + |
| 130 | + # Check debug output |
| 131 | + captured = capsys.readouterr() |
| 132 | + assert "[DEBUG] Exit code: 1" in captured.err |
| 133 | + assert "[DEBUG] stdout:" in captured.err |
| 134 | + assert "[DEBUG] stderr:" in captured.err |
| 135 | + |
| 136 | + |
| 137 | +def test_verbose_dry_run(tmp_path, capsys): |
| 138 | + """Test verbose output in dry-run mode""" |
| 139 | + test_file = tmp_path / "test.c" |
| 140 | + test_file.write_text("#include <stdio.h>\nint main(){return 0;}") |
| 141 | + |
| 142 | + with patch("cpp_linter_hooks.clang_format.ensure_installed") as mock_ensure: |
| 143 | + mock_ensure.return_value = "/fake/clang-format" |
| 144 | + with patch("subprocess.run") as mock_run: |
| 145 | + mock_run.return_value = MagicMock( |
| 146 | + returncode=0, stdout="dry run output", stderr="" |
| 147 | + ) |
| 148 | + |
| 149 | + # Test verbose dry-run mode |
| 150 | + retval, output = run_clang_format( |
| 151 | + ["--verbose", "--dry-run", str(test_file)] |
| 152 | + ) |
| 153 | + |
| 154 | + # Check return values (dry-run should return -1) |
| 155 | + assert retval == -1 |
| 156 | + assert "dry run output" in output |
| 157 | + |
| 158 | + # Check debug output |
| 159 | + captured = capsys.readouterr() |
| 160 | + assert "[DEBUG] Dry-run mode detected" in captured.err |
| 161 | + assert "[DEBUG] Exit code: 0 (converted to -1 for dry-run)" in captured.err |
0 commit comments