#[cfg(test)]
mod priority_tests {
use std::collections::HashMap;
use std::fs;
use tempfile::tempdir;
use yek::priority::{
compute_recentness_boost, get_file_priority, get_recent_commit_times_git2, PriorityRule,
};
#[test]
fn test_get_file_priority_multiple_matches() {
let rules = vec![
PriorityRule {
pattern: r"src/.*".to_string(),
score: 5,
},
PriorityRule {
pattern: r".*\.rs".to_string(),
score: 10,
},
];
assert_eq!(get_file_priority("src/main.rs", &rules), 15);
}
#[test]
fn test_compute_recentness_boost_empty() {
let commit_times = HashMap::new();
let boosts = compute_recentness_boost(&commit_times, 100);
assert!(boosts.is_empty());
}
#[test]
fn test_compute_recentness_boost_single() {
let mut commit_times = HashMap::new();
commit_times.insert("file.rs".to_string(), 12345);
let boosts = compute_recentness_boost(&commit_times, 100);
assert_eq!(boosts.get("file.rs"), Some(&0));
}
#[test]
fn test_compute_recentness_boost_multiple() {
let mut commit_times = HashMap::new();
commit_times.insert("old.rs".to_string(), 10000);
commit_times.insert("mid.rs".to_string(), 20000);
commit_times.insert("new.rs".to_string(), 30000);
let boosts = compute_recentness_boost(&commit_times, 100);
assert_eq!(boosts.get("old.rs"), Some(&0));
assert_eq!(boosts.get("mid.rs"), Some(&50));
assert_eq!(boosts.get("new.rs"), Some(&100));
}
#[test]
fn test_get_file_priority_no_rules() {
let path = "src/main.rs";
let rules = vec![];
let priority = get_file_priority(path, &rules);
assert_eq!(priority, 0);
}
#[test]
fn test_get_file_priority_with_rules() {
let path = "src/main.rs";
let rules = vec![
PriorityRule {
pattern: r"src/.*\.rs".to_string(),
score: 10,
},
PriorityRule {
pattern: r".*\.md".to_string(),
score: 5,
},
];
let priority = get_file_priority(path, &rules);
assert_eq!(priority, 10);
}
#[test]
fn test_get_file_priority_with_rules_no_match() {
let path = "docs/README.txt";
let rules = vec![
PriorityRule {
pattern: r"src/.*\.rs".to_string(),
score: 10,
},
PriorityRule {
pattern: r".*\.md".to_string(),
score: 5,
},
];
let priority = get_file_priority(path, &rules);
assert_eq!(priority, 0);
}
#[test]
fn test_get_file_priority_invalid_regex() {
let path = "src/main.rs";
let rules = vec![PriorityRule {
pattern: r"src/.*\.rs".to_string(),
score: 10,
}];
let priority = get_file_priority(path, &rules);
assert_eq!(priority, 10);
let rules = vec![PriorityRule {
pattern: r"src/[[.*\.rs".to_string(), score: 10,
}];
let priority = get_file_priority(path, &rules);
assert_eq!(priority, 0); }
#[test]
fn test_compute_recentness_boost_single_file() {
let mut commit_times = HashMap::new();
commit_times.insert("file1.txt".to_string(), 1234567890);
let max_boost = 100;
let boosts = compute_recentness_boost(&commit_times, max_boost);
assert_eq!(boosts.len(), 1);
assert_eq!(boosts["file1.txt"], 0); }
#[test]
fn test_compute_recentness_boost_multiple_files() {
let mut commit_times = HashMap::new();
commit_times.insert("file1.txt".to_string(), 1234567890);
commit_times.insert("file2.txt".to_string(), 1234567891);
commit_times.insert("file3.txt".to_string(), 1234567892);
let max_boost = 100;
let boosts = compute_recentness_boost(&commit_times, max_boost);
assert_eq!(boosts.len(), 3);
assert_eq!(boosts["file1.txt"], 0); assert_eq!(boosts["file2.txt"], 50); assert_eq!(boosts["file3.txt"], 100); }
#[test]
fn test_compute_recentness_boost_unsorted_input() {
let mut commit_times = HashMap::new();
commit_times.insert("file3.txt".to_string(), 1234567892);
commit_times.insert("file1.txt".to_string(), 1234567890);
commit_times.insert("file2.txt".to_string(), 1234567891);
let max_boost = 100;
let boosts = compute_recentness_boost(&commit_times, max_boost);
assert_eq!(boosts.len(), 3);
assert_eq!(boosts["file1.txt"], 0); assert_eq!(boosts["file2.txt"], 50); assert_eq!(boosts["file3.txt"], 100); }
#[test]
fn test_compute_recentness_boost_max_boost() {
let mut commit_times = HashMap::new();
commit_times.insert("file1.txt".to_string(), 1234567890);
commit_times.insert("file2.txt".to_string(), 1234567891);
let max_boost = 50;
let boosts = compute_recentness_boost(&commit_times, max_boost);
assert_eq!(boosts["file1.txt"], 0); assert_eq!(boosts["file2.txt"], 50); }
#[test]
fn test_get_recent_commit_times_no_git() {
let dir = tempdir().unwrap();
let times = get_recent_commit_times_git2(dir.path(), 100);
assert!(times.is_none());
}
#[test]
fn test_get_recent_commit_times_with_git() {
let dir = tempdir().unwrap();
let repo_path = dir.path();
std::process::Command::new("git")
.args(["init"])
.current_dir(repo_path)
.output()
.unwrap();
std::process::Command::new("git")
.args(["config", "user.name", "Test User"])
.current_dir(repo_path)
.output()
.unwrap();
std::process::Command::new("git")
.args(["config", "user.email", "test@example.com"])
.current_dir(repo_path)
.output()
.unwrap();
fs::write(repo_path.join("file1.txt"), "content1").unwrap();
std::process::Command::new("git")
.args(["add", "file1.txt"])
.current_dir(repo_path)
.output()
.unwrap();
std::process::Command::new("git")
.args(["commit", "-m", "Initial commit"])
.current_dir(repo_path)
.output()
.unwrap();
fs::write(repo_path.join("file2.txt"), "content2").unwrap();
std::process::Command::new("git")
.args(["add", "file2.txt"])
.current_dir(repo_path)
.output()
.unwrap();
std::process::Command::new("git")
.args(["commit", "-m", "Add file2"])
.current_dir(repo_path)
.output()
.unwrap();
let times = get_recent_commit_times_git2(repo_path, 100).unwrap();
assert_eq!(times.len(), 2);
assert!(times.contains_key("file1.txt"));
assert!(times.contains_key("file2.txt"));
}
#[test]
fn test_get_recent_commit_times_empty_repo() {
let dir = tempdir().unwrap();
let repo_path = dir.path();
std::process::Command::new("git")
.args(["init"])
.current_dir(repo_path)
.output()
.unwrap();
let times = get_recent_commit_times_git2(repo_path, 100);
assert!(times.is_none(), "Expected no times for empty repo");
}
#[test]
fn test_get_recent_commit_times_git_failure() {
let dir = tempdir().unwrap();
let repo_path = dir.path();
std::process::Command::new("git")
.args(["init"])
.current_dir(repo_path)
.output()
.unwrap();
fs::remove_dir_all(repo_path.join(".git")).unwrap();
fs::create_dir(repo_path.join(".git")).unwrap();
let times = get_recent_commit_times_git2(repo_path, 100);
assert!(times.is_none(), "Expected no times on Git failure");
}
#[test]
fn test_empty_priority_rules() {
let rules = vec![];
assert_eq!(get_file_priority("src/main.rs", &rules), 0);
}
#[test]
fn test_single_priority_rule() {
let rules = vec![PriorityRule {
pattern: String::from(".*\\.rs$"),
score: 100,
}];
assert_eq!(get_file_priority("src/main.rs", &rules), 100);
assert_eq!(get_file_priority("README.md", &rules), 0);
}
#[test]
fn test_multiple_priority_rules() {
let rules = vec![
PriorityRule {
pattern: String::from(".*\\.rs$"),
score: 100,
},
PriorityRule {
pattern: String::from("^src/.*"),
score: 50,
},
];
assert_eq!(get_file_priority("src/main.rs", &rules), 150);
assert_eq!(get_file_priority("tests/main.rs", &rules), 100);
assert_eq!(get_file_priority("README.md", &rules), 0);
}
#[test]
fn test_invalid_regex_pattern() {
let rules = vec![PriorityRule {
pattern: String::from("[invalid regex"),
score: 100,
}];
assert_eq!(get_file_priority("any_file.txt", &rules), 0);
}
#[test]
fn test_recentness_boost_empty() {
let commit_times = HashMap::new();
let boosts = compute_recentness_boost(&commit_times, 100);
assert!(boosts.is_empty());
}
#[test]
fn test_recentness_boost_single_file() {
let mut commit_times = HashMap::new();
commit_times.insert("file.rs".to_string(), 1000);
let boosts = compute_recentness_boost(&commit_times, 100);
assert_eq!(boosts["file.rs"], 0);
}
#[test]
fn test_recentness_boost_evenly_spaced() {
let mut commit_times = HashMap::new();
commit_times.insert("oldest.rs".to_string(), 1000);
commit_times.insert("middle.rs".to_string(), 2000);
commit_times.insert("newest.rs".to_string(), 3000);
let max_boost = 100;
let boosts = compute_recentness_boost(&commit_times, max_boost);
assert_eq!(boosts["oldest.rs"], 0);
assert_eq!(boosts["newest.rs"], max_boost);
assert!(boosts["middle.rs"] >= 45 && boosts["middle.rs"] <= 55);
}
#[test]
fn test_recentness_boost_same_time() {
let mut commit_times = HashMap::new();
commit_times.insert("file1.rs".to_string(), 1000);
commit_times.insert("file2.rs".to_string(), 1000);
let boosts = compute_recentness_boost(&commit_times, 100);
assert_eq!(boosts["file1.rs"], boosts["file2.rs"]);
}
#[test]
fn test_get_recent_commit_times_git_max_depth() {
let dir = tempdir().unwrap();
let repo_path = dir.path();
std::process::Command::new("git")
.args(["init"])
.current_dir(repo_path)
.output()
.unwrap();
std::process::Command::new("git")
.args(["config", "user.name", "Test User"])
.current_dir(repo_path)
.output()
.unwrap();
std::process::Command::new("git")
.args(["config", "user.email", "test@example.com"])
.current_dir(repo_path)
.output()
.unwrap();
fs::create_dir(repo_path.join("subdir")).unwrap();
fs::write(repo_path.join("subdir").join("file.txt"), "content").unwrap();
std::process::Command::new("git")
.args(["add", "."])
.current_dir(repo_path)
.output()
.unwrap();
std::process::Command::new("git")
.args(["commit", "-m", "Initial commit"])
.current_dir(repo_path)
.output()
.unwrap();
let times = get_recent_commit_times_git2(repo_path, 1).unwrap();
assert!(!times.is_empty());
}
#[test]
fn test_get_recent_commit_times_git_tree_walk_error() {
let dir = tempdir().unwrap();
let repo_path = dir.path();
std::process::Command::new("git")
.args(["init"])
.current_dir(repo_path)
.output()
.unwrap();
std::process::Command::new("git")
.args(["config", "user.name", "Test User"])
.current_dir(repo_path)
.output()
.unwrap();
std::process::Command::new("git")
.args(["config", "user.email", "test@example.com"])
.current_dir(repo_path)
.output()
.unwrap();
fs::write(repo_path.join("file.txt"), "content").unwrap();
std::process::Command::new("git")
.args(["add", "file.txt"])
.current_dir(repo_path)
.output()
.unwrap();
std::process::Command::new("git")
.args(["commit", "-m", "Initial commit"])
.current_dir(repo_path)
.output()
.unwrap();
let times = get_recent_commit_times_git2(repo_path, 100).unwrap();
assert!(times.contains_key("file.txt"));
}
#[test]
fn test_get_recent_commit_times_git_revwalk_error() {
let dir = tempdir().unwrap();
let repo_path = dir.path();
std::process::Command::new("git")
.args(["init"])
.current_dir(repo_path)
.output()
.unwrap();
let times = get_recent_commit_times_git2(repo_path, 100);
assert!(times.is_none());
}
#[test]
fn test_compute_recentness_boost_large_time_range() {
let mut commit_times = HashMap::new();
commit_times.insert("old.rs".to_string(), 1000000000); commit_times.insert("new.rs".to_string(), 1670000000);
let boosts = compute_recentness_boost(&commit_times, 100);
assert_eq!(boosts["old.rs"], 0);
assert_eq!(boosts["new.rs"], 100);
}
#[test]
fn test_get_file_priority_regex_compilation_failure() {
let rules = vec![PriorityRule {
pattern: r"[invalid".to_string(), score: 10,
}];
assert_eq!(get_file_priority("test.rs", &rules), 0);
}
#[test]
fn test_get_recent_commit_times_git_no_head() {
let dir = tempdir().unwrap();
let repo_path = dir.path();
std::process::Command::new("git")
.args(["init", "--bare"])
.current_dir(repo_path)
.output()
.unwrap();
let times = get_recent_commit_times_git2(repo_path, 100);
assert!(times.is_none());
}
#[test]
fn test_get_recent_commit_times_git_corrupted_objects() {
let dir = tempdir().unwrap();
let repo_path = dir.path();
std::process::Command::new("git")
.args(["init"])
.current_dir(repo_path)
.output()
.unwrap();
std::process::Command::new("git")
.args(["config", "user.name", "Test User"])
.current_dir(repo_path)
.output()
.unwrap();
std::process::Command::new("git")
.args(["config", "user.email", "test@example.com"])
.current_dir(repo_path)
.output()
.unwrap();
fs::write(repo_path.join("file1.txt"), "content1").unwrap();
std::process::Command::new("git")
.args(["add", "file1.txt"])
.current_dir(repo_path)
.output()
.unwrap();
std::process::Command::new("git")
.args(["commit", "-m", "Initial commit"])
.current_dir(repo_path)
.output()
.unwrap();
let objects_dir = repo_path.join(".git").join("objects");
if objects_dir.exists() {
for entry in fs::read_dir(&objects_dir).unwrap().flatten() {
if entry.path().is_dir() {
fs::remove_dir_all(entry.path()).ok();
break; }
}
}
let _times = get_recent_commit_times_git2(repo_path, 100);
}
}
#[test]
fn test_get_recent_commit_times_git_with_corrupted_head() {
use std::fs;
use tempfile::tempdir;
use yek::priority::get_recent_commit_times_git2;
let dir = tempdir().unwrap();
let repo_path = dir.path();
std::process::Command::new("git")
.args(["init"])
.current_dir(repo_path)
.output()
.unwrap();
let head_file = repo_path.join(".git").join("HEAD");
fs::write(&head_file, "corrupted content").unwrap();
let times = get_recent_commit_times_git2(repo_path, 100);
assert!(times.is_none());
}
#[test]
fn test_get_recent_commit_times_git_with_invalid_repo_structure() {
use std::fs;
use tempfile::tempdir;
use yek::priority::get_recent_commit_times_git2;
let dir = tempdir().unwrap();
let repo_path = dir.path();
fs::create_dir(repo_path.join(".git")).unwrap();
fs::write(repo_path.join(".git").join("config"), "[core]\n").unwrap();
let times = get_recent_commit_times_git2(repo_path, 100);
assert!(times.is_none());
}
#[test]
fn test_get_recent_commit_times_git_with_detached_head() {
use std::fs;
use tempfile::tempdir;
use yek::priority::get_recent_commit_times_git2;
let dir = tempdir().unwrap();
let repo_path = dir.path();
std::process::Command::new("git")
.args(["init"])
.current_dir(repo_path)
.output()
.unwrap();
std::process::Command::new("git")
.args(["config", "user.name", "Test User"])
.current_dir(repo_path)
.output()
.unwrap();
std::process::Command::new("git")
.args(["config", "user.email", "test@example.com"])
.current_dir(repo_path)
.output()
.unwrap();
fs::write(repo_path.join("file.txt"), "content").unwrap();
std::process::Command::new("git")
.args(["add", "file.txt"])
.current_dir(repo_path)
.output()
.unwrap();
std::process::Command::new("git")
.args(["commit", "-m", "Initial commit"])
.current_dir(repo_path)
.output()
.unwrap();
let output = std::process::Command::new("git")
.args(["rev-parse", "HEAD"])
.current_dir(repo_path)
.output()
.unwrap();
let commit_hash = String::from_utf8_lossy(&output.stdout).trim().to_string();
std::process::Command::new("git")
.args(["checkout", &commit_hash])
.current_dir(repo_path)
.output()
.unwrap();
let times = get_recent_commit_times_git2(repo_path, 100);
assert!(times.is_some());
assert!(times.unwrap().contains_key("file.txt"));
}
#[test]
fn test_get_recent_commit_times_git_with_shallow_clone() {
use std::fs;
use tempfile::tempdir;
use yek::priority::get_recent_commit_times_git2;
let dir = tempdir().unwrap();
let repo_path = dir.path();
std::process::Command::new("git")
.args(["init"])
.current_dir(repo_path)
.output()
.unwrap();
std::process::Command::new("git")
.args(["config", "user.name", "Test User"])
.current_dir(repo_path)
.output()
.unwrap();
std::process::Command::new("git")
.args(["config", "user.email", "test@example.com"])
.current_dir(repo_path)
.output()
.unwrap();
for i in 1..=5 {
let filename = format!("file{}.txt", i);
fs::write(repo_path.join(&filename), format!("content{}", i)).unwrap();
std::process::Command::new("git")
.args(["add", &filename])
.current_dir(repo_path)
.output()
.unwrap();
std::process::Command::new("git")
.args(["commit", "-m", &format!("Commit {}", i)])
.current_dir(repo_path)
.output()
.unwrap();
}
let times = get_recent_commit_times_git2(repo_path, 2);
assert!(times.is_some());
let times = times.unwrap();
assert!(!times.is_empty());
}
#[test]
fn test_get_recent_commit_times_git_with_submodules() {
use std::fs;
use tempfile::tempdir;
use yek::priority::get_recent_commit_times_git2;
let dir = tempdir().unwrap();
let repo_path = dir.path();
std::process::Command::new("git")
.args(["init"])
.current_dir(repo_path)
.output()
.unwrap();
fs::write(
repo_path.join(".gitmodules"),
"[submodule \"sub\"]\n\tpath = sub\n\turl = ./sub\n",
)
.unwrap();
let times = get_recent_commit_times_git2(repo_path, 100);
assert!(times.is_none() || times.unwrap().is_empty());
}