#![cfg(target_os = "linux")]
use alopex_sql::{AlopexDialect, Parser, ParserError};
#[test]
fn invalid_sql_returns_parser_error_with_span() {
let err = Parser::parse_sql(&AlopexDialect, "SELECT FROM").expect_err("invalid SQL");
match err {
ParserError::UnexpectedToken {
line,
column,
found,
..
} => {
assert_eq!(line, 1);
assert!(column > 0);
assert!(found.contains("Parse error"));
}
other => panic!("expected ParserError::UnexpectedToken, got {other:?}"),
}
}
#[test]
fn parse_failure_does_not_poison_subsequent_parses() {
let err = Parser::parse_sql(&AlopexDialect, "SELECT 99999999999999999999999999")
.expect_err("oversized integer literal should fail");
let message = err.to_string();
assert!(
!message.contains("empty payload from Nim parser"),
"oversized integer literal must produce a clean prkError from Nim, \
not fall through the Rust-side empty-payload defensive path; got: {message}"
);
for i in 0..3 {
Parser::parse_sql(&AlopexDialect, "SELECT 1")
.unwrap_or_else(|err| panic!("parse #{i} after failure must succeed, got {err}"));
}
}
#[test]
fn nul_byte_input_returns_parser_error_without_panic() {
let err = Parser::parse_sql(&AlopexDialect, "\0\x03J").expect_err("invalid SQL");
match err {
ParserError::UnexpectedToken {
expected, found, ..
} => {
assert!(expected.contains("without interior NUL"));
assert_eq!(found, "interior NUL byte");
}
other => panic!("expected ParserError::UnexpectedToken, got {other:?}"),
}
}