github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/testutils/sqlutils/pretty.go (about)

     1  // Copyright 2018 The Cockroach Authors.
     2  //
     3  // Use of this software is governed by the Business Source License
     4  // included in the file licenses/BSL.txt.
     5  //
     6  // As of the Change Date specified in that file, in accordance with
     7  // the Business Source License, use of this software will be governed
     8  // by the Apache License, Version 2.0, included in the file
     9  // licenses/APL.txt.
    10  
    11  package sqlutils
    12  
    13  import (
    14  	"testing"
    15  
    16  	"github.com/cockroachdb/cockroach/pkg/sql/parser"
    17  	"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
    18  )
    19  
    20  // VerifyStatementPrettyRoundtrip verifies that the SQL statements in s
    21  // correctly round trip through the pretty printer.
    22  func VerifyStatementPrettyRoundtrip(t *testing.T, sql string) {
    23  	t.Helper()
    24  
    25  	stmts, err := parser.Parse(sql)
    26  	if err != nil {
    27  		t.Fatalf("%s: %s", err, sql)
    28  	}
    29  	cfg := tree.DefaultPrettyCfg()
    30  	// Be careful to not simplify otherwise the tests won't round trip.
    31  	cfg.Simplify = false
    32  	for i := range stmts {
    33  		// Dataflow of the statement through these checks:
    34  		//
    35  		//             sql (from test file)
    36  		//              |
    37  		//          (parser.Parse)
    38  		//              v
    39  		//           origStmt
    40  		//          /         \
    41  		//    (cfg.Pretty)    (AsStringWithFlags,FmtParsable)
    42  		//       v                          |
    43  		//    prettyStmt                    |
    44  		//       |                          |
    45  		// (parser.ParseOne)                |
    46  		//       v                          |
    47  		//   parsedPretty                   |
    48  		//       |                          |
    49  		// (AsStringWithFlags,FmtSimple)    |
    50  		//       v                          v
    51  		//   prettyFormatted          origFormatted
    52  		//
    53  		// == Check 1: prettyFormatted == origFormatted
    54  		// If false:
    55  		//
    56  		//       |                          |
    57  		//       |                   (parser.ParseOne)
    58  		//       |                          v
    59  		//       |                    reparsedStmt
    60  		//       |                          |
    61  		//       |                 (AsStringWithFlags,FmtParsable)
    62  		//       v                          v
    63  		//   prettyFormatted           origFormatted
    64  		//
    65  		// == Check 2: prettyFormatted == origFormatted
    66  		//
    67  		origStmt := stmts[i].AST
    68  		// Be careful to not simplify otherwise the tests won't round trip.
    69  		prettyStmt := cfg.Pretty(origStmt)
    70  		parsedPretty, err := parser.ParseOne(prettyStmt)
    71  		if err != nil {
    72  			t.Fatalf("%s: %s", err, prettyStmt)
    73  		}
    74  		prettyFormatted := tree.AsStringWithFlags(parsedPretty.AST, tree.FmtSimple)
    75  		origFormatted := tree.AsStringWithFlags(origStmt, tree.FmtParsable)
    76  		if prettyFormatted != origFormatted {
    77  			// Type annotations and unicode strings don't round trip well. Sometimes we
    78  			// need to reparse the original formatted output and format that for these
    79  			// to match.
    80  			reparsedStmt, err := parser.ParseOne(origFormatted)
    81  			if err != nil {
    82  				t.Fatal(err)
    83  			}
    84  			origFormatted = tree.AsStringWithFlags(reparsedStmt.AST, tree.FmtParsable)
    85  			if prettyFormatted != origFormatted {
    86  				t.Fatalf("orig formatted != pretty formatted\norig SQL: %q\norig formatted: %q\npretty printed: %s\npretty formatted: %q",
    87  					sql,
    88  					origFormatted,
    89  					prettyStmt,
    90  					prettyFormatted,
    91  				)
    92  			}
    93  		}
    94  	}
    95  }