use crate::adapters::analyzers::coupling::sdp::*;
use crate::adapters::analyzers::coupling::{metrics::compute_coupling_metrics, ModuleGraph};
#[test]
fn test_no_violations_all_same_instability() {
let graph = ModuleGraph {
modules: vec!["a".into(), "b".into()],
forward: vec![vec![1], vec![0]],
};
let metrics = compute_coupling_metrics(&graph);
let violations = check_sdp(&graph, &metrics);
assert!(
violations.is_empty(),
"Equal instability should not trigger SDP"
);
}
#[test]
fn test_violation_stable_depends_on_unstable() {
let graph = ModuleGraph {
modules: vec![
"a".into(),
"b".into(),
"x".into(),
"y".into(),
"p".into(),
"q".into(),
],
forward: vec![
vec![1], vec![4, 5], vec![0], vec![0], vec![], vec![], ],
};
let metrics = compute_coupling_metrics(&graph);
let violations = check_sdp(&graph, &metrics);
assert_eq!(violations.len(), 1);
assert_eq!(violations[0].from_module, "a");
assert_eq!(violations[0].to_module, "b");
assert!(violations[0].from_instability < violations[0].to_instability);
}
#[test]
fn test_no_violation_unstable_depends_on_stable() {
let graph = ModuleGraph {
modules: vec!["a".into(), "b".into()],
forward: vec![vec![1], vec![]],
};
let metrics = compute_coupling_metrics(&graph);
let violations = check_sdp(&graph, &metrics);
assert!(
violations.is_empty(),
"Unstable depending on stable is correct SDP"
);
}
#[test]
fn test_no_violations_empty_graph() {
let graph = ModuleGraph {
modules: vec![],
forward: vec![],
};
let violations = check_sdp(&graph, &[]);
assert!(violations.is_empty());
}
#[test]
fn test_no_violations_single_module() {
let graph = ModuleGraph {
modules: vec!["a".into()],
forward: vec![vec![]],
};
let metrics = compute_coupling_metrics(&graph);
let violations = check_sdp(&graph, &metrics);
assert!(violations.is_empty());
}
#[test]
fn test_zero_violations_for_stable_leaves() {
let graph = ModuleGraph {
modules: vec!["a".into(), "b".into(), "c".into(), "d".into(), "e".into()],
forward: vec![
vec![1, 2], vec![], vec![], vec![0], vec![0], ],
};
let metrics = compute_coupling_metrics(&graph);
let violations = check_sdp(&graph, &metrics);
assert!(violations.is_empty());
}
#[test]
fn test_violation_details() {
let graph = ModuleGraph {
modules: vec![
"a".into(),
"b".into(),
"x".into(),
"y".into(),
"p".into(),
"q".into(),
],
forward: vec![
vec![1], vec![4, 5], vec![0], vec![0], vec![], vec![], ],
};
let metrics = compute_coupling_metrics(&graph);
let violations = check_sdp(&graph, &metrics);
assert_eq!(violations.len(), 1);
let v = &violations[0];
assert_eq!(v.from_module, "a");
assert_eq!(v.to_module, "b");
assert!(v.from_instability < 0.5);
assert!(v.to_instability > 0.5);
}
#[test]
fn test_sdp_violation_default_not_suppressed() {
let graph = ModuleGraph {
modules: vec![
"a".into(),
"b".into(),
"x".into(),
"y".into(),
"p".into(),
"q".into(),
],
forward: vec![vec![1], vec![4, 5], vec![0], vec![0], vec![], vec![]],
};
let metrics = compute_coupling_metrics(&graph);
let violations = check_sdp(&graph, &metrics);
assert_eq!(violations.len(), 1);
assert!(
!violations[0].suppressed,
"SDP violations should default to not suppressed"
);
}
#[test]
fn test_sdp_violation_suppressed_when_from_module_suppressed() {
let graph = ModuleGraph {
modules: vec![
"a".into(),
"b".into(),
"x".into(),
"y".into(),
"p".into(),
"q".into(),
],
forward: vec![vec![1], vec![4, 5], vec![0], vec![0], vec![], vec![]],
};
let mut metrics = compute_coupling_metrics(&graph);
metrics[0].suppressed = true; let violations = check_sdp(&graph, &metrics);
assert_eq!(violations.len(), 1);
assert!(
violations[0].suppressed,
"from_module suppressed → violation created suppressed"
);
}
#[test]
fn test_sdp_violation_suppressed_when_to_module_suppressed() {
let graph = ModuleGraph {
modules: vec![
"a".into(),
"b".into(),
"x".into(),
"y".into(),
"p".into(),
"q".into(),
],
forward: vec![vec![1], vec![4, 5], vec![0], vec![0], vec![], vec![]],
};
let mut metrics = compute_coupling_metrics(&graph);
metrics[1].suppressed = true; let violations = check_sdp(&graph, &metrics);
assert_eq!(violations.len(), 1);
assert!(
violations[0].suppressed,
"to_module suppressed → violation created suppressed"
);
}