use super::orphan_target_helpers::*;
use super::*;
use crate::domain::findings::OrphanKind;
use crate::findings::Dimension;
#[test]
fn file_length_pin_mismatches_god_struct_is_orphan() {
let out = orphans(Dimension::Srp, "file_length", Some(400.0), 5, |a| {
a.findings.srp.push(make_srp_struct_finding("src/x.rs", 5));
});
assert_eq!(out.len(), 1, "file_length pin must not match god_struct");
assert_eq!(out[0].target_spec().as_deref(), Some("file_length=400"));
assert_eq!(out[0].target_suffix(), ", file_length=400");
}
#[test]
fn complexity_wrong_metric_target_is_orphan() {
let m = ComplexityMetrics {
cognitive_complexity: 18,
..Default::default()
};
let out = orphans(
Dimension::Complexity,
"max_cyclomatic",
Some(20.0),
10,
|a| {
a.results = vec![make_fa_with_complexity("src/x.rs", 10, m.clone())];
},
);
assert_eq!(
out.len(),
1,
"max_cyclomatic pin must not match a cognitive finding"
);
}
#[test]
fn cluster_pin_on_length_only_finding_is_orphan() {
let out = orphans(
Dimension::Srp,
"max_independent_clusters",
Some(5.0),
1,
|a| {
a.findings
.srp
.push(srp_module_full("src/x.rs", 350, 1.5, 1));
},
);
assert_eq!(
out.len(),
1,
"cluster pin on a length-only finding must be flagged, got {out:?}"
);
assert_eq!(
out[0].kind,
OrphanKind::Stale,
"an inactive-component pin is stale: {out:?}"
);
}
#[test]
fn file_length_pin_on_cluster_only_finding_is_orphan() {
let out = orphans(Dimension::Srp, "file_length", Some(400.0), 1, |a| {
a.findings
.srp
.push(srp_module_full("src/x.rs", 200, 0.5, 5));
});
assert_eq!(
out.len(),
1,
"file_length pin on a cluster-only finding must be flagged, got {out:?}"
);
assert_eq!(
out[0].kind,
OrphanKind::Stale,
"an inactive-component pin is stale: {out:?}"
);
}
#[test]
fn magic_numbers_pin_above_function_is_not_orphan() {
let m = ComplexityMetrics {
magic_numbers: vec![crate::adapters::analyzers::iosp::MagicNumberOccurrence {
line: 25,
value: "42".to_string(),
}],
..Default::default()
};
let out = orphans(Dimension::Complexity, "magic_numbers", None, 10, |a| {
a.results = vec![make_fa_with_complexity("src/x.rs", 10, m.clone())];
});
assert!(
out.is_empty(),
"magic_numbers marker on the fn must match, got {out:?}"
);
}
#[test]
fn targeted_coupling_pin_with_structural_finding_is_not_orphan() {
let out = orphans(Dimension::Coupling, "max_fan_out", Some(10.0), 5, |a| {
a.findings
.coupling
.push(make_structural_coupling_finding("src/x.rs", 5));
});
assert!(
out.is_empty(),
"targeted coupling pin is module-global, not orphan: {out:?}"
);
}
#[test]
fn targeted_coupling_sdp_pin_without_finding_is_not_orphan() {
let out = orphans(Dimension::Coupling, "sdp", None, 5, |_a| {});
assert!(
out.is_empty(),
"module-global coupling marker is unverifiable: {out:?}"
);
}
#[test]
fn coupling_metric_pin_is_never_too_loose_checked() {
let out = orphans(Dimension::Coupling, "max_instability", Some(0.99), 5, |a| {
a.findings
.coupling
.push(make_structural_coupling_finding("src/x.rs", 5));
});
assert!(
out.is_empty(),
"coupling metric pins are not too-loose-checked: {out:?}"
);
}
#[test]
fn structural_coupling_target_matches_its_finding() {
let out = orphans(Dimension::Coupling, "sit", None, 5, |a| {
a.findings
.coupling
.push(make_structural_coupling_finding("src/x.rs", 5));
});
assert!(
out.is_empty(),
"allow(coupling, sit) matches a SIT finding: {out:?}"
);
}
#[test]
fn structural_coupling_target_wrong_kind_is_orphan() {
let out = orphans(Dimension::Coupling, "oi", None, 5, |a| {
a.findings
.coupling
.push(make_structural_coupling_finding("src/x.rs", 5));
});
assert_eq!(
out.len(),
1,
"allow(coupling, oi) must not match a SIT finding: {out:?}"
);
}
#[test]
fn both_active_module_finding_emits_both_targets() {
let push = |a: &mut crate::report::AnalysisResult| {
a.findings
.srp
.push(srp_module_full("src/x.rs", 900, 1.5, 5));
};
assert!(orphans(Dimension::Srp, "file_length", Some(900.0), 1, push).is_empty());
assert!(orphans(
Dimension::Srp,
"max_independent_clusters",
Some(5.0),
1,
push
)
.is_empty());
assert_eq!(
orphans(Dimension::Srp, "god_struct", None, 1, push).len(),
1
);
}
fn arch_finding(
file: &str,
line: usize,
rule_id: &str,
) -> crate::domain::findings::ArchitectureFinding {
crate::domain::findings::ArchitectureFinding {
common: make_finding(file, line, Dimension::Architecture, rule_id),
}
}
fn arch_enabled() -> Config {
let mut c = Config::default();
c.architecture.enabled = true;
c
}
#[test]
fn architecture_targeted_wrong_family_is_orphan() {
let cfg = arch_enabled();
let out = orphans_cfg(
target_of("layer", None),
Dimension::Architecture,
5,
&cfg,
|a| {
a.findings
.architecture
.push(arch_finding("src/x.rs", 5, "architecture/forbidden"));
},
);
assert_eq!(
out.len(),
1,
"layer marker must not match a forbidden finding: {out:?}"
);
}
#[test]
fn architecture_targeted_right_family_is_clean() {
let cfg = arch_enabled();
let out = orphans_cfg(
target_of("forbidden", None),
Dimension::Architecture,
5,
&cfg,
|a| {
a.findings.architecture.push(arch_finding(
"src/x.rs",
5,
"architecture/forbidden/edge",
));
},
);
assert!(
out.is_empty(),
"forbidden marker matches a forbidden finding: {out:?}"
);
}
#[test]
fn tq_targeted_wrong_kind_is_orphan() {
use crate::domain::findings::TqFindingKind;
let out = orphans(Dimension::TestQuality, "uncovered", None, 5, |a| {
a.findings
.test_quality
.push(make_tq_finding("src/x.rs", 5, TqFindingKind::NoAssertion));
});
assert_eq!(
out.len(),
1,
"uncovered marker must not match a no_assertion finding: {out:?}"
);
}
#[test]
fn tq_targeted_right_kind_is_clean() {
use crate::domain::findings::TqFindingKind;
let out = orphans(Dimension::TestQuality, "no_assertion", None, 5, |a| {
a.findings
.test_quality
.push(make_tq_finding("src/x.rs", 5, TqFindingKind::NoAssertion));
});
assert!(
out.is_empty(),
"no_assertion marker matches its own kind: {out:?}"
);
}
#[test]
fn dry_targeted_wrong_kind_is_orphan() {
let out = orphans(Dimension::Dry, "duplicate", None, 5, |a| {
a.findings
.dry
.push(make_dry_wildcard_finding("src/x.rs", 5));
});
assert_eq!(
out.len(),
1,
"duplicate marker must not match a wildcard finding: {out:?}"
);
}