mod common;
use common::{identity_known_failures, identity_test, IdentityFixtures, TestResults};
use once_cell::sync::Lazy;
use std::fs;
const FIXTURES_PATH: &str = "tests/sqlglot_fixtures";
static IDENTITY_FIXTURES: Lazy<Option<IdentityFixtures>> = Lazy::new(|| {
let path = format!("{}/identity.json", FIXTURES_PATH);
match fs::read_to_string(&path) {
Ok(content) => match serde_json::from_str(&content) {
Ok(fixtures) => Some(fixtures),
Err(e) => {
eprintln!("Warning: Failed to parse identity.json: {}", e);
None
}
},
Err(e) => {
eprintln!(
"Warning: Failed to read identity.json: {} (run `make setup-fixtures` first)",
e
);
None
}
}
});
#[test]
fn test_sqlglot_identity_all() {
let result = std::thread::Builder::new()
.stack_size(16 * 1024 * 1024) .spawn(|| {
let fixtures = match IDENTITY_FIXTURES.as_ref() {
Some(f) => f,
None => {
println!("Skipping identity tests - fixtures not available");
println!("Run `make setup-fixtures` to set up test fixtures");
return None;
}
};
let known = identity_known_failures();
let mut results = TestResults::with_known_failures(&known);
for test in &fixtures.tests {
let test_id = format!("identity:{}", test.line);
let result = identity_test(&test.sql);
results.record_with_sql(&test_id, &test.sql, test.line, result);
}
results.print_summary("SQLGlot Identity");
Some(results.pass_rate())
})
.expect("Failed to spawn test thread")
.join()
.expect("Test thread panicked");
if let Some(pass_rate) = result {
assert!(
pass_rate >= 1.0,
"Pass rate {:.1}% — all identity tests must pass",
pass_rate * 100.0
);
}
}
#[test]
fn test_sqlglot_identity_sample() {
std::thread::Builder::new()
.stack_size(8 * 1024 * 1024) .spawn(|| {
let fixtures = match IDENTITY_FIXTURES.as_ref() {
Some(f) => f,
None => {
println!("Skipping identity sample tests - fixtures not available");
return;
}
};
let sample_size = 100.min(fixtures.tests.len());
let mut results = TestResults::default();
for test in fixtures.tests.iter().take(sample_size) {
let test_id = format!("identity:{}", test.line);
let result = identity_test(&test.sql);
results.record(&test_id, result);
}
results.print_summary("SQLGlot Identity (Sample)");
})
.expect("Failed to spawn test thread")
.join()
.expect("Test thread panicked");
}
mod by_category {
use super::*;
#[test]
fn test_identity_simple_expressions() {
let test_cases = ["1", "(1)", "1.0", "'x'", "''", "a", "a.b"];
let mut results = TestResults::default();
for sql in &test_cases {
let result = identity_test(sql);
results.record(sql, result);
}
results.print_summary("Simple Expressions");
assert!(
results.pass_rate() >= 0.5,
"Simple expressions should mostly pass"
);
}
#[test]
fn test_identity_arithmetic() {
let test_cases = ["1 + 2", "1 - 2", "1 * 2", "1 / 2", "(1 + 2) * 3"];
let mut results = TestResults::default();
for sql in &test_cases {
let result = identity_test(sql);
results.record(sql, result);
}
results.print_summary("Arithmetic Operations");
}
#[test]
fn test_identity_select() {
let test_cases = [
"SELECT 1",
"SELECT a",
"SELECT a, b",
"SELECT * FROM t",
"SELECT a FROM t WHERE b = 1",
];
let mut results = TestResults::default();
for sql in &test_cases {
let result = identity_test(sql);
results.record(sql, result);
}
results.print_summary("SELECT Statements");
}
#[test]
fn test_identity_functions() {
let test_cases = ["SUM(1)", "COUNT(*)", "MAX(a)", "MIN(b)", "COALESCE(a, b)"];
let mut results = TestResults::default();
for sql in &test_cases {
let result = identity_test(sql);
results.record(sql, result);
}
results.print_summary("Function Calls");
}
#[test]
fn test_debug_sql() {
let test_cases = [
r#""""x""""#,
r#"@"x""#,
"SELECT * FROM ((SELECT 1) UNION (SELECT 2) UNION (SELECT 3))",
"SELECT * FROM (((SELECT 1) UNION SELECT 2) ORDER BY x LIMIT 1 OFFSET 1)",
"SELECT * FROM ((SELECT 1 AS x) CROSS JOIN (SELECT 2 AS y)) AS z",
"''''", "SELECT * FROM ((SELECT 1))", "SELECT * FROM ((SELECT 1) AS a(b))", "SELECT a FROM test PIVOT(SUM(x) FOR y IN ('z', 'q')) UNPIVOT(x FOR y IN (z, q)) AS x", "SELECT * FROM ((SELECT 1) AS a UNION ALL (SELECT 2) AS b)", ];
for sql in &test_cases {
println!("\nInput: {}", sql);
let result = identity_test(sql);
match result {
Ok(_) => println!("✓ PASS"),
Err(e) => println!("{}", e),
}
}
}
}