use std::fs;
use assert_cmd::Command;
use predicates::prelude::*;
use tempfile::TempDir;
fn cli() -> Command {
Command::cargo_bin("bca").unwrap()
}
const SUPPRESSED_RUST: &str = r#"
pub fn classify(n: i32) -> &'static str {
// bca: suppress(cyclomatic)
if n < 0 {
"neg"
} else if n == 0 {
"zero"
} else {
"pos"
}
}
"#;
const LIZARD_RUST: &str = r#"
pub fn classify(n: i32) -> &'static str {
// #lizard forgives
if n < 0 {
"neg"
} else {
"pos"
}
}
"#;
const FILE_SUPPRESSED_RUST: &str = r#"
// bca: suppress-file(cyclomatic)
pub fn classify(n: i32) -> &'static str {
if n < 0 {
"neg"
} else {
"pos"
}
}
"#;
fn write_fixture(dir: &TempDir, name: &str, body: &str) -> String {
let path = dir.path().join(name);
fs::write(&path, body).expect("write fixture");
path.to_str().expect("utf8 fixture path").to_string()
}
#[test]
fn suppression_marker_silences_violation_by_default() {
let dir = TempDir::new().unwrap();
let path = write_fixture(&dir, "branchy.rs", SUPPRESSED_RUST);
cli()
.args(["--paths", &path, "check", "--threshold", "cyclomatic=1"])
.assert()
.success()
.stderr(predicate::str::is_empty());
}
#[test]
fn no_suppress_flag_re_enables_violation() {
let dir = TempDir::new().unwrap();
let path = write_fixture(&dir, "branchy.rs", SUPPRESSED_RUST);
cli()
.args([
"--paths",
&path,
"check",
"--threshold",
"cyclomatic=1",
"--no-suppress",
])
.assert()
.code(2)
.stderr(predicate::str::contains("classify"))
.stderr(predicate::str::contains("cyclomatic"));
}
#[test]
fn lizard_compat_marker_silences_violation() {
let dir = TempDir::new().unwrap();
let path = write_fixture(&dir, "branchy.rs", LIZARD_RUST);
cli()
.args(["--paths", &path, "check", "--threshold", "cyclomatic=1"])
.assert()
.success()
.stderr(predicate::str::is_empty());
}
#[test]
fn file_scoped_marker_silences_nested_function_violation() {
let dir = TempDir::new().unwrap();
let path = write_fixture(&dir, "branchy.rs", FILE_SUPPRESSED_RUST);
cli()
.args(["--paths", &path, "check", "--threshold", "cyclomatic=1"])
.assert()
.success()
.stderr(predicate::str::is_empty());
}
const LEGACY_ALLOW_RUST: &str = r#"
pub fn classify(n: i32) -> &'static str {
// bca: allow(cyclomatic)
if n < 0 {
"neg"
} else if n == 0 {
"zero"
} else {
"pos"
}
}
"#;
#[test]
fn legacy_allow_marker_does_not_suppress() {
let dir = TempDir::new().unwrap();
let path = write_fixture(&dir, "branchy.rs", LEGACY_ALLOW_RUST);
cli()
.args(["--paths", &path, "check", "--threshold", "cyclomatic=1"])
.assert()
.code(2)
.stderr(predicate::str::contains("classify"))
.stderr(predicate::str::contains("cyclomatic"))
.stderr(predicate::str::contains(
"unknown bca directive verb 'allow'",
));
}
#[test]
fn unsuppressed_metric_still_violates() {
let dir = TempDir::new().unwrap();
let path = write_fixture(&dir, "branchy.rs", SUPPRESSED_RUST);
cli()
.args(["--paths", &path, "check", "--threshold", "cognitive=0"])
.assert()
.code(2)
.stderr(predicate::str::contains("cognitive"));
}