|
3 | 3 | from __future__ import annotations |
4 | 4 |
|
5 | 5 | import os |
6 | | -import shutil |
7 | 6 | import subprocess |
8 | 7 | import sys |
9 | 8 | from pathlib import Path |
|
15 | 14 | from tests.unit.scripts.fensu_policy._test_types import ( |
16 | 15 | ConversionFieldLinesTestCase, |
17 | 16 | ConversionFieldRuleTestCase, |
| 17 | + MixedCheckTestCase, |
18 | 18 | ) |
| 19 | +from tests.unit.scripts.fensu_policy.helpers import run_fensu_check, write_semantics_crate |
19 | 20 |
|
20 | | -REPOSITORY: Path = Path(__file__).resolve().parents[4] |
21 | | -WORKSPACE_MANIFEST: str = '[workspace]\nmembers = ["crates/sqlquack-semantics"]\nresolver = "2"\n' |
22 | | -CRATE_MANIFEST: str = ( |
23 | | - '[package]\nname = "sqlquack-semantics"\nversion = "0.1.0"\nedition = "2021"\n\n' |
24 | | - "[features]\ndefault = []\nsnowflake = []\n" |
25 | | -) |
26 | | -LIB: str = '#[cfg(feature = "snowflake")]\nmod snowflake;\nmod schemas;\n' |
27 | 21 | FIELD_RULE_CONFIG: str = ( |
28 | 22 | '[targets.rust]\nanalyzer = "rust"\nroots = ["crates"]\ntests = []\n' |
29 | 23 | 'rule_modules = ["scripts.fensu_policy.rules.conversion_fields"]\nselect = ["XSQ009"]\n' |
30 | 24 | ) |
| 25 | +# A Python target with a custom rule beside the Rust one, as the repository's own fensu.toml has. |
| 26 | +MIXED_CONFIG: str = ( |
| 27 | + '[targets.python]\nanalyzer = "python"\nroots = ["tooling"]\ntests = []\n' |
| 28 | + 'rule_modules = ["scripts.fensu_policy.rules.script_names"]\nselect = ["XSQ005"]\n\n' |
| 29 | + + FIELD_RULE_CONFIG |
| 30 | +) |
31 | 31 |
|
32 | 32 |
|
33 | 33 | @pytest.mark.parametrize( |
@@ -125,31 +125,46 @@ def test_given_source_when_checking_then_lists_conversion_field_reads( |
125 | 125 | def test_given_crate_when_running_fensu_then_reports_shared_conversion_field_reads( |
126 | 126 | test_case: ConversionFieldRuleTestCase, tmp_path: Path |
127 | 127 | ) -> None: |
128 | | - crate: Path = tmp_path / "crates" / "sqlquack-semantics" |
129 | | - for folder in ("snowflake", "schemas"): |
130 | | - (crate / "src" / folder).mkdir(parents=True) |
131 | | - (crate / "src" / folder / "mod.rs").write_text("pub fn column() {}\n") |
132 | | - (tmp_path / "Cargo.toml").write_text(WORKSPACE_MANIFEST) |
133 | | - (crate / "Cargo.toml").write_text(CRATE_MANIFEST) |
134 | | - (crate / "src" / "lib.rs").write_text(LIB) |
135 | | - (crate / test_case.path).write_text(test_case.source) |
136 | | - (tmp_path / "fensu.toml").write_text(FIELD_RULE_CONFIG) |
137 | | - shutil.copytree( |
138 | | - REPOSITORY / "scripts" / "fensu_policy", |
139 | | - tmp_path / "scripts" / "fensu_policy", |
140 | | - ignore=shutil.ignore_patterns("__pycache__"), |
141 | | - ) |
142 | | - (tmp_path / "scripts" / "__init__.py").write_text("") |
143 | | - |
144 | | - completed: subprocess.CompletedProcess[str] = subprocess.run( |
145 | | - [str(Path(sys.executable).with_name("fensu")), "check", "--no-cache"], |
146 | | - cwd=tmp_path, |
147 | | - env={**os.environ, "PYTHONPATH": str(tmp_path)}, |
148 | | - capture_output=True, |
149 | | - text=True, |
150 | | - check=False, |
151 | | - ) |
| 128 | + write_semantics_crate(tmp_path, FIELD_RULE_CONFIG) |
| 129 | + (tmp_path / "crates" / "sqlquack-semantics" / test_case.path).write_text(test_case.source) |
| 130 | + |
| 131 | + completed: subprocess.CompletedProcess[str] = run_fensu_check(tmp_path, os.environ["PATH"]) |
152 | 132 |
|
153 | 133 | output: str = completed.stdout + completed.stderr |
154 | 134 | assert completed.returncode == min(test_case.expected_fault_count, 1), output |
155 | 135 | assert output.count("XSQ009") == test_case.expected_fault_count, output |
| 136 | + |
| 137 | + |
| 138 | +@pytest.mark.parametrize( |
| 139 | + "test_case", |
| 140 | + [ |
| 141 | + MixedCheckTestCase( |
| 142 | + "with cargo, the check is complete", |
| 143 | + os.environ["PATH"], |
| 144 | + 0, |
| 145 | + "Found 0 faults", |
| 146 | + "Check incomplete", |
| 147 | + ), |
| 148 | + MixedCheckTestCase( |
| 149 | + "without cargo, the check says it is incomplete", |
| 150 | + str(Path(sys.executable).parent), |
| 151 | + 2, |
| 152 | + "Check incomplete", |
| 153 | + "Found ", |
| 154 | + ), |
| 155 | + ], |
| 156 | + ids=lambda case: case.description, |
| 157 | +) |
| 158 | +def test_given_python_and_rust_targets_when_running_fensu_then_summary_says_whether_all_ran( |
| 159 | + test_case: MixedCheckTestCase, tmp_path: Path |
| 160 | +) -> None: |
| 161 | + write_semantics_crate(tmp_path, MIXED_CONFIG) |
| 162 | + (tmp_path / "tooling").mkdir() |
| 163 | + (tmp_path / "tooling" / "__init__.py").write_text("") |
| 164 | + |
| 165 | + completed: subprocess.CompletedProcess[str] = run_fensu_check(tmp_path, test_case.path) |
| 166 | + |
| 167 | + output: str = completed.stdout + completed.stderr |
| 168 | + assert completed.returncode == test_case.expected_returncode, output |
| 169 | + assert test_case.expected_summary in output, output |
| 170 | + assert test_case.absent_summary not in output, output |
0 commit comments