Skip to content

Commit

Permalink
Add snapshot testing for AST pretty printing
Browse files Browse the repository at this point in the history
  • Loading branch information
jpschorr committed Jul 9, 2024
1 parent a54868e commit dd28ef5
Show file tree
Hide file tree
Showing 22 changed files with 1,126 additions and 27 deletions.
8 changes: 3 additions & 5 deletions deny.toml
Original file line number Diff line number Diff line change
Expand Up @@ -126,15 +126,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"] },
# 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

0 comments on commit dd28ef5

Please sign in to comment.