This is an automated email from the ASF dual-hosted git repository. jhyde pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/calcite.git
commit dfd6a0cdc51b61e88787fcae92839119e868df0e Author: Julian Hyde <[email protected]> AuthorDate: Fri Oct 25 17:04:12 2019 -0700 Refactor SqlPrettyWriterTest, using a fluent API for invoking tests --- .../calcite/sql/test/SqlPrettyWriterTest.java | 454 +++++++++++---------- .../calcite/sql/test/SqlPrettyWriterTest.xml | 2 +- 2 files changed, 240 insertions(+), 216 deletions(-) diff --git a/core/src/test/java/org/apache/calcite/sql/test/SqlPrettyWriterTest.java b/core/src/test/java/org/apache/calcite/sql/test/SqlPrettyWriterTest.java index ce7a806..42a5041 100644 --- a/core/src/test/java/org/apache/calcite/sql/test/SqlPrettyWriterTest.java +++ b/core/src/test/java/org/apache/calcite/sql/test/SqlPrettyWriterTest.java @@ -31,6 +31,9 @@ import org.junit.Test; import java.io.PrintWriter; import java.io.StringWriter; +import java.util.Objects; +import java.util.function.Consumer; +import java.util.function.UnaryOperator; import static org.junit.Assert.assertTrue; @@ -42,8 +45,6 @@ import static org.junit.Assert.assertTrue; public class SqlPrettyWriterTest { //~ Static fields/initializers --------------------------------------------- - public static final String NL = System.getProperty("line.separator"); - //~ Constructors ----------------------------------------------------------- public SqlPrettyWriterTest() { @@ -65,289 +66,312 @@ public class SqlPrettyWriterTest { try { node = SqlParser.create(sql).parseQuery(); } catch (SqlParseException e) { - String message = "Received error while parsing SQL '" + sql - + "'; error is:" + NL + e.toString(); + String message = "Received error while parsing SQL '" + sql + "'" + + "; error is:\n" + + e.toString(); throw new AssertionError(message); } return node; } - protected void assertPrintsTo( - boolean newlines, - final String sql, - String expected) { - final SqlNode node = parseQuery(sql); - final SqlPrettyWriter prettyWriter = - new SqlPrettyWriter(AnsiSqlDialect.DEFAULT); - prettyWriter.setAlwaysUseParentheses(false); - if (newlines) { - prettyWriter.setCaseClausesOnNewLines(true); + /** Helper. */ + class Sql { + private final String sql; + private final boolean expr; + private final String desc; + private final String formatted; + private final UnaryOperator<SqlPrettyWriter> transform; + + Sql(String sql, boolean expr, String desc, String formatted, + UnaryOperator<SqlPrettyWriter> transform) { + this.sql = Objects.requireNonNull(sql); + this.expr = expr; + this.desc = desc; + this.formatted = Objects.requireNonNull(formatted); + this.transform = Objects.requireNonNull(transform); + } + + Sql withWriter(Consumer<SqlPrettyWriter> consumer) { + Objects.requireNonNull(consumer); + return new Sql(sql, expr, desc, formatted, w -> { + final SqlPrettyWriter w2 = transform.apply(w); + consumer.accept(w2); + return w2; + }); + } + + Sql expectingDesc(String desc) { + return Objects.equals(this.desc, desc) + ? this + : new Sql(sql, expr, desc, formatted, transform); + } + + Sql withExpr(boolean expr) { + return this.expr == expr + ? this + : new Sql(sql, expr, desc, formatted, transform); + } + + Sql expectingFormatted(String formatted) { + return Objects.equals(this.formatted, formatted) + ? this + : new Sql(sql, expr, desc, formatted, transform); } - String actual = prettyWriter.format(node); - getDiffRepos().assertEquals("formatted", expected, actual); - - // Now parse the result, and make sure it is structurally equivalent - // to the original. - final String actual2 = actual.replaceAll("`", "\""); - final SqlNode node2 = parseQuery(actual2); - assertTrue(node.equalsDeep(node2, Litmus.THROW)); - } - protected void assertExprPrintsTo( - boolean newlines, - final String sql, - String expected) { - final SqlCall valuesCall = (SqlCall) parseQuery("VALUES (" + sql + ")"); - final SqlCall rowCall = valuesCall.operand(0); - final SqlNode node = rowCall.operand(0); - final SqlPrettyWriter prettyWriter = - new SqlPrettyWriter(AnsiSqlDialect.DEFAULT); - prettyWriter.setAlwaysUseParentheses(false); - if (newlines) { - prettyWriter.setCaseClausesOnNewLines(true); + Sql check() { + final SqlPrettyWriter prettyWriter = + transform.apply(new SqlPrettyWriter(AnsiSqlDialect.DEFAULT)); + final SqlNode node; + if (expr) { + final SqlCall valuesCall = (SqlCall) parseQuery("VALUES (" + sql + ")"); + final SqlCall rowCall = valuesCall.operand(0); + node = rowCall.operand(0); + } else { + node = parseQuery(sql); + } + + // Describe settings + if (desc != null) { + final StringWriter sw = new StringWriter(); + final PrintWriter pw = new PrintWriter(sw); + prettyWriter.describe(pw, true); + pw.flush(); + final String desc = sw.toString(); + getDiffRepos().assertEquals("desc", this.desc, desc); + } + + // Format + final String formatted = prettyWriter.format(node); + getDiffRepos().assertEquals("formatted", this.formatted, formatted); + + // Now parse the result, and make sure it is structurally equivalent + // to the original. + final String actual2 = formatted.replaceAll("`", "\""); + final SqlNode node2; + if (expr) { + final SqlCall valuesCall = + (SqlCall) parseQuery("VALUES (" + actual2 + ")"); + final SqlCall rowCall = valuesCall.operand(0); + node2 = rowCall.operand(0); + } else { + node2 = parseQuery(actual2); + } + assertTrue(node.equalsDeep(node2, Litmus.THROW)); + + return this; } - String actual = prettyWriter.format(node); - getDiffRepos().assertEquals("formatted", expected, actual); - - // Now parse the result, and make sure it is structurally equivalent - // to the original. - final String actual2 = actual.replaceAll("`", "\""); - final SqlNode valuesCall2 = parseQuery("VALUES (" + actual2 + ")"); - assertTrue(valuesCall.equalsDeep(valuesCall2, Litmus.THROW)); } - // ~ Tests ---------------------------------------------------------------- + private Sql simple() { + return sql("select x as a, b as b, c as c, d," + + " 'mixed-Case string'," + + " unquotedCamelCaseId," + + " \"quoted id\" " + + "from" + + " (select *" + + " from t" + + " where x = y and a > 5" + + " group by z, zz" + + " window w as (partition by c)," + + " w1 as (partition by c,d order by a, b" + + " range between interval '2:2' hour to minute preceding" + + " and interval '1' day following)) " + + "order by gg"); + } - protected void checkSimple( - SqlPrettyWriter prettyWriter, - String expectedDesc, - String expected) throws Exception { - final SqlNode node = - parseQuery("select x as a, b as b, c as c, d," - + " 'mixed-Case string'," - + " unquotedCamelCaseId," - + " \"quoted id\" " - + "from" - + " (select *" - + " from t" - + " where x = y and a > 5" - + " group by z, zz" - + " window w as (partition by c)," - + " w1 as (partition by c,d order by a, b" - + " range between interval '2:2' hour to minute preceding" - + " and interval '1' day following)) " - + "order by gg"); - - // Describe settings - final StringWriter sw = new StringWriter(); - final PrintWriter pw = new PrintWriter(sw); - prettyWriter.describe(pw, true); - pw.flush(); - String desc = sw.toString(); - getDiffRepos().assertEquals("desc", expectedDesc, desc); - - // Format - String actual = prettyWriter.format(node); - getDiffRepos().assertEquals("formatted", expected, actual); + private Sql sql(String sql) { + return new Sql(sql, false, "${desc}", "${formatted}", w -> w); } - @Test public void testDefault() throws Exception { - final SqlPrettyWriter prettyWriter = - new SqlPrettyWriter(AnsiSqlDialect.DEFAULT); - checkSimple(prettyWriter, "${desc}", "${formatted}"); + private Sql expr(String sql) { + return sql(sql).withExpr(true).expectingDesc(null); } - @Test public void testIndent8() throws Exception { - final SqlPrettyWriter prettyWriter = - new SqlPrettyWriter(AnsiSqlDialect.DEFAULT); - prettyWriter.setIndentation(8); - checkSimple(prettyWriter, "${desc}", "${formatted}"); + // ~ Tests ---------------------------------------------------------------- + + @Test public void testDefault() { + simple().check(); } - @Test public void testClausesNotOnNewLine() throws Exception { - final SqlPrettyWriter prettyWriter = - new SqlPrettyWriter(AnsiSqlDialect.DEFAULT); - prettyWriter.setClauseStartsLine(false); - checkSimple(prettyWriter, "${desc}", "${formatted}"); + @Test public void testIndent8() { + simple() + .withWriter(w -> w.setIndentation(8)) + .check(); } - @Test public void testSelectListItemsOnSeparateLines() throws Exception { - final SqlPrettyWriter prettyWriter = - new SqlPrettyWriter(AnsiSqlDialect.DEFAULT); - prettyWriter.setSelectListItemsOnSeparateLines(true); - checkSimple(prettyWriter, "${desc}", "${formatted}"); + @Test public void testClausesNotOnNewLine() { + simple() + .withWriter(w -> w.setClauseStartsLine(false)) + .check(); } - @Test public void testSelectListExtraIndentFlag() throws Exception { - final SqlPrettyWriter prettyWriter = - new SqlPrettyWriter(AnsiSqlDialect.DEFAULT); - prettyWriter.setSelectListItemsOnSeparateLines(true); - prettyWriter.setSelectListExtraIndentFlag(false); - checkSimple(prettyWriter, "${desc}", "${formatted}"); + @Test public void testSelectListItemsOnSeparateLines() { + simple() + .withWriter(w -> w.setSelectListItemsOnSeparateLines(true)) + .check(); } - @Test public void testKeywordsLowerCase() throws Exception { - final SqlPrettyWriter prettyWriter = - new SqlPrettyWriter(AnsiSqlDialect.DEFAULT); - prettyWriter.setKeywordsLowerCase(true); - checkSimple(prettyWriter, "${desc}", "${formatted}"); + @Test public void testSelectListExtraIndentFlag() { + simple() + .withWriter(w -> w.setSelectListItemsOnSeparateLines(true)) + .withWriter(w -> w.setSelectListExtraIndentFlag(false)) + .check(); } - @Test public void testParenthesizeAllExprs() throws Exception { - final SqlPrettyWriter prettyWriter = - new SqlPrettyWriter(AnsiSqlDialect.DEFAULT); - prettyWriter.setAlwaysUseParentheses(true); - checkSimple(prettyWriter, "${desc}", "${formatted}"); + @Test public void testKeywordsLowerCase() { + simple() + .withWriter(w -> w.setKeywordsLowerCase(true)) + .check(); } - @Test public void testOnlyQuoteIdentifiersWhichNeedIt() throws Exception { - final SqlPrettyWriter prettyWriter = - new SqlPrettyWriter(AnsiSqlDialect.DEFAULT); - prettyWriter.setQuoteAllIdentifiers(false); - checkSimple(prettyWriter, "${desc}", "${formatted}"); + @Test public void testParenthesizeAllExprs() { + simple() + .withWriter(w -> w.setAlwaysUseParentheses(true)) + .check(); } - @Test public void testDamiansSubQueryStyle() throws Exception { + @Test public void testOnlyQuoteIdentifiersWhichNeedIt() { + simple() + .withWriter(w -> w.setQuoteAllIdentifiers(false)) + .check(); + } + + @Test public void testBlackSubQueryStyle() { // Note that ( is at the indent, SELECT is on the same line, and ) is // below it. - final SqlPrettyWriter prettyWriter = - new SqlPrettyWriter(AnsiSqlDialect.DEFAULT); - prettyWriter.setSubQueryStyle(SqlWriter.SubQueryStyle.BLACK); - checkSimple(prettyWriter, "${desc}", "${formatted}"); + simple() + .withWriter(w -> w.setSubQueryStyle(SqlWriter.SubQueryStyle.BLACK)) + .check(); } @Ignore("default SQL parser cannot parse DDL") @Test public void testExplain() { - assertPrintsTo(false, "explain select * from t", "foo"); + sql("explain select * from t") + .check(); } @Test public void testCase() { // Note that CASE is rewritten to the searched form. Wish it weren't // so, but that's beyond the control of the pretty-printer. - assertExprPrintsTo( - true, - "case 1 when 2 + 3 then 4 when case a when b then c else d end then 6 else 7 end", - "CASE" + NL - + "WHEN 1 = 2 + 3" + NL - + "THEN 4" + NL - + "WHEN 1 = CASE" + NL - + " WHEN `A` = `B`" + NL // todo: indent should be 4 not 8 - + " THEN `C`" + NL - + " ELSE `D`" + NL - + " END" + NL - + "THEN 6" + NL - + "ELSE 7" + NL - + "END"); + // todo: indent should be 4 not 8 + final String sql = "case 1\n" + + " when 2 + 3 then 4\n" + + " when case a when b then c else d end then 6\n" + + " else 7\n" + + "end"; + final String formatted = "CASE\n" + + "WHEN 1 = 2 + 3\n" + + "THEN 4\n" + + "WHEN 1 = CASE\n" + + " WHEN `A` = `B`\n" // todo: indent should be 4 not 8 + + " THEN `C`\n" + + " ELSE `D`\n" + + " END\n" + + "THEN 6\n" + + "ELSE 7\n" + + "END"; + expr(sql) + .withWriter(w -> w.setCaseClausesOnNewLines(true)) + .expectingFormatted(formatted) + .check(); } @Test public void testCase2() { - assertExprPrintsTo( - false, - "case 1 when 2 + 3 then 4 when case a when b then c else d end then 6 else 7 end", - "CASE WHEN 1 = 2 + 3 THEN 4 WHEN 1 = CASE WHEN `A` = `B` THEN `C` ELSE `D` END THEN 6 ELSE 7 END"); + final String sql = "case 1" + + " when 2 + 3 then 4" + + " when case a when b then c else d end then 6" + + " else 7 end"; + final String formatted = "CASE WHEN 1 = 2 + 3 THEN 4" + + " WHEN 1 = CASE WHEN `A` = `B` THEN `C` ELSE `D` END THEN 6" + + " ELSE 7 END"; + expr(sql) + .expectingFormatted(formatted) + .check(); } @Test public void testBetween() { - assertExprPrintsTo( - true, - "x not between symmetric y and z", - "`X` NOT BETWEEN SYMMETRIC `Y` AND `Z`"); // todo: remove leading + // todo: remove leading + expr("x not between symmetric y and z") + .expectingFormatted("`X` NOT BETWEEN SYMMETRIC `Y` AND `Z`") + .check(); // space } @Test public void testCast() { - assertExprPrintsTo( - true, - "cast(x + y as decimal(5, 10))", - "CAST(`X` + `Y` AS DECIMAL(5, 10))"); + expr("cast(x + y as decimal(5, 10))") + .expectingFormatted("CAST(`X` + `Y` AS DECIMAL(5, 10))") + .check(); } @Test public void testLiteralChain() { - assertExprPrintsTo( - true, - "'x' /* comment */ 'y'" + NL - + " 'z' ", - "'x'" + NL + "'y'" + NL + "'z'"); + final String sql = "'x' /* comment */ 'y'\n" + + " 'z' "; + final String formatted = "'x'\n" + + "'y'\n" + + "'z'"; + expr(sql).expectingFormatted(formatted).check(); } @Test public void testOverlaps() { - assertExprPrintsTo( - true, - "(x,xx) overlaps (y,yy) or x is not null", - "PERIOD (`X`, `XX`) OVERLAPS PERIOD (`Y`, `YY`) OR `X` IS NOT NULL"); + final String sql = "(x,xx) overlaps (y,yy) or x is not null"; + final String formatted = "PERIOD (`X`, `XX`) OVERLAPS PERIOD (`Y`, `YY`)" + + " OR `X` IS NOT NULL"; + expr(sql).expectingFormatted(formatted).check(); } @Test public void testUnion() { - assertPrintsTo( - true, - "select * from t " - + "union select * from (" - + " select * from u " - + " union select * from v) " - + "union select * from w " - + "order by a, b", - - // todo: SELECT should not be indented from UNION, like this: - // UNION - // SELECT * - // FROM `W` - - "${formatted}"); + // todo: SELECT should not be indented from UNION, like this: + // UNION + // SELECT * + // FROM `W` + final String sql = "select * from t " + + "union select * from (" + + " select * from u " + + " union select * from v) " + + "union select * from w " + + "order by a, b"; + sql(sql) + .expectingDesc(null) + .check(); } @Test public void testMultiset() { - assertPrintsTo( - false, - "values (multiset (select * from t))", - "${formatted}"); + sql("values (multiset (select * from t))") + .expectingDesc(null) + .check(); } @Test public void testInnerJoin() { - assertPrintsTo( - true, - "select * from x inner join y on x.k=y.k", - "${formatted}"); - } - - @Test public void testWhereListItemsOnSeparateLinesOr() throws Exception { - checkPrettySeparateLines( - "select x" - + " from y" - + " where h is not null and i < j" - + " or ((a or b) is true) and d not in (f,g)" - + " or x <> z"); + sql("select * from x inner join y on x.k=y.k") + .expectingDesc(null) + .check(); } - @Test public void testWhereListItemsOnSeparateLinesAnd() throws Exception { - checkPrettySeparateLines( - "select x" - + " from y" - + " where h is not null and (i < j" - + " or ((a or b) is true)) and (d not in (f,g)" - + " or v <> ((w * x) + y) * z)"); + @Test public void testWhereListItemsOnSeparateLinesOr() { + final String sql = "select x" + + " from y" + + " where h is not null and i < j" + + " or ((a or b) is true) and d not in (f,g)" + + " or x <> z"; + sql(sql) + .withWriter(w -> w.setSelectListItemsOnSeparateLines(true)) + .withWriter(w -> w.setSelectListExtraIndentFlag(false)) + .withWriter(w -> w.setWhereListItemsOnSeparateLines(true)) + .check(); } - private void checkPrettySeparateLines(String sql) { - final SqlPrettyWriter prettyWriter = - new SqlPrettyWriter(AnsiSqlDialect.DEFAULT); - prettyWriter.setSelectListItemsOnSeparateLines(true); - prettyWriter.setSelectListExtraIndentFlag(false); - - final SqlNode node = parseQuery(sql); - - // Describe settings - final StringWriter sw = new StringWriter(); - final PrintWriter pw = new PrintWriter(sw); - prettyWriter.describe(pw, true); - pw.flush(); - String desc = sw.toString(); - getDiffRepos().assertEquals("desc", "${desc}", desc); - prettyWriter.setWhereListItemsOnSeparateLines(true); - - // Format - String actual = prettyWriter.format(node); - getDiffRepos().assertEquals("formatted", "${formatted}", actual); + @Test public void testWhereListItemsOnSeparateLinesAnd() { + final String sql = "select x" + + " from y" + + " where h is not null and (i < j" + + " or ((a or b) is true)) and (d not in (f,g)" + + " or v <> ((w * x) + y) * z)"; + sql(sql) + .withWriter(w -> w.setSelectListItemsOnSeparateLines(true)) + .withWriter(w -> w.setSelectListExtraIndentFlag(false)) + .withWriter(w -> w.setWhereListItemsOnSeparateLines(true)) + .check(); } } diff --git a/core/src/test/resources/org/apache/calcite/sql/test/SqlPrettyWriterTest.xml b/core/src/test/resources/org/apache/calcite/sql/test/SqlPrettyWriterTest.xml index 472061d..a349946 100644 --- a/core/src/test/resources/org/apache/calcite/sql/test/SqlPrettyWriterTest.xml +++ b/core/src/test/resources/org/apache/calcite/sql/test/SqlPrettyWriterTest.xml @@ -154,7 +154,7 @@ FROM (SELECT * ORDER BY GG]]> </Resource> </TestCase> - <TestCase name="testDamiansSubQueryStyle"> + <TestCase name="testBlackSubQueryStyle"> <Resource name="desc"/> <Resource name="formatted"> <