use super::*;
fn wildcard_matches(pattern: &str, candidate: &str) -> bool {
if !pattern.contains('*') {
return pattern.eq_ignore_ascii_case(candidate);
}
let pattern_lc = pattern.to_ascii_lowercase();
wildcard_matches_lowered(&pattern_lc, candidate)
}
#[test]
fn flatten_1_of_them_is_or() {
let expr = parse_condition("1 of them").unwrap();
let names = vec!["sel1".into(), "sel2".into()];
let (cond, terms) = flatten_condition(&expr, &names).unwrap();
assert_eq!(cond, MatcherCondition::Or);
assert_eq!(terms.len(), 2);
assert!(terms.iter().all(|t| !t.negative));
}
#[test]
fn flatten_all_of_them_is_and() {
let expr = parse_condition("all of them").unwrap();
let names = vec!["sel1".into(), "sel2".into()];
let (cond, terms) = flatten_condition(&expr, &names).unwrap();
assert_eq!(cond, MatcherCondition::And);
assert_eq!(terms.len(), 2);
}
#[test]
fn flatten_1_of_pattern_selects_matching_selections() {
let expr = parse_condition("1 of sel_a*").unwrap();
let names = vec!["sel_a1".into(), "sel_a2".into(), "sel_b".into()];
let (cond, terms) = flatten_condition(&expr, &names).unwrap();
assert_eq!(cond, MatcherCondition::Or);
assert_eq!(terms.len(), 2);
assert!(terms.iter().any(|t| t.name == "sel_a1"));
assert!(terms.iter().any(|t| t.name == "sel_a2"));
}
#[test]
fn flatten_all_of_pattern_selects_matching_selections() {
let expr = parse_condition("all of sel_*").unwrap();
let names = vec!["sel_1".into(), "sel_2".into(), "other".into()];
let (cond, terms) = flatten_condition(&expr, &names).unwrap();
assert_eq!(cond, MatcherCondition::And);
assert_eq!(terms.len(), 2);
}
#[test]
fn resolve_wildcard_pattern_is_case_insensitive_after_hoisting_lowercase() {
let names = vec![
"Sel_Alpha".to_string(),
"SEL_beta".to_string(),
"other".to_string(),
];
let got = resolve_selection_pattern("SEL_*", &names).unwrap();
assert_eq!(got, vec!["SEL_beta".to_string(), "Sel_Alpha".to_string()]);
}
#[test]
fn wildcard_matches_lowered_equals_wildcard_matches() {
let cases = [
("A*C", "abc"),
("A*C", "ABDC"),
("*mid*", "XmidY"),
("pre*", "PREfix"),
("A*C", "xyz"),
("*end", "the_END"),
];
for (pat, cand) in cases {
let via_entry = wildcard_matches(pat, cand);
let via_lowered = wildcard_matches_lowered(&pat.to_ascii_lowercase(), cand);
assert_eq!(via_entry, via_lowered, "mismatch for {pat} vs {cand}");
}
}
#[test]
fn test_wildcard_matches_lowered_anchoring() {
assert!(wildcard_matches_lowered("a*a", "a_a_x_a"));
assert!(wildcard_matches_lowered("a*b*a", "a_b_a_b_a"));
assert!(!wildcard_matches_lowered("a*b*a", "a_b_a_b"));
assert!(wildcard_matches_lowered("sel_*_rule", "sel_a_x_rule"));
assert!(!wildcard_matches_lowered("sel_*_rule", "sel_a_x_rule_extra"));
}
#[test]
fn flatten_near_is_rejected() {
let expr = parse_condition("sel1 | near sel2").unwrap();
let names = vec!["sel1".into(), "sel2".into()];
let result = flatten_condition(&expr, &names);
assert!(result.is_err(), "near must be rejected during flattening");
let err = result.unwrap_err().to_string();
assert!(err.contains("near"));
}
#[test]
fn flatten_and_condition_is_and() {
let expr = parse_condition("sel1 and sel2").unwrap();
let names = vec!["sel1".into(), "sel2".into()];
let (cond, terms) = flatten_condition(&expr, &names).unwrap();
assert_eq!(cond, MatcherCondition::And);
assert_eq!(terms.len(), 2);
}
#[test]
fn flatten_or_condition_is_or() {
let expr = parse_condition("sel1 or sel2").unwrap();
let names = vec!["sel1".into(), "sel2".into()];
let (cond, terms) = flatten_condition(&expr, &names).unwrap();
assert_eq!(cond, MatcherCondition::Or);
assert_eq!(terms.len(), 2);
}