archunit/slices/assertion/
forbidden_slice_dependencies.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
use crate::common::ProjectedEdge;

use super::{SliceDependencyRule, SliceDependencyViolation};

/// Collects dependencies that match one forbidden source-to-target slice pair.
#[must_use]
pub fn gather_forbidden_slice_dependency_violations(
    edges: &[ProjectedEdge],
    source_slice: &str,
    target_slice: &str,
) -> Vec<SliceDependencyViolation> {
    edges
        .iter()
        .filter(|edge| edge.source_label == source_slice && edge.target_label == target_slice)
        .cloned()
        .map(|edge| {
            SliceDependencyViolation::new(
                edge,
                source_slice,
                target_slice,
                SliceDependencyRule::ContainDependency,
                true,
            )
        })
        .collect()
}

#[cfg(test)]
mod tests {
    use crate::common::{Edge, ImportKind, ProjectedEdge};

    use super::gather_forbidden_slice_dependency_violations;

    fn projected(source: &str, target: &str) -> ProjectedEdge {
        ProjectedEdge::new(
            source,
            target,
            [Edge::new(source, target, false, [ImportKind::Use])],
        )
    }

    #[test]
    fn returns_only_the_exact_directed_forbidden_pair() {
        let rejected = projected("api", "database");
        let edges = [
            projected("api", "application"),
            rejected.clone(),
            projected("database", "api"),
        ];

        let violations = gather_forbidden_slice_dependency_violations(&edges, "api", "database");

        assert_eq!(violations.len(), 1);
        assert_eq!(violations[0].dependency, rejected);
        assert!(violations[0].is_negated);
    }
}