use debtmap::*;
use std::path::PathBuf;
#[test]
fn test_code_smell_long_parameter_list() {
let func = FunctionMetrics {
name: "test_function".to_string(),
file: PathBuf::from("test.rs"),
line: 10,
cyclomatic: 5,
cognitive: 8,
nesting: 2,
length: 30,
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 smell = detect_long_parameter_list(&func, 7);
assert!(smell.is_some(), "Should detect long parameter list");
let smell = smell.unwrap();
assert_eq!(smell.smell_type, SmellType::LongParameterList);
assert_eq!(smell.severity, Priority::Medium);
let no_smell = detect_long_parameter_list(&func, 3);
assert!(
no_smell.is_none(),
"Should not detect smell for short parameter list"
);
}
#[test]
fn test_code_smell_long_method() {
let mut func = FunctionMetrics {
name: "test_function".to_string(),
file: PathBuf::from("test.rs"),
line: 10,
cyclomatic: 5,
cognitive: 8,
nesting: 2,
length: 100, 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 smell = detect_long_method(&func);
assert!(smell.is_some(), "Should detect long method");
let smell = smell.unwrap();
assert_eq!(smell.smell_type, SmellType::LongMethod);
assert_eq!(smell.severity, Priority::Medium);
func.length = 30;
let no_smell = detect_long_method(&func);
assert!(
no_smell.is_none(),
"Should not detect smell for short method"
);
}
#[test]
fn test_code_smell_deep_nesting() {
let mut func = FunctionMetrics {
name: "test_function".to_string(),
file: PathBuf::from("test.rs"),
line: 10,
cyclomatic: 5,
cognitive: 8,
nesting: 6, length: 30,
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 smell = detect_deep_nesting(&func);
assert!(smell.is_some(), "Should detect deep nesting");
let smell = smell.unwrap();
assert_eq!(smell.smell_type, SmellType::DeepNesting);
assert_eq!(smell.severity, Priority::Medium);
func.nesting = 2;
let no_smell = detect_deep_nesting(&func);
assert!(
no_smell.is_none(),
"Should not detect smell for shallow nesting"
);
}
#[test]
fn test_code_smell_detection_multiple() {
let func = FunctionMetrics {
name: "bad_function".to_string(),
file: PathBuf::from("test.rs"),
line: 10,
cyclomatic: 15,
cognitive: 20,
nesting: 6,
length: 100,
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 smells = analyze_function_smells(&func, 7);
assert!(smells.len() >= 3, "Should detect multiple code smells");
let has_long_params = smells
.iter()
.any(|s| matches!(s.smell_type, SmellType::LongParameterList));
let has_long_method = smells
.iter()
.any(|s| matches!(s.smell_type, SmellType::LongMethod));
let has_deep_nesting = smells
.iter()
.any(|s| matches!(s.smell_type, SmellType::DeepNesting));
assert!(has_long_params, "Should detect long parameter list");
assert!(has_long_method, "Should detect long method");
assert!(has_deep_nesting, "Should detect deep nesting");
}
#[test]
fn test_module_smell_detection() {
let path = PathBuf::from("large_module.rs");
let smells = analyze_module_smells(&path, 500);
assert!(!smells.is_empty(), "Should detect large module");
let smell = &smells[0];
assert_eq!(smell.smell_type, SmellType::LargeClass);
assert_eq!(smell.severity, Priority::Medium);
let no_smells = analyze_module_smells(&path, 200);
assert!(
no_smells.is_empty(),
"Should not detect smell for normal size module"
);
}
#[test]
fn test_code_smell_to_debt_item() {
let smell = CodeSmell {
smell_type: SmellType::LongMethod,
location: PathBuf::from("test.rs"),
line: 100,
message: "Method is too long".to_string(),
severity: Priority::High,
};
let debt_item = smell.to_debt_item();
assert!(matches!(debt_item.debt_type, DebtType::CodeSmell { .. }));
assert_eq!(debt_item.priority, Priority::High);
assert_eq!(debt_item.line, 100);
assert_eq!(debt_item.message, "Method is too long");
}
#[test]
fn test_code_smell_suppression() {
let content = r#"
// debtmap:ignore-next-line[codesmell]
// This is a very long line that would normally trigger a code smell
// This is a normal line
"#;
let path = PathBuf::from("test.rs");
let items = find_code_smells_with_suppression(
content,
&path,
Some(&parse_suppression_comments(content, Language::Rust, &path)),
);
assert_eq!(items.len(), 0, "Long line should be suppressed");
}