#![cfg(not(target_family = "wasm"))]
use std::fs;
use std::path::Path;
use insta::assert_debug_snapshot;
use insta::{assert_snapshot, with_settings};
use prqlc::sql::Dialect;
use prqlc::sql::SupportLevel;
use prqlc::{Options, Target};
use test_each_file::test_each_path;
mod lex {
use super::*;
test_each_path! { in "./prqlc/prqlc/tests/integration/queries" => run }
fn run(prql_path: &Path) {
let test_name = prql_path.file_stem().unwrap().to_str().unwrap();
let prql = fs::read_to_string(prql_path).unwrap();
let tokens = prqlc_parser::lexer::lex_source(&prql).unwrap();
with_settings!({ input_file => prql_path }, {
assert_debug_snapshot!(test_name, tokens)
});
}
}
mod compile {
use super::*;
test_each_path! { in "./prqlc/prqlc/tests/integration/queries" => run }
fn run(prql_path: &Path) {
let test_name = prql_path.file_stem().unwrap().to_str().unwrap();
let prql = fs::read_to_string(prql_path).unwrap();
if prql.contains("generic:skip") {
return;
}
let target = Target::Sql(Some(Dialect::Generic));
let options = Options::default().no_signature().with_target(target);
let sql = prqlc::compile(&prql, &options).unwrap();
with_settings!({ input_file => prql_path }, {
assert_snapshot!(test_name, &sql, &prql)
});
}
}
fn should_run_query(dialect: Dialect, prql: &str) -> bool {
let dialect_str = dialect.to_string().to_lowercase();
match dialect.support_level() {
SupportLevel::Supported => !prql.contains(&format!("{dialect_str}:skip")),
SupportLevel::Unsupported => prql.contains(&format!("{dialect_str}:test")),
SupportLevel::Nascent => false,
}
}
mod compileall {
use super::*;
use similar::TextDiff;
use strum::IntoEnumIterator;
test_each_path! { in "./prqlc/prqlc/tests/integration/queries" => run }
fn run(prql_path: &Path) {
let test_name = prql_path.file_stem().unwrap().to_str().unwrap();
let prql = fs::read_to_string(prql_path).unwrap();
if prql.contains("generic:skip") {
return;
}
let target = Target::Sql(Some(Dialect::Generic));
let options = Options::default().no_signature().with_target(target);
let generic_sql = prqlc::compile(&prql, &options).unwrap();
let mut diffsnap = "".to_owned();
for dialect in Dialect::iter() {
if !should_run_query(dialect, &prql) {
continue;
}
let dialect_target = Target::Sql(Some(dialect));
let dialect_options = Options::default()
.no_signature()
.with_target(dialect_target);
let dialect_sql = prqlc::compile(&prql, &dialect_options).unwrap();
let diff = TextDiff::from_lines(&generic_sql, &dialect_sql);
diffsnap = format!(
"{diffsnap}\n{}",
diff.unified_diff()
.context_radius(10)
.header("generic", &dialect.to_string())
);
}
with_settings!({ input_file => prql_path }, {
assert_snapshot!(test_name, diffsnap, &prql)
});
}
}
mod fmt {
use super::*;
test_each_path! { in "./prqlc/prqlc/tests/integration/queries" => run }
fn run(prql_path: &Path) {
let test_name = prql_path.file_stem().unwrap().to_str().unwrap();
let prql = fs::read_to_string(prql_path).unwrap();
let pl = prqlc::prql_to_pl(&prql).unwrap();
let formatted = prqlc::pl_to_prql(&pl).unwrap();
with_settings!({ input_file => prql_path }, {
assert_snapshot!(test_name, &formatted, &prql)
});
prqlc::prql_to_pl(&formatted).unwrap();
}
}
#[cfg(feature = "serde_yaml")]
mod debug_lineage {
use super::*;
test_each_path! { in "./prqlc/prqlc/tests/integration/queries" => run }
fn run(prql_path: &Path) {
let test_name = prql_path.file_stem().unwrap().to_str().unwrap();
let prql = fs::read_to_string(prql_path).unwrap();
let pl = prqlc::prql_to_pl(&prql).unwrap();
let fc = prqlc::internal::pl_to_lineage(pl).unwrap();
let lineage = serde_yaml::to_string(&fc).unwrap();
with_settings!({ input_file => prql_path }, {
assert_snapshot!(test_name, &lineage, &prql)
});
}
}
#[cfg(any(feature = "test-dbs", feature = "test-dbs-external"))]
mod results {
use itertools::Itertools;
use super::*;
use crate::dbs::{batch_to_csv, runners};
test_each_path! { in "./prqlc/prqlc/tests/integration/queries" => run }
fn run(prql_path: &Path) {
let test_name = prql_path.file_stem().unwrap().to_str().unwrap();
let prql = fs::read_to_string(prql_path).unwrap();
let results: Vec<(Dialect, String)> = runners()
.iter()
.filter_map(|runner| {
let mut runner = runner.lock().unwrap();
let dialect = runner.dialect();
if !should_run_query(dialect, &prql) {
return None;
}
eprintln!("Executing {test_name} for {dialect}");
match runner.query(&prql) {
Ok(batch) => {
let csv = batch_to_csv(batch);
Some(Ok((dialect, csv)))
}
Err(e) => Some(Err(e)),
}
})
.try_collect()
.unwrap();
if results.is_empty() {
panic!("No valid dialects to run the query at {prql_path:#?} against");
}
let ((first_dialect, first_text), others) = results.split_first().unwrap();
with_settings!({ input_file => prql_path }, {
assert_snapshot!(test_name, first_text, &prql)
});
for (dialect, text) in others {
similar_asserts::assert_eq!(
first_text,
text,
"{} {} {}",
test_name,
first_dialect,
dialect
);
}
}
}