You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by jh...@apache.org on 2019/10/27 00:24:51 UTC

[calcite] 01/02: Refactor SqlPrettyWriterTest, using a fluent API for invoking tests

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 <jh...@apache.org>
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">
       <![CDATA[SELECT `X` AS `A`, `B` AS `B`, `C` AS `C`, `D`, 'mixed-Case string', `UNQUOTEDCAMELCASEID`, `quoted id`