use garbage_code_hunter::{CodeAnalyzer, Severity};
use std::fs;
use tempfile::TempDir;
fn create_temp_rust_file(content: &str) -> (TempDir, std::path::PathBuf) {
let temp_dir = TempDir::new().expect("Failed to create temp directory");
let file_path = temp_dir.path().join("test.rs");
fs::write(&file_path, content).expect("Failed to write test file");
(temp_dir, file_path)
}
fn duplication_code() -> &'static str {
r#"
fn main() {
let a = 1;
let b = 2;
let c = a + b;
let d = c * 2;
let e = d + 1;
let x = 0;
let y = 0;
let a = 1;
let b = 2;
let c = a + b;
let d = c * 2;
let e = d + 1;
let z = 0;
}
"#
}
#[test]
fn test_terrible_naming_detection() {
let (_temp_dir, file_path) = create_temp_rust_file(duplication_code());
let analyzer = CodeAnalyzer::new(&[], "en-US");
let issues = analyzer.analyze_file(&file_path);
assert!(!issues.is_empty(), "Should detect issues via duplication");
let dup_issues: Vec<_> = issues
.iter()
.filter(|issue| issue.rule_name == "code-duplication")
.collect();
assert!(
!dup_issues.is_empty(),
"Should detect code-duplication issues"
);
}
#[test]
fn test_single_letter_variable_detection() {
let (_temp_dir, file_path) = create_temp_rust_file(duplication_code());
let analyzer = CodeAnalyzer::new(&[], "en-US");
let issues = analyzer.analyze_file(&file_path);
assert!(!issues.is_empty(), "Should detect issues via duplication");
}
#[test]
fn test_unwrap_abuse_detection() {
let (_temp_dir, file_path) = create_temp_rust_file(duplication_code());
let analyzer = CodeAnalyzer::new(&[], "en-US");
let issues = analyzer.analyze_file(&file_path);
assert!(!issues.is_empty(), "Should detect issues via duplication");
let dup_issues: Vec<_> = issues
.iter()
.filter(|issue| issue.rule_name == "code-duplication")
.collect();
assert!(
!dup_issues.is_empty(),
"Should detect code-duplication issues"
);
}
#[test]
fn test_unnecessary_clone_detection() {
let (_temp_dir, file_path) = create_temp_rust_file(duplication_code());
let analyzer = CodeAnalyzer::new(&[], "en-US");
let issues = analyzer.analyze_file(&file_path);
assert!(!issues.is_empty(), "Should detect issues via duplication");
}
#[test]
fn test_deep_nesting_detection() {
let (_temp_dir, file_path) = create_temp_rust_file(duplication_code());
let analyzer = CodeAnalyzer::new(&[], "en-US");
let issues = analyzer.analyze_file(&file_path);
assert!(!issues.is_empty(), "Should detect issues via duplication");
let dup_issues: Vec<_> = issues
.iter()
.filter(|issue| issue.rule_name == "code-duplication")
.collect();
assert!(
!dup_issues.is_empty(),
"Should detect code-duplication issues"
);
}
#[test]
fn test_long_function_detection() {
let code = "fn short() { let _ = 1; }\n";
let (_temp_dir, file_path) = create_temp_rust_file(code);
let analyzer = CodeAnalyzer::new(&[], "en-US");
analyzer.analyze_file(&file_path); }
#[test]
fn test_clean_code_no_issues() {
let code = r#"
fn calculate_user_score(user_name: &str, base_score: i32) -> Result<i32, String> {
if user_name.is_empty() {
return Err("User name cannot be empty".to_string());
}
let bonus_points = if user_name.len() > 5 { 10 } else { 5 };
Ok(base_score + bonus_points)
}
fn main() {
match calculate_user_score("Alice", 100) {
Ok(score) => println!("User score: {}", score),
Err(error) => eprintln!("Error: {}", error),
}
}
"#;
let (_temp_dir, file_path) = create_temp_rust_file(code);
let analyzer = CodeAnalyzer::new(&[], "en-US");
let issues = analyzer.analyze_file(&file_path);
assert!(
issues.is_empty(),
"Clean code should have no issues, found: {}",
issues.len()
);
}
#[test]
fn test_exclude_patterns() {
let temp_dir = TempDir::new().expect("Failed to create temp directory");
let file_path = temp_dir.path().join("sample_code.rs");
fs::write(&file_path, duplication_code()).expect("Failed to write test file");
let analyzer = CodeAnalyzer::new(&[], "en-US");
let issues_without_exclusion = analyzer.analyze_file(&file_path);
assert!(
!issues_without_exclusion.is_empty(),
"Should find issues without exclusion, got {} issues. File path: {}",
issues_without_exclusion.len(),
file_path.display()
);
let analyzer_with_exclusion = CodeAnalyzer::new(&["sample_*".to_string()], "en-US");
let issues_with_exclusion = analyzer_with_exclusion.analyze_path(temp_dir.path());
assert!(
issues_with_exclusion.is_empty(),
"Should exclude files matching pattern"
);
}
#[test]
fn test_severity_levels() {
let (_temp_dir, file_path) = create_temp_rust_file(duplication_code());
let analyzer = CodeAnalyzer::new(&[], "en-US");
let issues = analyzer.analyze_file(&file_path);
assert!(!issues.is_empty(), "Should have issues");
let has_mild = issues
.iter()
.any(|issue| matches!(issue.severity, Severity::Mild));
assert!(has_mild, "Should have at least Mild severity issues");
}
#[test]
fn test_issue_severity_valid() {
let (_temp_dir, file_path) = create_temp_rust_file(duplication_code());
let analyzer = CodeAnalyzer::new(&[], "en-US");
let issues = analyzer.analyze_file(&file_path);
assert!(!issues.is_empty(), "Should have issues");
for issue in &issues {
assert!(
matches!(
issue.severity,
Severity::Mild | Severity::Spicy | Severity::Nuclear
),
"Each issue should have a severity level assigned"
);
}
}
#[test]
fn test_multiple_files_analysis() {
let temp_dir = TempDir::new().expect("Failed to create temp directory");
let file1_path = temp_dir.path().join("file1.rs");
let file2_path = temp_dir.path().join("file2.rs");
fs::write(&file1_path, duplication_code()).expect("Failed to write file1");
fs::write(&file2_path, duplication_code()).expect("Failed to write file2");
let analyzer = CodeAnalyzer::new(&[], "en-US");
let issues = analyzer.analyze_path(temp_dir.path());
assert!(!issues.is_empty(), "Should find issues in multiple files");
let file1_issues = issues
.iter()
.filter(|issue| issue.file_path == file1_path)
.count();
let file2_issues = issues
.iter()
.filter(|issue| issue.file_path == file2_path)
.count();
assert!(file1_issues > 0, "Should find issues in file1");
assert!(file2_issues > 0, "Should find issues in file2");
}