Files
pgr/tests/test_rust_audits.py
2026-09-25 17:41:26 +02:00

261 lines
8.3 KiB
Python

# file: tests/test_rust_audits.py
# version: 2
"""Targeted contracts for the optional monotask Rust structure audits."""
from __future__ import annotations
import pathlib
import subprocess
import sys
import tempfile
import unittest
sys.path.insert(0, str(pathlib.Path(__file__).resolve().parents[1] / "scripts"))
from audit_rust_blank_lines import audit_file as audit_blanks # noqa: E402
from audit_rust_const_blocks import audit_file as audit_consts # noqa: E402
from audit_rust_item_spacing import audit_file as audit_item_spacing # noqa: E402
from audit_rust_module_order import audit_file as audit_module_order # noqa: E402
from audit_rust_reexport_blocks import audit_file as audit_reexports # noqa: E402
from audit_rust_trait_import_blocks import audit_file as audit_trait_imports # noqa: E402
from _rust_audit_common import selected_files # noqa: E402
class RustAuditTests(unittest.TestCase):
def setUp(self) -> None:
self.temporary = tempfile.TemporaryDirectory()
self.addCleanup(self.temporary.cleanup)
self.root = pathlib.Path(self.temporary.name)
def source(self, text: str) -> pathlib.Path:
path = self.root / "source.rs"
path.write_text(text, encoding="utf-8")
return path
def test_clean_body_and_const_visibility_groups(self) -> None:
path = self.source("""pub const ALPHA: u8 = 1;
pub const BETA: u8 = 2;
pub(crate) const GAMMA: u8 = 3;
const OMEGA: u8 = 4;
fn sample() {
let value = r#"{\n\n}"#;
println!("{value}");
}
""")
self.assertEqual(audit_blanks(path), [])
self.assertEqual(audit_consts(path), [])
def test_blank_body_and_repeated_blank_lines(self) -> None:
path = self.source("""fn sample() {
let value = 1;
println!("{value}");
}
""")
issues = audit_blanks(path)
self.assertTrue(any("consecutive" in issue for issue in issues))
self.assertTrue(any("inside fn body" in issue for issue in issues))
def test_blank_string_and_nested_comment_braces_are_ignored(self) -> None:
path = self.source('''fn sample() {
let data = r#"{
}"#;
/* outer { /* inner } */ outer } */
println!("{data}");
}
''')
self.assertEqual(audit_blanks(path), [])
def test_struct_body_and_tuple_struct(self) -> None:
path = self.source("""struct Payload {
x: u8,
y: u8,
}
struct Pair(u8, u8);
""")
self.assertEqual(len(audit_blanks(path)), 1)
self.assertIn("struct body", audit_blanks(path)[0])
def test_const_order_and_multiline_initializer(self) -> None:
path = self.source("""const BETA: [u8; 2] = [
1,
2,
];
const ALPHA: u8 = 1;
pub const GAMMA: u8 = 3;
""")
issues = audit_consts(path)
self.assertTrue(any("alphabetical" in issue for issue in issues))
self.assertTrue(any("visibility" in issue for issue in issues))
def test_const_spacing(self) -> None:
path = self.source("""pub const ALPHA: u8 = 1;
pub const BETA: u8 = 2;
pub(crate) const GAMMA: u8 = 3;
""")
issues = audit_consts(path)
self.assertEqual(sum("blank line(s)" in issue for issue in issues), 2)
def test_const_function_does_not_join_const_block(self) -> None:
path = self.source("""const ZETA: u8 = 1;
const fn compute() -> u8 {
1
}
const ALPHA: u8 = 2;
""")
self.assertEqual(audit_consts(path), [])
def test_scope_and_missing_path(self) -> None:
self.source("fn sample() {}\n")
selected, errors = selected_files([str(self.root), str(self.root / "absent.rs")])
self.assertEqual(len(selected), 1)
self.assertEqual(len(errors), 1)
def test_cli_status_for_success_violation_and_invalid_selection(self) -> None:
path = self.source("const ALPHA: u8 = 1;\nconst BETA: u8 = 2;\n")
script = pathlib.Path(__file__).resolve().parents[1] / "scripts" / "audit_rust_const_blocks.py"
def run(subject: pathlib.Path) -> subprocess.CompletedProcess[str]:
return subprocess.run([sys.executable, "-B", str(script), str(subject)], capture_output=True, text=True, check=False)
self.assertEqual(run(path).returncode, 0)
path.write_text("const BETA: u8 = 1;\nconst ALPHA: u8 = 2;\n", encoding="utf-8")
self.assertEqual(run(path).returncode, 1)
self.assertEqual(run(self.root / "missing.rs").returncode, 2)
def test_item_spacing_between_distinct_items(self) -> None:
path = self.source("""struct Alpha {}
struct Beta {}
fn sample() {}
""")
issues = audit_item_spacing(path)
self.assertTrue(any("exactly one blank line" in issue for issue in issues))
def test_item_spacing_delegates_compact_declaration_blocks(self) -> None:
path = self.source("""const ALPHA: u8 = 1;
const BETA: u8 = 2;
static CACHE: u8 = 0;
static READY: u8 = 1;
type First = u8;
type Second = u16;
""")
self.assertEqual(audit_item_spacing(path), [])
def test_item_spacing_inside_impl(self) -> None:
path = self.source("""struct Sample {}
impl Sample {
fn alpha() {}
fn beta() {}
}
""")
self.assertTrue(any("exactly one blank line" in issue for issue in audit_item_spacing(path)))
def test_item_spacing_does_not_infer_across_macro(self) -> None:
path = self.source("""struct Alpha {}
macro_rules! generated { () => {}; }
struct Beta {}
""")
self.assertEqual(audit_item_spacing(path), [])
def test_module_order_production_and_tests(self) -> None:
path = self.source("""mod beta;
mod alpha;
#[cfg(test)]
mod tests;
""")
issues = audit_module_order(path)
self.assertTrue(any("production" in issue for issue in issues))
path.write_text("#[cfg(test)]\nmod tests;\nmod alpha;\n", encoding="utf-8")
self.assertTrue(any("test modules must follow" in issue for issue in audit_module_order(path)))
def test_module_order_clean_with_path_attribute(self) -> None:
path = self.source("""mod alpha;
mod beta;
#[cfg(test)]
#[path = "unit_tests/mod.rs"]
mod unit_tests;
""")
self.assertEqual(audit_module_order(path), [])
def test_reexport_blocks_visibility_and_spacing(self) -> None:
path = self.source("""pub(crate) use self::internal::Internal;
pub use self::public::Public;
""")
issues = audit_reexports(path)
self.assertTrue(any("must precede" in issue for issue in issues))
path.write_text("pub use self::public::Alpha;\n\npub use self::public::Beta;\n", encoding="utf-8")
self.assertTrue(any("contains an empty line" in issue for issue in audit_reexports(path)))
def test_reexport_blocks_clean_with_rustdocs(self) -> None:
path = self.source("""/// Alpha.
pub use self::public::Alpha;
/// Beta.
pub use self::public::Beta;
/// Internal.
pub(crate) use self::internal::Internal;
""")
self.assertEqual(audit_reexports(path), [])
def test_trait_import_block_layout(self) -> None:
path = self.source("""use alpha::AlphaTrait;
use beta::BetaTrait;
struct Sample {}
""")
self.assertTrue(any("contains an empty line" in issue for issue in audit_trait_imports(path)))
path.write_text("struct Sample {}\n\nuse alpha::AlphaTrait;\n", encoding="utf-8")
self.assertTrue(any("must precede" in issue for issue in audit_trait_imports(path)))
def test_trait_import_block_clean_and_exports_ignored(self) -> None:
path = self.source("""mod alpha;
use alpha::AlphaTrait;
use beta::BetaTrait;
struct Sample {}
pub use self::alpha::Alpha;
""")
self.assertEqual(audit_trait_imports(path), [])
def test_new_audit_cli_statuses(self) -> None:
path = self.source("mod alpha;\nmod beta;\n")
root = pathlib.Path(__file__).resolve().parents[1] / "scripts"
scripts = (
root / "audit_rust_item_spacing.py",
root / "audit_rust_module_order.py",
root / "audit_rust_reexport_blocks.py",
root / "audit_rust_trait_import_blocks.py",
)
for script in scripts:
result = subprocess.run([sys.executable, "-B", str(script), str(path)], capture_output=True, text=True, check=False)
self.assertEqual(result.returncode, 0, (script, result.stderr))
missing = subprocess.run([sys.executable, "-B", str(script), str(self.root / "missing.rs")], capture_output=True, text=True, check=False)
self.assertEqual(missing.returncode, 2, (script, missing.stderr))
if __name__ == "__main__":
unittest.main()