use detect::parser::test_utils::RawTestExpr;
use detect::parser::*;
#[test]
fn test_simple_predicate() {
let result = RawParser::parse_raw_expr("name == foo").unwrap();
let expected = RawTestExpr::string_predicate("name", "==", "foo");
assert_eq!(result.to_test_expr(), expected);
}
#[test]
fn test_quoted_values() {
let result = RawParser::parse_raw_expr(r#"filename == "my file.txt""#).unwrap();
let expected = RawTestExpr::quoted_predicate("filename", "==", "my file.txt");
assert_eq!(result.to_test_expr(), expected);
}
#[test]
fn test_single_quoted_values() {
let result = RawParser::parse_raw_expr("filename == 'my file.txt'").unwrap();
let expected = RawTestExpr::quoted_predicate("filename", "==", "my file.txt");
assert_eq!(result.to_test_expr(), expected);
}
#[test]
fn test_escape_sequences() {
let result = RawParser::parse_raw_expr(r#"name == "file\"with\"quotes""#).unwrap();
let expected = RawTestExpr::quoted_predicate("name", "==", r#"file\"with\"quotes"#);
assert_eq!(result.to_test_expr(), expected);
let result = RawParser::parse_raw_expr(r#"content == "line1\nline2\ttab\\backslash""#).unwrap();
let expected =
RawTestExpr::quoted_predicate("content", "==", r#"line1\nline2\ttab\\backslash"#);
assert_eq!(result.to_test_expr(), expected);
let result = RawParser::parse_raw_expr(r"name == 'file\'with\'quotes'").unwrap();
let expected = RawTestExpr::quoted_predicate("name", "==", r"file\'with\'quotes");
assert_eq!(result.to_test_expr(), expected);
}
#[test]
fn test_set_values() {
let result = RawParser::parse_raw_expr("ext in [rs, js, ts]").unwrap();
let expected = RawTestExpr::string_predicate("ext", "in", "[rs, js, ts]");
assert_eq!(result.to_test_expr(), expected);
}
#[test]
fn test_mixed_set() {
let result = RawParser::parse_raw_expr(r#"name in [README, "my file", config]"#).unwrap();
let expected = RawTestExpr::string_predicate("name", "in", r#"[README, "my file", config]"#);
assert_eq!(result.to_test_expr(), expected);
}
#[test]
fn test_set_with_quotes_and_escapes() {
let result = RawParser::parse_raw_expr(r#"name in ["file\"1", 'file\'2', plain]"#).unwrap();
let expected = RawTestExpr::string_predicate("name", "in", r#"["file\"1", 'file\'2', plain]"#);
assert_eq!(result.to_test_expr(), expected);
}
#[test]
fn test_empty_set() {
let result = RawParser::parse_raw_expr("ext in []").unwrap();
let expected = RawTestExpr::string_predicate("ext", "in", "[]");
assert_eq!(result.to_test_expr(), expected);
}
#[test]
fn test_boolean_logic() {
let result = RawParser::parse_raw_expr("name == foo AND size > 1000").unwrap();
let expected = RawTestExpr::and(
RawTestExpr::string_predicate("name", "==", "foo"),
RawTestExpr::string_predicate("size", ">", "1000"),
);
assert_eq!(result.to_test_expr(), expected);
}
#[test]
fn test_or_logic() {
let result = RawParser::parse_raw_expr("name == foo OR name == bar").unwrap();
let expected = RawTestExpr::or(
RawTestExpr::string_predicate("name", "==", "foo"),
RawTestExpr::string_predicate("name", "==", "bar"),
);
assert_eq!(result.to_test_expr(), expected);
}
#[test]
fn test_negation_variants() {
let result = RawParser::parse_raw_expr("NOT name == foo").unwrap();
let expected = RawTestExpr::not(RawTestExpr::string_predicate("name", "==", "foo"));
assert_eq!(result.to_test_expr(), expected);
let result = RawParser::parse_raw_expr("! name == foo").unwrap();
let expected = RawTestExpr::not(RawTestExpr::string_predicate("name", "==", "foo"));
assert_eq!(result.to_test_expr(), expected);
let result = RawParser::parse_raw_expr("\\! name == foo").unwrap();
let expected = RawTestExpr::not(RawTestExpr::string_predicate("name", "==", "foo"));
assert_eq!(result.to_test_expr(), expected);
}
#[test]
fn test_operator_precedence() {
let result = RawParser::parse_raw_expr("a == b OR c == d AND e == f").unwrap();
let expected = RawTestExpr::or(
RawTestExpr::string_predicate("a", "==", "b"),
RawTestExpr::and(
RawTestExpr::string_predicate("c", "==", "d"),
RawTestExpr::string_predicate("e", "==", "f"),
),
);
assert_eq!(result.to_test_expr(), expected);
}
#[test]
fn test_parentheses() {
let result = RawParser::parse_raw_expr("(a == b OR c == d) AND e == f").unwrap();
let expected = RawTestExpr::and(
RawTestExpr::or(
RawTestExpr::string_predicate("a", "==", "b"),
RawTestExpr::string_predicate("c", "==", "d"),
),
RawTestExpr::string_predicate("e", "==", "f"),
);
assert_eq!(result.to_test_expr(), expected);
}
#[test]
fn test_complex_expression() {
let result =
RawParser::parse_raw_expr(r#"(name == "test.rs" OR ext in [js, ts]) AND NOT size > 1mb"#)
.unwrap();
let expected = RawTestExpr::and(
RawTestExpr::or(
RawTestExpr::quoted_predicate("name", "==", "test.rs"),
RawTestExpr::string_predicate("ext", "in", "[js, ts]"),
),
RawTestExpr::not(RawTestExpr::string_predicate("size", ">", "1mb")),
);
assert_eq!(result.to_test_expr(), expected);
}
#[test]
fn test_all_operators() {
let test_cases = vec![
("name == foo", "=="),
("name != foo", "!="),
("name ~= foo", "~="),
("name > foo", ">"),
("name < foo", "<"),
("name >= foo", ">="),
("name <= foo", "<="),
("name contains foo", "contains"),
("name in [foo]", "in"),
];
for (input, expected_op) in test_cases {
let result = RawParser::parse_raw_expr(input).unwrap();
match result.to_test_expr() {
RawTestExpr::Predicate(pred) => {
assert_eq!(pred.operator, expected_op, "Failed for input: {}", input);
}
_ => panic!("Expected predicate for input: {}", input),
}
}
}
#[test]
fn test_complex_selectors() {
let result = RawParser::parse_raw_expr("name == test.rs").unwrap();
let expected = RawTestExpr::string_predicate("name", "==", "test.rs");
assert_eq!(result.to_test_expr(), expected);
let result = RawParser::parse_raw_expr("meta.size > 1000").unwrap();
let expected = RawTestExpr::string_predicate("meta.size", ">", "1000");
assert_eq!(result.to_test_expr(), expected);
}
#[test]
fn test_case_insensitive_keywords() {
let result = RawParser::parse_raw_expr("name == foo AND name == bar").unwrap();
let result_upper = RawParser::parse_raw_expr("name == foo AND name == bar").unwrap();
assert_eq!(result.to_test_expr(), result_upper.to_test_expr());
let result = RawParser::parse_raw_expr("NOT name == foo").unwrap();
let result_lower = RawParser::parse_raw_expr("not name == foo").unwrap();
assert_eq!(result.to_test_expr(), result_lower.to_test_expr());
}
#[test]
fn test_syntax_errors() {
let result = RawParser::parse_raw_expr("name ==");
assert!(result.is_err());
let result = RawParser::parse_raw_expr("name foo");
assert!(result.is_err());
let result = RawParser::parse_raw_expr("(name == foo");
assert!(result.is_err());
let result = RawParser::parse_raw_expr("name in [foo");
assert!(
result.is_ok(),
"Permissive grammar allows [foo as bare token"
);
let result = RawParser::parse_raw_expr(r#"name == "unclosed"#);
assert!(result.is_err());
}
#[test]
fn test_invalid_escape_sequences() {
let result = RawParser::parse_raw_expr(r#"name == "invalid\x""#);
let expected = RawTestExpr::quoted_predicate("name", "==", r"invalid\x");
assert_eq!(result.unwrap().to_test_expr(), expected);
let result = RawParser::parse_raw_expr("name == \"unterminated");
assert!(result.is_err());
}
#[test]
fn test_whitespace_handling() {
let result1 = RawParser::parse_raw_expr("name==foo").unwrap();
let result2 = RawParser::parse_raw_expr("name == foo").unwrap();
let result3 = RawParser::parse_raw_expr(" name == foo ").unwrap();
assert_eq!(result1.to_test_expr(), result2.to_test_expr());
assert_eq!(result2.to_test_expr(), result3.to_test_expr());
let result = RawParser::parse_raw_expr("ext in [ rs , js , ts ]").unwrap();
let expected = RawTestExpr::string_predicate("ext", "in", "[ rs , js , ts ]");
assert_eq!(result.to_test_expr(), expected);
}
#[test]
fn test_edge_cases() {
let result = RawParser::parse_raw_expr(r#"name == """#).unwrap();
let expected = RawTestExpr::quoted_predicate("name", "==", "");
assert_eq!(result.to_test_expr(), expected);
let result = RawParser::parse_raw_expr("name == foo-bar_baz.txt").unwrap();
let expected = RawTestExpr::string_predicate("name", "==", "foo-bar_baz.txt");
assert_eq!(result.to_test_expr(), expected);
let result = RawParser::parse_raw_expr("path.name_with_underscores == foo").unwrap();
let expected = RawTestExpr::string_predicate("path.name_with_underscores", "==", "foo");
assert_eq!(result.to_test_expr(), expected);
}