Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add snapshot testing for AST pretty printing #474

Merged
merged 1 commit into from
Jul 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 3 additions & 6 deletions deny.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ ignore = [
# Advisory: https://rustsec.org/advisories/RUSTSEC-2021-0145
# atty potential misaligned pointer; used by some pretty-printing deps (criterion, miette, lalrpop)
"RUSTSEC-2021-0145",

# Advisory: https://rustsec.org/advisories/RUSTSEC-2020-0071
# `chrono` uses an old version of `time`, but `chrono` >= 4.2 doesn't use the code path with the issue
"RUSTSEC-2020-0071",
Expand Down Expand Up @@ -126,15 +125,13 @@ allow = [
deny = [
# Use `once_cell` instead
# `OnceCell`s API is under consideration for inclusion in `std`: https://github.com/rust-lang/rust/issues/74465
{ name = "lazy_static", wrappers = ["Inflector", "criterion"]},


{ name = "lazy_static", wrappers = ["Inflector", "criterion", "insta", "console"] },
# Advisory: https://rustsec.org/advisories/RUSTSEC-2020-0071
# `time` < 0.2.23 has a potential (though unlikely) potential segfault
{ name = "time", version ="<0.2.23", wrappers = ["chrono"]},
{ name = "time", version = "<0.2.23", wrappers = ["chrono"] },
# Advisory: https://rustsec.org/advisories/RUSTSEC-2020-0071
# `chrono` uses an old version of `time`, but `chrono` >= 4.2 doesn't use the code path with the issue
{ name = "chrono", version ="<0.4.20"}
{ name = "chrono", version = "<0.4.20" }
]


Expand Down
2 changes: 2 additions & 0 deletions partiql-ast/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ thiserror = "1.0"

[dev-dependencies]
partiql-parser = { path = "../partiql-parser", version = "0.8" }
itertools = "0.13"
insta = "1.38.0"

[features]
default = []
Expand Down
72 changes: 50 additions & 22 deletions partiql-ast/tests/common.rs → partiql-ast/tests/pretty.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
use itertools::Itertools;
use partiql_ast::pretty::ToPretty;
use partiql_parser::ParserResult;

pub fn setup() {
// setup test code goes here
}

#[track_caller]
#[inline]
fn parse(statement: &str) -> ParserResult<'_> {
Expand All @@ -13,19 +10,33 @@ fn parse(statement: &str) -> ParserResult<'_> {

#[track_caller]
#[inline]
fn pretty_print_test(statement: &str) {
fn pretty_print_test(name: &str, statement: &str) {
let res = parse(statement);
assert!(res.is_ok());
let res = res.unwrap();

// TODO https://github.com/partiql/partiql-lang-rust/issues/473
for w in [180, 120, 80, 40, 30, 20, 10] {
println!("{:-<w$}", "");
println!("{}\n", res.ast.to_pretty_string(w).unwrap());
}

let doc = [180, 120, 80, 40, 30, 20, 10]
.into_iter()
.map(|w| {
let header = format!("{:-<w$}", "");
let ast = format!("{}\n", res.ast.to_pretty_string(w).unwrap());
format!("{header}\n{ast}")
})
.join("\n");

let w = 200;
let header = format!("{:=<w$}", "");
let doc = format!("{header}\n{statement}\n{header}\n\n{doc}");

insta::assert_snapshot!(name, doc)
}

#[test]
fn pretty() {
pretty_print_test(
"pretty",
"select foo,bar, baz,thud.*,grunt.a[*].b[2].*, count(1) as n from
<<
{ 'foo': 'foo', 'x': 9, 'y':5, z:-11 },
Expand All @@ -42,6 +53,7 @@ fn pretty() {
#[test]
fn pretty2() {
pretty_print_test(
"pretty2",
"select foo,bar, baz,thud,grunt, count(1) as n from
(SELECT * FROM table1)
where (bar between 3 and 25 AND baz NOT LIKE 'example%') OR foo.a.b[*] IS MISSING
Expand All @@ -52,32 +64,42 @@ fn pretty2() {

#[test]
fn pretty_having_limit_offset() {
pretty_print_test("SELECT a FROM foo GROUP BY a HAVING a > 2 ORDER BY a LIMIT 1 OFFSET 1");
pretty_print_test(
"having_limit_offset",
"SELECT a FROM foo GROUP BY a HAVING a > 2 ORDER BY a LIMIT 1 OFFSET 1",
);
}

#[test]
fn pretty_select_value_unpivot() {
pretty_print_test("SELECT VALUE foo FROM (SELECT VALUE v FROM UNPIVOT e AS v) AS foo");
pretty_print_test(
"select value unpivot",
"SELECT VALUE foo FROM (SELECT VALUE v FROM UNPIVOT e AS v) AS foo",
);
}

#[test]
fn pretty_select_value_tuple_ctor() {
pretty_print_test("SELECT VALUE {'a':v.a, 'b':v.b} FROM [{'a':1, 'b':1}, {'a':2, 'b':2}] AS v");
pretty_print_test(
"pretty_select_value_tuple_ctor",
"SELECT VALUE {'a':v.a, 'b':v.b} FROM [{'a':1, 'b':1}, {'a':2, 'b':2}] AS v",
);
}

#[test]
fn pretty_from_comma() {
pretty_print_test("SELECT a, b FROM T1, T2");
pretty_print_test("pretty_from_comma", "SELECT a, b FROM T1, T2");
}

#[test]
fn pretty_expr_in() {
pretty_print_test("(a, b) IN ((1, 2), (3, 4))");
pretty_print_test("pretty_expr_in", "(a, b) IN ((1, 2), (3, 4))");
}

#[test]
fn pretty_setop() {
pretty_print_test(
"pretty_setop",
"(SELECT a1 FROM b1 ORDER BY c1 LIMIT d1 OFFSET e1)
UNION
(SELECT a2 FROM b2 ORDER BY c2 LIMIT d2 OFFSET e2)
Expand All @@ -88,6 +110,7 @@ fn pretty_setop() {
#[test]
fn pretty_bagop() {
pretty_print_test(
"pretty_bagop",
"
(
(SELECT a1 FROM b1 ORDER BY c1 LIMIT d1 OFFSET e1)
Expand All @@ -103,6 +126,7 @@ fn pretty_bagop() {
#[test]
fn pretty_join() {
pretty_print_test(
"pretty_join",
"
SELECT t1.id AS id, t1.val AS val1, t2.val AS val2
FROM table1 AS t1 JOIN table1_null_row AS t2 ON t1.id = t2.id",
Expand All @@ -111,27 +135,31 @@ fn pretty_join() {

#[test]
fn pretty_kw_fns() {
pretty_print_test("trim(trailing from 'test')");
pretty_print_test("POSITION('abc' IN 'abcdefg')");
pretty_print_test("substring('test', 100, 50)");
pretty_print_test("substring('test', 100)");
pretty_print_test("pretty_kw_fn1", "trim(trailing from 'test')");
pretty_print_test("pretty_kw_fn2", "POSITION('abc' IN 'abcdefg')");
pretty_print_test("pretty_kw_fn3", "substring('test', 100, 50)");
pretty_print_test("pretty_kw_fn4", "substring('test', 100)");
}

#[test]
fn pretty_typed_lits() {
pretty_print_test("TIME WITH TIME ZONE '23:59:59.1234567890+18:00'");
pretty_print_test("TIME (3) WITH TIME ZONE '12:59:31'");
pretty_print_test(
"pretty_typed_lits1",
"TIME WITH TIME ZONE '23:59:59.1234567890+18:00'",
);
pretty_print_test("pretty_typed_lits2", "TIME (3) WITH TIME ZONE '12:59:31'");
}

#[test]
fn pretty_case() {
pretty_print_test("SELECT VALUE CASE WHEN x + 1 < i THEN '< ONE' WHEN x + 1 = f THEN 'TWO' WHEN (x + 1 > d) AND (x + 1 < 100) THEN '>= THREE < 100' ELSE '?' END FROM << -1.0000, i, f, d, 100e0, null, missing >> AS x");
pretty_print_test("SELECT VALUE CASE x + 1 WHEN NULL THEN 'shouldnt be null' WHEN MISSING THEN 'shouldnt be missing' WHEN i THEN 'ONE' WHEN f THEN 'TWO' WHEN d THEN 'THREE' END FROM << i, f, d, null, missing >> AS x");
pretty_print_test("pretty_case_1", "SELECT VALUE CASE WHEN x + 1 < i THEN '< ONE' WHEN x + 1 = f THEN 'TWO' WHEN (x + 1 > d) AND (x + 1 < 100) THEN '>= THREE < 100' ELSE '?' END FROM << -1.0000, i, f, d, 100e0, null, missing >> AS x");
pretty_print_test("pretty_case_2","SELECT VALUE CASE x + 1 WHEN NULL THEN 'shouldnt be null' WHEN MISSING THEN 'shouldnt be missing' WHEN i THEN 'ONE' WHEN f THEN 'TWO' WHEN d THEN 'THREE' END FROM << i, f, d, null, missing >> AS x");
}

#[test]
fn pretty_pivot() {
pretty_print_test(
"pretty_pivot",
"
PIVOT foo.a AT foo.b
FROM <<{'a': 1, 'b':'I'}, {'a': 2, 'b':'II'}, {'a': 3, 'b':'III'}>> AS foo
Expand Down
42 changes: 42 additions & 0 deletions partiql-ast/tests/snapshots/pretty__having_limit_offset.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
source: partiql-ast/tests/pretty.rs
expression: doc
---
========================================================================================================================================================================================================
SELECT a FROM foo GROUP BY a HAVING a > 2 ORDER BY a LIMIT 1 OFFSET 1
========================================================================================================================================================================================================

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SELECT a FROM foo GROUP BY a HAVING (a > 2) ORDER BY a LIMIT 1 OFFSET 1

------------------------------------------------------------------------------------------------------------------------
SELECT a FROM foo GROUP BY a HAVING (a > 2) ORDER BY a LIMIT 1 OFFSET 1

--------------------------------------------------------------------------------
SELECT a FROM foo GROUP BY a HAVING (a > 2) ORDER BY a LIMIT 1 OFFSET 1

----------------------------------------
SELECT a FROM foo GROUP BY a
HAVING (a > 2) ORDER BY a LIMIT 1
OFFSET 1

------------------------------
SELECT a FROM foo GROUP BY a
HAVING (a > 2) ORDER BY a
LIMIT 1 OFFSET 1

--------------------
SELECT a FROM foo
GROUP BY a
HAVING (a > 2)
ORDER BY a LIMIT 1
OFFSET 1

----------
SELECT a
FROM foo
GROUP BY a
HAVING (a > 2)
ORDER BY a
LIMIT 1
OFFSET 1
149 changes: 149 additions & 0 deletions partiql-ast/tests/snapshots/pretty__pretty.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
---
source: partiql-ast/tests/pretty.rs
expression: doc
---
========================================================================================================================================================================================================
select foo,bar, baz,thud.*,grunt.a[*].b[2].*, count(1) as n from
<<
{ 'foo': 'foo', 'x': 9, 'y':5, z:-11 },
{ 'foo': 'bar' },
{ 'foo': 'qux' },
{ 'foo': 'bar' },
{ 'foo': 'baz' },
{ 'foo': 'bar' },
{ 'foo': 'baz' }
>> group by foo order by n desc
========================================================================================================================================================================================================

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SELECT foo, bar, baz, thud.*, grunt.a[*].b[2].*, count(1) AS n FROM <<
{ 'foo': 'foo', 'x': 9, 'y': 5, z: -11 },
{ 'foo': 'bar' },
{ 'foo': 'qux' },
{ 'foo': 'bar' },
{ 'foo': 'baz' },
{ 'foo': 'bar' },
{ 'foo': 'baz' }
>> GROUP BY foo ORDER BY n DESC

------------------------------------------------------------------------------------------------------------------------
SELECT foo, bar, baz, thud.*, grunt.a[*].b[2].*, count(1) AS n FROM <<
{ 'foo': 'foo', 'x': 9, 'y': 5, z: -11 },
{ 'foo': 'bar' },
{ 'foo': 'qux' },
{ 'foo': 'bar' },
{ 'foo': 'baz' },
{ 'foo': 'bar' },
{ 'foo': 'baz' }
>> GROUP BY foo ORDER BY n DESC

--------------------------------------------------------------------------------
SELECT foo, bar, baz, thud.*, grunt.a[*].b[2].*, count(1) AS n FROM <<
{ 'foo': 'foo', 'x': 9, 'y': 5, z: -11 },
{ 'foo': 'bar' },
{ 'foo': 'qux' },
{ 'foo': 'bar' },
{ 'foo': 'baz' },
{ 'foo': 'bar' },
{ 'foo': 'baz' }
>> GROUP BY foo ORDER BY n DESC

----------------------------------------
SELECT foo, bar, baz, thud.*,
grunt.a[*].b[2].*, count(1) AS n
FROM <<
{
'foo': 'foo',
'x': 9,
'y': 5,
z: -11
},
{ 'foo': 'bar' },
{ 'foo': 'qux' },
{ 'foo': 'bar' },
{ 'foo': 'baz' },
{ 'foo': 'bar' },
{ 'foo': 'baz' }
>> GROUP BY foo ORDER BY n DESC

------------------------------
SELECT foo, bar, baz, thud.*,
grunt.a[*].b[2].*,
count(1) AS n FROM <<
{
'foo': 'foo',
'x': 9,
'y': 5,
z: -11
},
{ 'foo': 'bar' },
{ 'foo': 'qux' },
{ 'foo': 'bar' },
{ 'foo': 'baz' },
{ 'foo': 'bar' },
{ 'foo': 'baz' }
>> GROUP BY foo
ORDER BY n DESC

--------------------
SELECT foo, bar,
baz, thud.*,
grunt.a[*].b[2].*,
count(1) AS n
FROM <<
{
'foo': 'foo',
'x': 9,
'y': 5,
z: -11
},
{ 'foo': 'bar'
},
{ 'foo': 'qux'
},
{ 'foo': 'bar'
},
{ 'foo': 'baz'
},
{ 'foo': 'bar'
},
{ 'foo': 'baz' }
>> GROUP BY foo
ORDER BY n DESC

----------
SELECT foo,
bar,
baz,
thud.*,
grunt.a[*].b[2].*,
count(1) AS n
FROM <<
{
'foo': 'foo',
'x': 9,
'y': 5,
z: -11
},
{
'foo': 'bar'
},
{
'foo': 'qux'
},
{
'foo': 'bar'
},
{
'foo': 'baz'
},
{
'foo': 'bar'
},
{
'foo': 'baz'
}
>>
GROUP BY
foo
ORDER BY n DESC
Loading
Loading