use super::*;
fn assert_readonly_tck_equivalence_for_pipeline(pipeline: &str) {
for case in tck_readonly::load_readonly_cases() {
let unopt_out = tck_readonly::execute_case_unoptimized_for_equivalence(&case);
let opt_out = if pipeline == PIPELINE_CORE {
tck_readonly::execute_case_optimized_for_equivalence(&case)
} else {
tck_readonly::execute_case_with_pipeline_for_equivalence(&case, pipeline)
};
match (unopt_out, opt_out) {
(Ok(unopt), Ok(opt)) => {
if case.any_order {
assert_eq!(
normalize_rows(&opt.rows),
normalize_rows(&unopt.rows),
"optimized/unoptimized mismatch (any-order) for pipeline `{pipeline}` readonly tck case: {}",
case.name,
);
} else {
assert_eq!(
opt.rows, unopt.rows,
"optimized/unoptimized mismatch for pipeline `{pipeline}` readonly tck case: {}",
case.name,
);
}
}
(Err(unopt_err), Err(opt_err)) => {
if let Some(expected) = &case.expected_error_contains {
let expected_lower = expected.to_ascii_lowercase();
assert!(
unopt_err.to_ascii_lowercase().contains(&expected_lower),
"unoptimized error does not match expected substring `{expected}` for pipeline `{pipeline}` case `{}`: {unopt_err}",
case.name,
);
assert!(
opt_err.to_ascii_lowercase().contains(&expected_lower),
"optimized error does not match expected substring `{expected}` for pipeline `{pipeline}` case `{}`: {opt_err}",
case.name,
);
} else {
assert_eq!(
opt_err, unopt_err,
"optimized/unoptimized error mismatch for pipeline `{pipeline}` readonly tck case: {}",
case.name,
);
}
}
(Ok(unopt), Err(opt_err)) => {
panic!(
"optimized/unoptimized mismatch for pipeline `{pipeline}` readonly tck case `{}`: unoptimized succeeded with {:?}, optimized failed with `{opt_err}`",
case.name, unopt.rows
);
}
(Err(unopt_err), Ok(opt)) => {
panic!(
"optimized/unoptimized mismatch for pipeline `{pipeline}` readonly tck case `{}`: unoptimized failed with `{unopt_err}`, optimized succeeded with {:?}",
case.name, opt.rows
);
}
}
}
}
#[test]
fn readonly_tck_corpus_equivalence_core_pipeline() {
assert_readonly_tck_equivalence_for_pipeline(PIPELINE_CORE);
}
#[test]
fn readonly_tck_corpus_equivalence_full_pipeline() {
assert_readonly_tck_equivalence_for_pipeline(PIPELINE_FULL);
}
#[test]
fn curated_query_equivalence_core_and_full_pipelines() {
let queries = [
"MATCH (n:Person) RETURN n.name AS name ORDER BY name",
"MATCH (n:Person)-[r:KNOWS]->(m:Person) WHERE n.age > 25 RETURN n.name, m.name ORDER BY n.name, m.name",
"OPTIONAL MATCH (n:Person)-[r:WORKS_AT]->(c:Company) RETURN n.name, c.name ORDER BY n.name",
"MATCH (n:Person) WITH COLLECT(n.name) AS names UNWIND names AS name RETURN name ORDER BY name",
"MATCH (n:Person) RETURN n.name AS name UNION MATCH (m:Person) RETURN m.name AS name",
"MATCH (a:Person)-[p:KNOWS*1..2]->(b:Person) RETURN p",
"MATCH (n:Person) RETURN 1 + n.age AS age ORDER BY age",
"MATCH (n:Person) RETURN (n.age + 1) + 2 AS age ORDER BY age",
"MATCH (n:Person) RETURN CASE WHEN false THEN 0 WHEN true THEN n.age + 0 ELSE n.age + 0 END AS age ORDER BY age",
"MATCH (n:Person) WHERE CASE WHEN n.age > 35 THEN true WHEN n.name = \"Alice\" THEN true ELSE false END RETURN n.name AS name ORDER BY name",
];
for cypher in queries {
assert_query_equivalent_under_pipeline(cypher, PIPELINE_CORE);
assert_query_equivalent_under_pipeline(cypher, PIPELINE_FULL);
}
}