use crate::ast::*;
use crate::proptest::arbitrary::*;
use crate::transpiler::ToSql;
use proptest::prelude::*;
proptest! {
#![proptest_config(ProptestConfig::with_cases(500))]
#[test]
fn to_sql_doesnt_panic(qail in arb_qail_get()) {
let _ = qail.to_sql();
}
#[test]
fn to_sql_produces_output(qail in arb_qail_get()) {
let sql = qail.to_sql();
prop_assert!(!sql.is_empty(), "SQL output should not be empty");
}
#[test]
fn identifiers_are_safe(ident in arb_identifier()) {
prop_assert!(!ident.contains(';'), "Identifier should not contain semicolon");
prop_assert!(!ident.contains('\''), "Identifier should not contain single quote");
prop_assert!(!ident.contains('"'), "Identifier should not contain double quote");
prop_assert!(!ident.contains('\0'), "Identifier should not contain null byte");
}
#[test]
fn operator_needs_value_consistency(op in arb_operator()) {
let symbol = op.sql_symbol();
let needs_val = op.needs_value();
if symbol == "IS NULL" || symbol == "IS NOT NULL" {
prop_assert!(!needs_val, "{} should not need a value", symbol);
}
}
#[test]
fn aggregate_func_has_sql_name(func in arb_aggregate_func()) {
let name = func.to_string();
prop_assert!(!name.is_empty(), "Aggregate function name should not be empty");
prop_assert!(name.chars().all(|c| c.is_ascii_uppercase() || c == '_'),
"Aggregate function name should be uppercase: {}", name);
}
#[test]
fn get_action_produces_select(
table in arb_identifier(),
columns in proptest::collection::vec(arb_expr_leaf(), 1..3),
) {
let qail = Qail {
action: Action::Get,
table,
columns,
..Default::default()
};
let sql = qail.to_sql();
prop_assert!(sql.starts_with("SELECT"), "GET should produce SELECT, got: {}", sql);
}
#[test]
fn del_action_produces_delete(table in arb_identifier()) {
let qail = Qail {
action: Action::Del,
table,
..Default::default()
};
let sql = qail.to_sql();
prop_assert!(sql.starts_with("DELETE"), "DEL should produce DELETE, got: {}", sql);
}
}