use probe_code::search::elastic_query::Expr;
use probe_code::search::query::{create_structured_patterns, QueryPlan};
use std::collections::{HashMap, HashSet};
#[test]
fn test_multi_keyword_pattern_generation() {
let ast = Expr::Term {
keywords: vec!["white".to_string(), "list".to_string()],
field: None,
required: false,
excluded: false,
exact: false,
};
let mut term_indices = HashMap::new();
term_indices.insert("white".to_string(), 0);
term_indices.insert("list".to_string(), 1);
let plan = QueryPlan {
ast,
term_indices,
excluded_terms: HashSet::new(),
exact: false,
};
let patterns = create_structured_patterns(&plan);
assert!(
patterns.len() >= 2,
"Should generate at least two patterns for multi-keyword term"
);
let pattern_strings: Vec<&str> = patterns.iter().map(|(p, _)| p.as_str()).collect();
assert!(
pattern_strings.iter().any(|p| p.contains("white")),
"Should generate a pattern for 'white'"
);
assert!(
pattern_strings.iter().any(|p| p.contains("list")),
"Should generate a pattern for 'list'"
);
for (_, indices) in &patterns {
assert!(
indices.contains(&0) || indices.contains(&1),
"Pattern should be associated with term index 0 or 1"
);
}
}
#[test]
fn test_excluded_term_pattern_generation() {
let ast = Expr::Term {
keywords: vec!["excluded".to_string()],
field: None,
required: false,
excluded: true,
exact: false,
};
let mut term_indices = HashMap::new();
term_indices.insert("excluded".to_string(), 0);
let mut excluded_terms = HashSet::new();
excluded_terms.insert("excluded".to_string());
let plan = QueryPlan {
ast,
term_indices,
excluded_terms,
exact: false,
};
let patterns = create_structured_patterns(&plan);
assert!(
patterns.is_empty(),
"Should not generate patterns for excluded terms"
);
}
#[test]
fn test_and_expression_pattern_generation() {
let ast = Expr::And(
Box::new(Expr::Term {
keywords: vec!["term1".to_string()],
field: None,
required: false,
excluded: false,
exact: false,
}),
Box::new(Expr::Term {
keywords: vec!["term2".to_string()],
field: None,
required: false,
excluded: false,
exact: false,
}),
);
let mut term_indices = HashMap::new();
term_indices.insert("term1".to_string(), 0);
term_indices.insert("term2".to_string(), 1);
let plan = QueryPlan {
ast,
term_indices,
excluded_terms: HashSet::new(),
exact: false,
};
let patterns = create_structured_patterns(&plan);
assert!(
patterns.len() >= 2,
"Should generate at least two patterns for AND expression"
);
let pattern_strings: Vec<&str> = patterns.iter().map(|(p, _)| p.as_str()).collect();
assert!(
pattern_strings.iter().any(|p| p.contains("term1")),
"Should generate a pattern for 'term1'"
);
assert!(
pattern_strings.iter().any(|p| p.contains("term2")),
"Should generate a pattern for 'term2'"
);
}
#[test]
fn test_or_expression_pattern_generation() {
let ast = Expr::Or(
Box::new(Expr::Term {
keywords: vec!["term1".to_string()],
field: None,
required: false,
excluded: false,
exact: false,
}),
Box::new(Expr::Term {
keywords: vec!["term2".to_string()],
field: None,
required: false,
excluded: false,
exact: false,
}),
);
let mut term_indices = HashMap::new();
term_indices.insert("term1".to_string(), 0);
term_indices.insert("term2".to_string(), 1);
let plan = QueryPlan {
ast,
term_indices,
excluded_terms: HashSet::new(),
exact: false,
};
let patterns = create_structured_patterns(&plan);
assert!(
patterns.len() >= 3,
"Should generate at least three patterns for OR expression"
);
let pattern_strings: Vec<&str> = patterns.iter().map(|(p, _)| p.as_str()).collect();
assert!(
pattern_strings.iter().any(|p| p.contains("term1")),
"Should generate a pattern for 'term1'"
);
assert!(
pattern_strings.iter().any(|p| p.contains("term2")),
"Should generate a pattern for 'term2'"
);
assert!(
pattern_strings
.iter()
.any(|p| p.contains("term1") && p.contains("term2")),
"Should generate a combined pattern for 'term1' and 'term2'"
);
}
#[test]
fn test_complex_expression_pattern_generation() {
let ast = Expr::And(
Box::new(Expr::Term {
keywords: vec!["white".to_string(), "list".to_string()],
field: None,
required: false,
excluded: false,
exact: false,
}),
Box::new(Expr::Or(
Box::new(Expr::Term {
keywords: vec!["fire".to_string(), "wall".to_string()],
field: None,
required: false,
excluded: false,
exact: false,
}),
Box::new(Expr::Term {
keywords: vec!["network".to_string()],
field: None,
required: false,
excluded: false,
exact: false,
}),
)),
);
let mut term_indices = HashMap::new();
term_indices.insert("white".to_string(), 0);
term_indices.insert("list".to_string(), 1);
term_indices.insert("fire".to_string(), 2);
term_indices.insert("wall".to_string(), 3);
term_indices.insert("network".to_string(), 4);
let plan = QueryPlan {
ast,
term_indices,
excluded_terms: HashSet::new(),
exact: false,
};
let patterns = create_structured_patterns(&plan);
assert!(
patterns.len() >= 5,
"Should generate at least five patterns for complex expression"
);
let pattern_strings: Vec<&str> = patterns.iter().map(|(p, _)| p.as_str()).collect();
assert!(
pattern_strings.iter().any(|p| p.contains("white")),
"Should generate a pattern for 'white'"
);
assert!(
pattern_strings.iter().any(|p| p.contains("list")),
"Should generate a pattern for 'list'"
);
assert!(
pattern_strings.iter().any(|p| p.contains("fire")),
"Should generate a pattern for 'fire'"
);
assert!(
pattern_strings.iter().any(|p| p.contains("wall")),
"Should generate a pattern for 'wall'"
);
assert!(
pattern_strings.iter().any(|p| p.contains("network")),
"Should generate a pattern for 'network'"
);
assert!(
pattern_strings
.iter()
.any(|p| (p.contains("fire") && p.contains("wall"))
|| (p.contains("fire") && p.contains("network"))
|| (p.contains("wall") && p.contains("network"))),
"Should generate a combined pattern for the OR expression"
);
}
#[test]
fn test_pattern_deduplication() {
let ast = Expr::Or(
Box::new(Expr::Term {
keywords: vec!["term".to_string()],
field: None,
required: false,
excluded: false,
exact: false,
}),
Box::new(Expr::Term {
keywords: vec!["term".to_string()],
field: None,
required: false,
excluded: false,
exact: false,
}),
);
let mut term_indices = HashMap::new();
term_indices.insert("term".to_string(), 0);
let plan = QueryPlan {
ast,
term_indices,
excluded_terms: HashSet::new(),
exact: false,
};
let patterns = create_structured_patterns(&plan);
let term_pattern_count = patterns.iter().filter(|(p, _)| p.contains("term")).count();
assert!(
term_pattern_count <= 2,
"Should deduplicate patterns for the same term"
);
}