use debtmap::complexity::{
average_complexity, combine_complexity, max_complexity, ComplexityCalculator,
};
use debtmap::core::FunctionMetrics;
use std::path::PathBuf;
#[test]
fn test_complexity_calculator_new() {
let calc = ComplexityCalculator::new(10, 15);
let metrics = FunctionMetrics {
name: "test".to_string(),
file: PathBuf::from("test.rs"),
line: 1,
cyclomatic: 5,
cognitive: 5,
nesting: 1,
length: 10,
is_test: false,
visibility: None,
is_trait_method: false,
in_test_module: false,
entropy_score: None,
is_pure: None,
purity_confidence: None,
detected_patterns: None,
upstream_callers: None,
downstream_callees: None,
mapping_pattern_result: None,
adjusted_complexity: None,
composition_metrics: None,
language_specific: None,
purity_reason: None,
call_dependencies: None,
purity_level: None,
error_swallowing_count: None,
error_swallowing_patterns: None,
entropy_analysis: None,
};
assert!(!calc.is_complex(&metrics));
}
#[test]
fn test_complexity_calculator_is_complex_cyclomatic() {
let calc = ComplexityCalculator::new(10, 15);
let metrics = FunctionMetrics {
name: "test".to_string(),
file: PathBuf::from("test.rs"),
line: 1,
cyclomatic: 11,
cognitive: 5,
nesting: 1,
length: 10,
is_test: false,
visibility: None,
is_trait_method: false,
in_test_module: false,
entropy_score: None,
is_pure: None,
purity_confidence: None,
detected_patterns: None,
upstream_callers: None,
downstream_callees: None,
mapping_pattern_result: None,
adjusted_complexity: None,
composition_metrics: None,
language_specific: None,
purity_reason: None,
call_dependencies: None,
purity_level: None,
error_swallowing_count: None,
error_swallowing_patterns: None,
entropy_analysis: None,
};
assert!(
calc.is_complex(&metrics),
"Should be complex when cyclomatic > threshold"
);
}
#[test]
fn test_complexity_calculator_is_complex_cognitive() {
let calc = ComplexityCalculator::new(10, 15);
let metrics = FunctionMetrics {
name: "test".to_string(),
file: PathBuf::from("test.rs"),
line: 1,
cyclomatic: 5,
cognitive: 16,
nesting: 1,
length: 10,
is_test: false,
visibility: None,
is_trait_method: false,
in_test_module: false,
entropy_score: None,
is_pure: None,
purity_confidence: None,
detected_patterns: None,
upstream_callers: None,
downstream_callees: None,
mapping_pattern_result: None,
adjusted_complexity: None,
composition_metrics: None,
language_specific: None,
purity_reason: None,
call_dependencies: None,
purity_level: None,
error_swallowing_count: None,
error_swallowing_patterns: None,
entropy_analysis: None,
};
assert!(
calc.is_complex(&metrics),
"Should be complex when cognitive > threshold"
);
}
#[test]
fn test_complexity_calculator_is_complex_both() {
let calc = ComplexityCalculator::new(10, 15);
let metrics = FunctionMetrics {
name: "test".to_string(),
file: PathBuf::from("test.rs"),
line: 1,
cyclomatic: 11,
cognitive: 16,
nesting: 1,
length: 10,
is_test: false,
visibility: None,
is_trait_method: false,
in_test_module: false,
entropy_score: None,
is_pure: None,
purity_confidence: None,
detected_patterns: None,
upstream_callers: None,
downstream_callees: None,
mapping_pattern_result: None,
adjusted_complexity: None,
composition_metrics: None,
language_specific: None,
purity_reason: None,
call_dependencies: None,
purity_level: None,
error_swallowing_count: None,
error_swallowing_patterns: None,
entropy_analysis: None,
};
assert!(
calc.is_complex(&metrics),
"Should be complex when both metrics > threshold"
);
}
#[test]
fn test_complexity_calculator_is_not_complex() {
let calc = ComplexityCalculator::new(10, 15);
let metrics = FunctionMetrics {
name: "test".to_string(),
file: PathBuf::from("test.rs"),
line: 1,
cyclomatic: 10,
cognitive: 15,
nesting: 1,
length: 10,
is_test: false,
visibility: None,
is_trait_method: false,
in_test_module: false,
entropy_score: None,
is_pure: None,
purity_confidence: None,
detected_patterns: None,
upstream_callers: None,
downstream_callees: None,
mapping_pattern_result: None,
adjusted_complexity: None,
composition_metrics: None,
language_specific: None,
purity_reason: None,
call_dependencies: None,
purity_level: None,
error_swallowing_count: None,
error_swallowing_patterns: None,
entropy_analysis: None,
};
assert!(
!calc.is_complex(&metrics),
"Should not be complex when both metrics <= threshold"
);
}
#[test]
fn test_complexity_calculator_calculate_score_low() {
let calc = ComplexityCalculator::new(10, 20);
let metrics = FunctionMetrics {
name: "test".to_string(),
file: PathBuf::from("test.rs"),
line: 1,
cyclomatic: 5,
cognitive: 10,
nesting: 1,
length: 10,
is_test: false,
visibility: None,
is_trait_method: false,
in_test_module: false,
entropy_score: None,
is_pure: None,
purity_confidence: None,
detected_patterns: None,
upstream_callers: None,
downstream_callees: None,
mapping_pattern_result: None,
adjusted_complexity: None,
composition_metrics: None,
language_specific: None,
purity_reason: None,
call_dependencies: None,
purity_level: None,
error_swallowing_count: None,
error_swallowing_patterns: None,
entropy_analysis: None,
};
let score = calc.calculate_score(&metrics);
assert_eq!(
score, 50,
"Score should be 50 when metrics are half of thresholds"
);
}
#[test]
fn test_complexity_calculator_calculate_score_medium() {
let calc = ComplexityCalculator::new(10, 20);
let metrics = FunctionMetrics {
name: "test".to_string(),
file: PathBuf::from("test.rs"),
line: 1,
cyclomatic: 10,
cognitive: 20,
nesting: 1,
length: 10,
is_test: false,
visibility: None,
is_trait_method: false,
in_test_module: false,
entropy_score: None,
is_pure: None,
purity_confidence: None,
detected_patterns: None,
upstream_callers: None,
downstream_callees: None,
mapping_pattern_result: None,
adjusted_complexity: None,
composition_metrics: None,
language_specific: None,
purity_reason: None,
call_dependencies: None,
purity_level: None,
error_swallowing_count: None,
error_swallowing_patterns: None,
entropy_analysis: None,
};
let score = calc.calculate_score(&metrics);
assert_eq!(
score, 100,
"Score should be 100 when metrics equal thresholds"
);
}
#[test]
fn test_complexity_calculator_calculate_score_high() {
let calc = ComplexityCalculator::new(10, 20);
let metrics = FunctionMetrics {
name: "test".to_string(),
file: PathBuf::from("test.rs"),
line: 1,
cyclomatic: 20,
cognitive: 40,
nesting: 1,
length: 10,
is_test: false,
visibility: None,
is_trait_method: false,
in_test_module: false,
entropy_score: None,
is_pure: None,
purity_confidence: None,
detected_patterns: None,
upstream_callers: None,
downstream_callees: None,
mapping_pattern_result: None,
adjusted_complexity: None,
composition_metrics: None,
language_specific: None,
purity_reason: None,
call_dependencies: None,
purity_level: None,
error_swallowing_count: None,
error_swallowing_patterns: None,
entropy_analysis: None,
};
let score = calc.calculate_score(&metrics);
assert_eq!(
score, 200,
"Score should be 200 when metrics are double thresholds"
);
}
#[test]
fn test_complexity_calculator_calculate_score_zero() {
let calc = ComplexityCalculator::new(10, 20);
let metrics = FunctionMetrics {
name: "test".to_string(),
file: PathBuf::from("test.rs"),
line: 1,
cyclomatic: 0,
cognitive: 0,
nesting: 0,
length: 0,
is_test: false,
visibility: None,
is_trait_method: false,
in_test_module: false,
entropy_score: None,
is_pure: None,
purity_confidence: None,
detected_patterns: None,
upstream_callers: None,
downstream_callees: None,
mapping_pattern_result: None,
adjusted_complexity: None,
composition_metrics: None,
language_specific: None,
purity_reason: None,
call_dependencies: None,
purity_level: None,
error_swallowing_count: None,
error_swallowing_patterns: None,
entropy_analysis: None,
};
let score = calc.calculate_score(&metrics);
assert_eq!(score, 0, "Score should be 0 when metrics are 0");
}
#[test]
fn test_combine_complexity() {
assert_eq!(combine_complexity(0, 0), 0);
assert_eq!(combine_complexity(5, 0), 5);
assert_eq!(combine_complexity(0, 5), 5);
assert_eq!(combine_complexity(3, 7), 10);
assert_eq!(combine_complexity(100, 200), 300);
}
#[test]
fn test_max_complexity_empty() {
let complexities: Vec<u32> = vec![];
assert_eq!(max_complexity(&complexities), 0);
}
#[test]
fn test_max_complexity_single() {
let complexities = vec![5];
assert_eq!(max_complexity(&complexities), 5);
}
#[test]
fn test_max_complexity_multiple() {
let complexities = vec![3, 7, 2, 9, 1];
assert_eq!(max_complexity(&complexities), 9);
}
#[test]
fn test_max_complexity_all_same() {
let complexities = vec![5, 5, 5, 5];
assert_eq!(max_complexity(&complexities), 5);
}
#[test]
fn test_max_complexity_with_zero() {
let complexities = vec![0, 3, 0, 7, 0];
assert_eq!(max_complexity(&complexities), 7);
}
#[test]
fn test_average_complexity_empty() {
let complexities: Vec<u32> = vec![];
assert_eq!(average_complexity(&complexities), 0.0);
}
#[test]
fn test_average_complexity_single() {
let complexities = vec![5];
assert_eq!(average_complexity(&complexities), 5.0);
}
#[test]
fn test_average_complexity_multiple() {
let complexities = vec![2, 4, 6, 8];
assert_eq!(average_complexity(&complexities), 5.0);
}
#[test]
fn test_average_complexity_with_zeros() {
let complexities = vec![0, 5, 0, 10, 0];
assert_eq!(average_complexity(&complexities), 3.0);
}
#[test]
fn test_average_complexity_large_numbers() {
let complexities = vec![100, 200, 300];
assert_eq!(average_complexity(&complexities), 200.0);
}
#[test]
fn test_average_complexity_fractional_result() {
let complexities = vec![1, 2, 3, 4, 5];
assert_eq!(average_complexity(&complexities), 3.0);
}
#[test]
fn test_average_complexity_odd_count() {
let complexities = vec![1, 2, 3];
assert_eq!(average_complexity(&complexities), 2.0);
}
#[test]
fn test_complexity_calculator_boundary_values() {
let calc = ComplexityCalculator::new(1, 1);
let metrics_zero = FunctionMetrics {
name: "zero".to_string(),
file: PathBuf::from("test.rs"),
line: 1,
cyclomatic: 0,
cognitive: 0,
nesting: 0,
length: 0,
is_test: false,
visibility: None,
is_trait_method: false,
in_test_module: false,
entropy_score: None,
is_pure: None,
purity_confidence: None,
detected_patterns: None,
upstream_callers: None,
downstream_callees: None,
mapping_pattern_result: None,
adjusted_complexity: None,
composition_metrics: None,
language_specific: None,
purity_reason: None,
call_dependencies: None,
purity_level: None,
error_swallowing_count: None,
error_swallowing_patterns: None,
entropy_analysis: None,
};
assert!(!calc.is_complex(&metrics_zero));
let metrics_one = FunctionMetrics {
name: "one".to_string(),
file: PathBuf::from("test.rs"),
line: 1,
cyclomatic: 1,
cognitive: 1,
nesting: 0,
length: 0,
is_test: false,
visibility: None,
is_trait_method: false,
in_test_module: false,
entropy_score: None,
is_pure: None,
purity_confidence: None,
detected_patterns: None,
upstream_callers: None,
downstream_callees: None,
mapping_pattern_result: None,
adjusted_complexity: None,
composition_metrics: None,
language_specific: None,
purity_reason: None,
call_dependencies: None,
purity_level: None,
error_swallowing_count: None,
error_swallowing_patterns: None,
entropy_analysis: None,
};
assert!(!calc.is_complex(&metrics_one));
let metrics_two = FunctionMetrics {
name: "two".to_string(),
file: PathBuf::from("test.rs"),
line: 1,
cyclomatic: 2,
cognitive: 2,
nesting: 0,
length: 0,
is_test: false,
visibility: None,
is_trait_method: false,
in_test_module: false,
entropy_score: None,
is_pure: None,
purity_confidence: None,
detected_patterns: None,
upstream_callers: None,
downstream_callees: None,
mapping_pattern_result: None,
adjusted_complexity: None,
composition_metrics: None,
language_specific: None,
purity_reason: None,
call_dependencies: None,
purity_level: None,
error_swallowing_count: None,
error_swallowing_patterns: None,
entropy_analysis: None,
};
assert!(calc.is_complex(&metrics_two));
}
#[test]
fn test_complexity_score_proportions() {
let calc = ComplexityCalculator::new(10, 10);
let metrics_cyclo_only = FunctionMetrics {
name: "cyclo".to_string(),
file: PathBuf::from("test.rs"),
line: 1,
cyclomatic: 10,
cognitive: 0,
nesting: 0,
length: 0,
is_test: false,
visibility: None,
is_trait_method: false,
in_test_module: false,
entropy_score: None,
is_pure: None,
purity_confidence: None,
detected_patterns: None,
upstream_callers: None,
downstream_callees: None,
mapping_pattern_result: None,
adjusted_complexity: None,
composition_metrics: None,
language_specific: None,
purity_reason: None,
call_dependencies: None,
purity_level: None,
error_swallowing_count: None,
error_swallowing_patterns: None,
entropy_analysis: None,
};
let score_cyclo = calc.calculate_score(&metrics_cyclo_only);
assert_eq!(
score_cyclo, 50,
"Only cyclomatic at threshold should give 50"
);
let metrics_cognitive_only = FunctionMetrics {
name: "cognitive".to_string(),
file: PathBuf::from("test.rs"),
line: 1,
cyclomatic: 0,
cognitive: 10,
nesting: 0,
length: 0,
is_test: false,
visibility: None,
is_trait_method: false,
in_test_module: false,
entropy_score: None,
is_pure: None,
purity_confidence: None,
detected_patterns: None,
upstream_callers: None,
downstream_callees: None,
mapping_pattern_result: None,
adjusted_complexity: None,
composition_metrics: None,
language_specific: None,
purity_reason: None,
call_dependencies: None,
purity_level: None,
error_swallowing_count: None,
error_swallowing_patterns: None,
entropy_analysis: None,
};
let score_cognitive = calc.calculate_score(&metrics_cognitive_only);
assert_eq!(
score_cognitive, 50,
"Only cognitive at threshold should give 50"
);
}
#[test]
fn test_complexity_integration() {
let branch1 = 5;
let branch2 = 3;
let combined = combine_complexity(branch1, branch2);
let all_complexities = vec![branch1, branch2, combined];
let max = max_complexity(&all_complexities);
assert_eq!(combined, 8);
assert_eq!(max, 8);
let avg = average_complexity(&all_complexities);
assert_eq!(avg, 16.0 / 3.0);
}