#![allow(dead_code)]
use reflex::{
CacheManager, IndexConfig, Indexer, QueryEngine, QueryFilter, SearchResult, SymbolKind,
};
use std::path::{Path, PathBuf};
use std::sync::OnceLock;
static CORPUS_PATH: OnceLock<PathBuf> = OnceLock::new();
pub fn setup_corpus() -> &'static Path {
CORPUS_PATH
.get_or_init(|| {
let corpus = PathBuf::from("tests/corpus");
let cache = CacheManager::new(&corpus);
let indexer = Indexer::new(cache, IndexConfig::default());
indexer
.index(&corpus, false)
.expect("Failed to index corpus");
corpus
})
.as_path()
}
pub fn query_engine() -> QueryEngine {
let corpus = setup_corpus();
let cache = CacheManager::new(corpus);
QueryEngine::new(cache)
}
pub fn query_corpus(pattern: &str, filter: QueryFilter) -> Vec<SearchResult> {
query_engine()
.search(pattern, filter)
.expect("Query failed")
}
pub fn assert_symbol_found(results: &[SearchResult], name: &str, kind: SymbolKind) {
assert!(
results
.iter()
.any(|r| { r.symbol.as_deref() == Some(name) && r.kind == kind }),
"Expected to find symbol '{}' of kind {:?}, but it was not in results",
name,
kind
);
}
pub fn assert_file_match(results: &[SearchResult], path_contains: &str) {
assert!(
results.iter().any(|r| r.path.contains(path_contains)),
"Expected to find result in file containing '{}', but no match found",
path_contains
);
}
pub fn assert_result_count(results: &[SearchResult], expected: usize) {
assert_eq!(
results.len(),
expected,
"Expected {} results, but got {}",
expected,
results.len()
);
}
pub fn assert_result_count_at_least(results: &[SearchResult], min: usize) {
assert!(
results.len() >= min,
"Expected at least {} results, but got {}",
min,
results.len()
);
}
pub fn assert_result_count_at_most(results: &[SearchResult], max: usize) {
assert!(
results.len() <= max,
"Expected at most {} results, but got {}",
max,
results.len()
);
}
pub fn assert_all_kind(results: &[SearchResult], kind: SymbolKind) {
for result in results {
assert_eq!(
result.kind, kind,
"Expected all results to be {:?}, but found {:?}",
kind, result.kind
);
}
}
pub fn assert_all_language(results: &[SearchResult], lang: reflex::Language) {
for result in results {
assert_eq!(
result.lang, lang,
"Expected all results from {:?}, but found {:?}",
lang, result.lang
);
}
}
pub fn assert_sorted(results: &[SearchResult]) {
for i in 0..results.len().saturating_sub(1) {
let curr = &results[i];
let next = &results[i + 1];
assert!(
curr.path < next.path
|| (curr.path == next.path && curr.span.start_line <= next.span.start_line),
"Results are not sorted correctly at index {}",
i
);
}
}
pub fn assert_preview_contains(results: &[SearchResult], pattern: &str) {
assert!(
results.iter().any(|r| r.preview.contains(pattern)),
"Expected at least one preview to contain '{}'",
pattern
);
}
pub fn count_by_kind(results: &[SearchResult], kind: SymbolKind) -> usize {
results.iter().filter(|r| r.kind == kind).count()
}
pub fn count_by_file_pattern(results: &[SearchResult], pattern: &str) -> usize {
results.iter().filter(|r| r.path.contains(pattern)).count()
}
pub fn unique_files(results: &[SearchResult]) -> Vec<String> {
use std::collections::HashSet;
let mut files: HashSet<String> = results.iter().map(|r| r.path.clone()).collect();
let mut vec: Vec<String> = files.drain().collect();
vec.sort();
vec
}
pub fn assert_no_duplicates(results: &[SearchResult]) {
use std::collections::HashSet;
let mut seen = HashSet::new();
for result in results {
let key = (result.path.clone(), result.span.start_line);
assert!(
seen.insert(key.clone()),
"Duplicate result found: {:?}",
key
);
}
}
pub fn assert_all_match_glob(results: &[SearchResult], patterns: &[String]) {
use globset::{Glob, GlobSetBuilder};
let mut builder = GlobSetBuilder::new();
for pattern in patterns {
builder.add(Glob::new(pattern).unwrap());
}
let matcher = builder.build().unwrap();
for result in results {
assert!(
matcher.is_match(&result.path),
"Result path '{}' does not match any glob pattern: {:?}",
result.path,
patterns
);
}
}
pub fn assert_none_match_exclude(results: &[SearchResult], patterns: &[String]) {
use globset::{Glob, GlobSetBuilder};
let mut builder = GlobSetBuilder::new();
for pattern in patterns {
builder.add(Glob::new(pattern).unwrap());
}
let matcher = builder.build().unwrap();
for result in results {
assert!(
!matcher.is_match(&result.path),
"Result path '{}' matches excluded pattern: {:?}",
result.path,
patterns
);
}
}
pub fn assert_all_paths_contain(results: &[SearchResult], substring: &str) {
for result in results {
assert!(
result.path.contains(substring),
"Expected path to contain '{}', but got '{}'",
substring,
result.path
);
}
}
pub fn assert_no_paths_contain(results: &[SearchResult], substring: &str) {
for result in results {
assert!(
!result.path.contains(substring),
"Expected path to not contain '{}', but got '{}'",
substring,
result.path
);
}
}
pub fn assert_all_paths_unique(results: &[SearchResult]) {
let files = unique_files(results);
assert_eq!(
results.len(),
files.len(),
"Expected all paths to be unique, but found {} results with only {} unique paths",
results.len(),
files.len()
);
}
pub fn assert_has_paths_from_dir(results: &[SearchResult], dir: &str) {
assert!(
results.iter().any(|r| r.path.contains(dir)),
"Expected at least one result from directory '{}', but found none",
dir
);
}
pub fn assert_no_paths_from_dir(results: &[SearchResult], dir: &str) {
assert!(
results.iter().all(|r| !r.path.contains(dir)),
"Expected no results from directory '{}', but found some",
dir
);
}
pub fn assert_all_paths_extension(results: &[SearchResult], extension: &str) {
let ext = if extension.starts_with('.') {
extension.to_string()
} else {
format!(".{}", extension)
};
for result in results {
assert!(
result.path.ends_with(&ext),
"Expected path to end with '{}', but got '{}'",
ext,
result.path
);
}
}
pub fn count_from_dir(results: &[SearchResult], dir: &str) -> usize {
results.iter().filter(|r| r.path.contains(dir)).count()
}
pub fn count_unique_paths(results: &[SearchResult]) -> usize {
unique_files(results).len()
}