use serde_json::json;
use tellaro_query_language::evaluator::TqlEvaluator;
use tellaro_query_language::parser::TqlParser;
fn evaluate_query(query: &str, record: &serde_json::Value) -> bool {
let parser = TqlParser::new();
let evaluator = TqlEvaluator::new();
let ast = parser.parse(query).expect("Failed to parse query");
evaluator
.evaluate(&ast, record)
.expect("Failed to evaluate")
}
fn filter_records(query: &str, records: &[serde_json::Value]) -> Vec<serde_json::Value> {
records
.iter()
.filter(|r| evaluate_query(query, r))
.cloned()
.collect()
}
fn setup_tag_records() -> Vec<serde_json::Value> {
vec![
json!({"id": 1, "tags": []}),
json!({"id": 2, "tags": ["python", "rust"]}),
json!({"id": 3, "tags": ["javascript"]}),
]
}
fn setup_score_records() -> Vec<serde_json::Value> {
vec![
json!({"id": 1, "scores": []}),
json!({"id": 2, "scores": [50, 75]}),
json!({"id": 3, "scores": [25]}),
]
}
#[test]
fn test_empty_array_any_operator() {
let data = setup_tag_records();
let results = filter_records("any tags eq 'python'", &data);
assert_eq!(results.len(), 1);
assert_eq!(results[0].get("id").and_then(|v| v.as_i64()), Some(2));
}
#[test]
fn test_empty_array_all_operator() {
let data = setup_tag_records();
let results = filter_records("all tags eq 'python'", &data);
assert_eq!(results.len(), 0);
}
#[test]
fn test_empty_array_not_any_operator() {
let data = setup_tag_records();
let results = filter_records("none tags eq 'python'", &data);
assert_eq!(results.len(), 2);
let ids: Vec<i64> = results
.iter()
.filter_map(|r| r.get("id").and_then(|v| v.as_i64()))
.collect();
assert!(ids.contains(&1)); assert!(ids.contains(&3)); }
#[test]
fn test_empty_array_not_all_operator() {
let data = setup_tag_records();
let results = filter_records("not all tags eq 'python'", &data);
assert_eq!(results.len(), 3); }
#[test]
fn test_empty_array_exists() {
let data = setup_tag_records();
let results = filter_records("tags exists", &data);
assert_eq!(results.len(), 3);
}
#[test]
fn test_empty_array_greater_than() {
let data = setup_score_records();
let results = filter_records("any scores gt 60", &data);
assert_eq!(results.len(), 1);
assert_eq!(results[0].get("id").and_then(|v| v.as_i64()), Some(2));
}
#[test]
fn test_empty_array_less_than() {
let data = setup_score_records();
let results = filter_records("any scores lt 60", &data);
assert_eq!(results.len(), 2);
let ids: Vec<i64> = results
.iter()
.filter_map(|r| r.get("id").and_then(|v| v.as_i64()))
.collect();
assert!(ids.contains(&2));
assert!(ids.contains(&3));
}
#[test]
fn test_empty_array_contains_with_any() {
let data = setup_tag_records();
let results = filter_records("any tags contains 'py'", &data);
assert_eq!(results.len(), 1);
assert_eq!(results[0].get("id").and_then(|v| v.as_i64()), Some(2));
}
#[test]
fn test_empty_array_startswith_with_any() {
let data = setup_tag_records();
let results = filter_records("any tags startswith 'py'", &data);
assert_eq!(results.len(), 1);
assert_eq!(results[0].get("id").and_then(|v| v.as_i64()), Some(2));
}
#[test]
fn test_empty_array_endswith_with_any() {
let data = setup_tag_records();
let results = filter_records("any tags endswith 'on'", &data);
assert_eq!(results.len(), 1);
assert_eq!(results[0].get("id").and_then(|v| v.as_i64()), Some(2));
}
#[test]
fn test_multiple_empty_arrays_with_any() {
let data = vec![
json!({"id": 1, "tags": []}),
json!({"id": 2, "tags": []}),
json!({"id": 3, "tags": ["python"]}),
];
let results = filter_records("any tags eq 'python'", &data);
assert_eq!(results.len(), 1);
assert_eq!(results[0].get("id").and_then(|v| v.as_i64()), Some(3));
}
#[test]
fn test_empty_array_with_compound_expression() {
let data = setup_tag_records();
let results = filter_records("id > 1 AND any tags eq 'python'", &data);
assert_eq!(results.len(), 1);
assert_eq!(results[0].get("id").and_then(|v| v.as_i64()), Some(2));
}
#[test]
fn test_none_with_empty_arrays() {
let data = vec![
json!({"id": 1, "tags": []}),
json!({"id": 2, "tags": ["python"]}),
json!({"id": 3, "tags": ["java"]}),
];
let results = filter_records("none tags eq 'python'", &data);
assert_eq!(results.len(), 2);
let ids: Vec<i64> = results
.iter()
.filter_map(|r| r.get("id").and_then(|v| v.as_i64()))
.collect();
assert!(ids.contains(&1));
assert!(ids.contains(&3));
}
#[test]
fn test_all_with_numeric_comparison() {
let data = vec![
json!({"id": 1, "scores": []}),
json!({"id": 2, "scores": [80, 90]}),
json!({"id": 3, "scores": [50, 60]}),
];
let results = filter_records("all scores gt 70", &data);
assert_eq!(results.len(), 1);
assert_eq!(results[0].get("id").and_then(|v| v.as_i64()), Some(2));
}