#[cfg_attr(coverage_nightly, coverage(off))]
#[cfg(test)]
mod tests {
use super::*;
use crate::services::defect_probability::RiskLevel;
fn strip_ansi(s: &str) -> String {
let re = regex::Regex::new(r"\x1b\[[0-9;]*m").unwrap();
re.replace_all(s, "").to_string()
}
#[test]
fn test_defect_prediction_config_struct() {
let config = DefectPredictionConfig {
confidence_threshold: 0.8,
min_lines: 10,
include_low_confidence: false,
high_risk_only: true,
include_recommendations: true,
include: Some("src/".to_string()),
exclude: Some("test".to_string()),
};
assert_eq!(config.confidence_threshold, 0.8);
assert_eq!(config.min_lines, 10);
assert!(!config.include_low_confidence);
assert!(config.high_risk_only);
}
#[test]
fn test_calculate_simple_complexity_empty() {
let complexity = calculate_simple_complexity("");
assert_eq!(complexity, 1); }
#[test]
fn test_calculate_simple_complexity_no_branching() {
let code = r#"
let x = 1;
let y = 2;
let z = x + y;
"#;
let complexity = calculate_simple_complexity(code);
assert_eq!(complexity, 1); }
#[test]
fn test_calculate_simple_complexity_with_if() {
let code = r#"
if x > 0 {
return true;
}
"#;
let complexity = calculate_simple_complexity(code);
assert!(complexity > 1);
}
#[test]
fn test_calculate_simple_complexity_with_loops() {
let code = r#"
for item in items {
process(item);
}
while running {
tick();
}
"#;
let complexity = calculate_simple_complexity(code);
assert!(complexity >= 3); }
#[test]
fn test_calculate_simple_complexity_with_match() {
let code = r#"
match value {
0 => zero(),
1 => one(),
_ => other(),
}
"#;
let complexity = calculate_simple_complexity(code);
assert!(complexity > 1);
}
#[test]
fn test_calculate_simple_complexity_with_logical_operators() {
let code = r#"
if x && y {
do_something();
}
if a || b {
do_other();
}
"#;
let complexity = calculate_simple_complexity(code);
assert!(complexity >= 3);
}
#[test]
fn test_calculate_simple_complexity_with_exception_handling() {
let code = r#"
catch (Exception e) {
log(e);
}
except ValueError:
handle_error()
"#;
let complexity = calculate_simple_complexity(code);
assert!(complexity >= 3);
}
#[test]
fn test_calculate_simple_churn_score_empty() {
let score = calculate_simple_churn_score("", 0);
assert!((0.0..=1.0).contains(&score));
}
#[test]
fn test_calculate_simple_churn_score_with_todos() {
let code = r#"
// TODO: fix this
fn main() {
// FIXME: broken
println!("hello");
}
"#;
let score = calculate_simple_churn_score(code, 5);
assert!(score > 0.0);
}
#[test]
fn test_calculate_simple_churn_score_with_comments() {
let code = r#"
// This is a comment
// Another comment
/* Block comment */
fn main() {
println!("hello");
}
"#;
let score = calculate_simple_churn_score(code, 7);
assert!((0.0..=1.0).contains(&score));
}
#[test]
fn test_calculate_simple_churn_score_no_comments() {
let code = r#"
fn main() {
println!("hello");
}
"#;
let score = calculate_simple_churn_score(code, 4);
assert!(score >= 0.4);
}
#[test]
fn test_collect_file_metrics_empty() {
let files: Vec<(PathBuf, String, usize)> = vec![];
let metrics = collect_file_metrics(&files);
assert!(metrics.is_empty());
}
#[test]
fn test_collect_file_metrics_single_file() {
let files = vec![(
PathBuf::from("test.rs"),
"fn main() {\n println!(\"hello\");\n}".to_string(),
3,
)];
let metrics = collect_file_metrics(&files);
assert_eq!(metrics.len(), 1);
assert_eq!(metrics[0].lines_of_code, 3);
assert!(metrics[0].complexity >= 1.0);
}
#[test]
fn test_collect_file_metrics_with_imports() {
let code = r#"
use std::io;
import os
#include <stdio.h>
fn main() {}
"#;
let files = vec![(PathBuf::from("test.rs"), code.to_string(), 5)];
let metrics = collect_file_metrics(&files);
assert_eq!(metrics[0].afferent_coupling, 3.0); }
#[test]
fn test_count_conditional_statements() {
assert_eq!(count_conditional_statements("if x > 0 {"), 1);
assert_eq!(count_conditional_statements("else if y < 0 {"), 1);
assert_eq!(count_conditional_statements("let x = 1;"), 0);
}
#[test]
fn test_count_loop_statements() {
assert_eq!(count_loop_statements("for item in items {"), 1);
assert_eq!(count_loop_statements("while running {"), 1);
assert_eq!(count_loop_statements("let x = 1;"), 0);
}
#[test]
fn test_count_pattern_matching() {
assert_eq!(count_pattern_matching("match value {"), 1);
assert_eq!(count_pattern_matching("switch (x) {"), 1);
assert_eq!(count_pattern_matching("case 1:"), 1);
assert_eq!(count_pattern_matching("x => y"), 1);
assert_eq!(count_pattern_matching("let x = 1;"), 0);
}
#[test]
fn test_count_logical_operators() {
assert_eq!(count_logical_operators("if x && y {"), 1);
assert_eq!(count_logical_operators("if a || b {"), 1);
assert_eq!(count_logical_operators("if x && y || z {"), 1); assert_eq!(count_logical_operators("let x = 1;"), 0);
}
#[test]
fn test_count_exception_handling() {
assert_eq!(count_exception_handling("catch (Exception e) {"), 1);
assert_eq!(count_exception_handling("except ValueError:"), 1);
assert_eq!(count_exception_handling("try {"), 0);
}
#[test]
fn test_count_line_complexity() {
let complexity = count_line_complexity("if x && y {");
assert!(complexity >= 2); }
#[test]
fn test_defect_analysis_result_struct() {
let result = DefectAnalysisResult {
file_metrics: vec![],
filtered_predictions: vec![],
analysis_time: std::time::Duration::from_secs(1),
};
assert!(result.file_metrics.is_empty());
assert!(result.filtered_predictions.is_empty());
assert_eq!(result.analysis_time.as_secs(), 1);
}
#[test]
fn test_risk_distribution_struct() {
let dist = RiskDistribution {
high_risk_count: 5,
medium_risk_count: 10,
low_risk_count: 20,
};
assert_eq!(dist.high_risk_count, 5);
assert_eq!(dist.medium_risk_count, 10);
assert_eq!(dist.low_risk_count, 20);
}
include!("defect_prediction_tests_part2.rs");
}
#[cfg_attr(coverage_nightly, coverage(off))]
#[cfg(test)]
mod property_tests {
use proptest::prelude::*;
proptest! {
#[test]
fn basic_property_stability(_input in ".*") {
prop_assert!(true);
}
#[test]
fn module_consistency_check(_x in 0u32..1000) {
prop_assert!(_x < 1001);
}
}
}