use wildmatch::WildMatch;
fn categorize_patterns(
patterns: &[String],
) -> (Vec<String>, Vec<String>, Vec<String>, Vec<String>) {
let mut exact_patterns = Vec::new();
let mut exact_names = Vec::new();
let mut path_wildcard_patterns = Vec::new();
let mut name_wildcard_patterns = Vec::new();
for pattern in patterns {
if pattern.contains('*') || pattern.contains('?') {
if pattern.contains("::") {
path_wildcard_patterns.push(pattern.clone());
} else {
name_wildcard_patterns.push(pattern.clone());
}
} else if pattern.contains("::") {
exact_patterns.push(pattern.clone());
} else {
exact_names.push(pattern.clone());
}
}
(
exact_patterns,
exact_names,
path_wildcard_patterns,
name_wildcard_patterns,
)
}
pub fn resolve_test_patterns(
available_tests: &[String],
patterns: &[String],
) -> (Vec<String>, Vec<String>) {
let mut selected_tests = Vec::new();
let mut invalid_patterns = Vec::new();
let (exact_patterns, exact_names, path_wildcard_patterns, name_wildcard_patterns) =
categorize_patterns(patterns);
for pattern in exact_patterns {
if available_tests.contains(&pattern) {
selected_tests.push(pattern.clone());
} else {
invalid_patterns.push(pattern);
}
}
for pattern in exact_names {
let matches = match_test_by_name(available_tests, &pattern);
if !matches.is_empty() {
selected_tests.extend(matches);
} else {
invalid_patterns.push(pattern);
}
}
for pattern in path_wildcard_patterns {
let matches = match_test_by_path(available_tests, &pattern);
if !matches.is_empty() {
selected_tests.extend(matches);
} else {
invalid_patterns.push(pattern);
}
}
for pattern in name_wildcard_patterns {
let matches = match_test_by_name(available_tests, &pattern);
if !matches.is_empty() {
selected_tests.extend(matches);
} else {
invalid_patterns.push(pattern);
}
}
selected_tests.sort();
selected_tests.dedup();
(selected_tests, invalid_patterns)
}
fn match_test_by_path(available_tests: &[String], pattern: &str) -> Vec<String> {
let wildcard = WildMatch::new(pattern);
available_tests
.iter()
.filter(|test| wildcard.matches(test))
.cloned()
.collect()
}
fn match_test_by_name(available_tests: &[String], pattern: &str) -> Vec<String> {
let wildcard = WildMatch::new(pattern);
available_tests
.iter()
.filter(|test| {
if let Some(test_name) = test.split("::").last() {
wildcard.matches(test_name)
} else {
false
}
})
.cloned()
.collect()
}