#[cfg(test)]
mod tests {
use crate::filter::dsl::parser::lexer::{tokenize, Token};
fn tokens(input: &str) -> Vec<Token> {
tokenize(input).unwrap().into_iter().map(|s| s.token).collect()
}
#[test]
fn splits_simple_comparison() {
let got = tokens("status >= 400");
assert_eq!(
got,
vec![Token::Ident("status".into()), Token::Ge, Token::Int(400)],
);
}
#[test]
fn recognizes_boolean_keywords() {
let got = tokens("a and b or not c");
assert_eq!(
got,
vec![
Token::Ident("a".into()),
Token::And,
Token::Ident("b".into()),
Token::Or,
Token::Not,
Token::Ident("c".into()),
],
);
}
#[test]
fn parses_string_literal_with_escape() {
let got = tokens(r#"host = "api\"prod""#);
assert_eq!(
got,
vec![
Token::Ident("host".into()),
Token::Eq,
Token::Str("api\"prod".into()),
],
);
}
#[test]
fn parses_regex_literal() {
let got = tokens("body ~ /oops\\d+/");
assert_eq!(
got,
vec![
Token::Ident("body".into()),
Token::Tilde,
Token::Regex("oops\\d+".into()),
],
);
}
#[test]
fn rejects_unterminated_string() {
let err = tokenize("host = \"api").unwrap_err();
assert!(err.to_string().contains("unterminated"));
}
#[test]
fn rejects_unterminated_regex() {
let err = tokenize("body ~ /abc").unwrap_err();
assert!(err.to_string().contains("unterminated"));
}
#[test]
fn rejects_bare_minus() {
assert!(tokenize("status = -").is_err());
}
#[test]
fn accepts_negative_integer() {
let got = tokens("offset = -15");
assert_eq!(
got,
vec![Token::Ident("offset".into()), Token::Eq, Token::Int(-15)],
);
}
}