test: Add unit tests for index building and scanning functionality (#9)

This commit is contained in:
Eli Peter 2025-06-24 23:57:27 +02:00 committed by GitHub
parent 46c4732f6e
commit 72ca7fa45d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 92 additions and 0 deletions

View file

@ -129,3 +129,30 @@ pub fn build_index(
Ok(())
}
#[test]
fn build_index_creates_db_and_registers_files() {
let mut cfg = Config::default();
cfg.performance.worker_threads = Some(1);
cfg.performance.channel_multiplier = 1;
cfg.performance.batch_size = 2;
let td = tempfile::tempdir().unwrap();
let project_dir = td.path().join("proj");
fs::create_dir(&project_dir).unwrap();
let f_txt = project_dir.join("readme.txt");
fs::write(&f_txt, "hello").unwrap();
let db_path = td.path().join("proj.sqlite");
build_index("proj", &project_dir, &db_path, &cfg).expect("index build should succeed");
// ── Assert ────────────────────────────────────────────────────────────────
assert!(db_path.is_file(), "SQLite file must exist");
let pool = Indexer::init(&db_path).unwrap();
let idx = Indexer::from_pool("proj", &pool).unwrap();
let files = idx.get_files("proj").unwrap();
assert_eq!(files.len(), 1, "exactly one file indexed");
assert_eq!(files[0], f_txt);
}

View file

@ -165,3 +165,35 @@ pub fn scan_with_index_parallel(
Ok(diags)
}
#[test]
fn scan_with_index_parallel_uses_existing_index_without_rescanning() {
let mut cfg = Config::default();
cfg.performance.worker_threads = Some(1);
cfg.performance.channel_multiplier = 1;
cfg.performance.batch_size = 2;
let td = tempfile::tempdir().unwrap();
let project_dir = td.path().join("proj");
std::fs::create_dir(&project_dir).unwrap();
std::fs::write(project_dir.join("foo.txt"), "abc").unwrap();
let (project_name, db_path) = get_project_info(&project_dir, td.path()).unwrap();
crate::commands::index::build_index(&project_name, &project_dir, &db_path, &cfg).unwrap();
let pool = Indexer::init(&db_path).unwrap();
assert_eq!(
Indexer::from_pool(&project_name, &pool)
.unwrap()
.get_files(&project_name)
.unwrap()
.len(),
1
);
let diags = scan_with_index_parallel(&project_name, Arc::clone(&pool), &cfg)
.expect("scan should succeed");
assert!(diags.is_empty());
}

View file

@ -60,6 +60,7 @@ impl FromStr for Severity {
/// One AST pattern with a tree-sitter query and meta-data.
#[derive(Debug, Clone, Serialize)]
#[derive(PartialEq)]
pub struct Pattern {
/// Unique identifier (snake-case preferred).
pub id: &'static str,
@ -113,3 +114,35 @@ pub fn load(lang: &str) -> Vec<Pattern> {
let key = lang.to_ascii_lowercase();
REGISTRY.get(key.as_str()).copied().unwrap_or(&[]).to_vec()
}
#[test]
fn severity_as_db_str_roundtrip() {
for &s in &[Severity::High, Severity::Medium, Severity::Low] {
let db = s.as_db_str();
assert!(matches!(db, "HIGH" | "MEDIUM" | "LOW"));
assert_eq!(db.parse::<Severity>().unwrap(), s);
assert_eq!(db.to_lowercase().parse::<Severity>().unwrap(), s);
}
}
#[test]
fn severity_display_contains_uppercase_name() {
assert!(Severity::High.to_string().contains("HIGH"));
assert!(Severity::Medium.to_string().contains("MEDIUM"));
assert!(Severity::Low.to_string().contains("LOW"));
}
#[test]
fn load_returns_correct_pattern_slices() {
let rust = load("rust");
assert!(!rust.is_empty(), "Rust patterns should be loaded");
let ts = load("typescript");
let tsx = load("tsx");
assert_eq!(ts, tsx, "alias tsx must map to TypeScript patterns");
assert_eq!(load("RUST"), rust);
assert!(load("brainfuck").is_empty());
}