Skip to main content

libverify_core/
size.rs

1/// Check if a filename matches common generated-file patterns.
2///
3/// Matches: `*.lock`, `*-lock.json`, `*-lock.yaml`, `*-lock.yml`, `*.snap`, `*.generated.*`
4pub fn is_generated_file(filename: &str) -> bool {
5    let name = filename.rsplit('/').next().unwrap_or(filename);
6    name.ends_with(".lock")
7        || name.ends_with("-lock.json")
8        || name.ends_with("-lock.yaml")
9        || name.ends_with("-lock.yml")
10        || name.ends_with(".snap")
11        || name.contains(".generated.")
12}
13
14use crate::verdict::Severity;
15
16/// Classify a change request's size into a severity level.
17///
18/// Returns `Error` when either dimension exceeds its error threshold,
19/// `Warning` when either exceeds its warning threshold, `Pass` otherwise.
20pub fn classify_pr_size(
21    total_lines: usize,
22    total_files: usize,
23    warn_lines: usize,
24    warn_files: usize,
25    error_lines: usize,
26    error_files: usize,
27) -> Severity {
28    if total_lines > error_lines || total_files > error_files {
29        Severity::Error
30    } else if total_lines > warn_lines || total_files > warn_files {
31        Severity::Warning
32    } else {
33        Severity::Pass
34    }
35}
36
37#[cfg(test)]
38mod tests {
39    use super::*;
40
41    // ── is_generated_file ──────────────────────────────────────────
42
43    #[test]
44    fn lock_file() {
45        assert!(is_generated_file("Cargo.lock"));
46        assert!(is_generated_file("yarn.lock"));
47        assert!(is_generated_file("deep/path/Gemfile.lock"));
48    }
49
50    #[test]
51    fn lock_json() {
52        assert!(is_generated_file("package-lock.json"));
53        assert!(is_generated_file("node_modules/foo/package-lock.json"));
54    }
55
56    #[test]
57    fn lock_yaml() {
58        assert!(is_generated_file("pnpm-lock.yaml"));
59        assert!(is_generated_file("some/path/pnpm-lock.yaml"));
60        assert!(is_generated_file("pnpm-lock.yml"));
61    }
62
63    #[test]
64    fn yarn_lock() {
65        assert!(is_generated_file("yarn.lock"));
66        assert!(is_generated_file("packages/app/yarn.lock"));
67    }
68
69    #[test]
70    fn snap_file() {
71        assert!(is_generated_file("tests/__snapshots__/foo.snap"));
72    }
73
74    #[test]
75    fn generated_file() {
76        assert!(is_generated_file("src/schema.generated.ts"));
77        assert!(is_generated_file("proto/api.generated.go"));
78    }
79
80    #[test]
81    fn normal_file() {
82        assert!(!is_generated_file("src/main.rs"));
83        assert!(!is_generated_file("README.md"));
84        assert!(!is_generated_file("lib/lock_manager.rs"));
85    }
86
87    // ── classify_pr_size ───────────────────────────────────────────
88
89    const WARN_LINES: usize = 500;
90    const WARN_FILES: usize = 15;
91    const ERROR_LINES: usize = 1000;
92    const ERROR_FILES: usize = 30;
93
94    #[test]
95    fn small_pr_passes() {
96        assert_eq!(
97            classify_pr_size(10, 2, WARN_LINES, WARN_FILES, ERROR_LINES, ERROR_FILES),
98            Severity::Pass,
99        );
100    }
101
102    #[test]
103    fn many_lines_warns() {
104        assert_eq!(
105            classify_pr_size(600, 5, WARN_LINES, WARN_FILES, ERROR_LINES, ERROR_FILES),
106            Severity::Warning,
107        );
108    }
109
110    #[test]
111    fn many_files_warns() {
112        assert_eq!(
113            classify_pr_size(100, 20, WARN_LINES, WARN_FILES, ERROR_LINES, ERROR_FILES),
114            Severity::Warning,
115        );
116    }
117
118    #[test]
119    fn huge_pr_errors() {
120        assert_eq!(
121            classify_pr_size(1500, 40, WARN_LINES, WARN_FILES, ERROR_LINES, ERROR_FILES),
122            Severity::Error,
123        );
124    }
125
126    #[test]
127    fn boundary_at_threshold_passes() {
128        // Exactly at the threshold is not "exceeds", so it should pass/warn respectively.
129        assert_eq!(
130            classify_pr_size(500, 15, WARN_LINES, WARN_FILES, ERROR_LINES, ERROR_FILES),
131            Severity::Pass,
132        );
133        assert_eq!(
134            classify_pr_size(1000, 30, WARN_LINES, WARN_FILES, ERROR_LINES, ERROR_FILES),
135            Severity::Warning,
136        );
137    }
138}