From 84c0c44ee1cfc35c6bebd31f36470e22cb3966e2 Mon Sep 17 00:00:00 2001 From: ritwizsinha Date: Fri, 10 Sep 2021 17:52:15 +0530 Subject: [PATCH] Added auxilary code to run tests Signed-off-by: ritwizsinha --- go/vt/sqlparser/parse_test.go | 167 +++++++++++++++++++++++ go/vt/sqlparser/testdata/union_cases.txt | 6 + 2 files changed, 173 insertions(+) create mode 100644 go/vt/sqlparser/testdata/union_cases.txt diff --git a/go/vt/sqlparser/parse_test.go b/go/vt/sqlparser/parse_test.go index bec7ca8f569..a77df606902 100644 --- a/go/vt/sqlparser/parse_test.go +++ b/go/vt/sqlparser/parse_test.go @@ -21,7 +21,9 @@ import ( "bytes" "compress/gzip" "fmt" + "github.com/google/go-cmp/cmp" "io" + "io/ioutil" "math/rand" "os" "path" @@ -3492,3 +3494,168 @@ func BenchmarkParse3(b *testing.B) { largeQueryBenchmark(b, true) }) } + +func TestValidCases(t *testing.T) { + testOutputTempDir, err := ioutil.TempDir("", "parse_test") + require.NoError(t, err) + defer func() { + if !t.Failed() { + os.RemoveAll(testOutputTempDir) + } + }() + + testFile(t, "union_cases.txt", testOutputTempDir) +} +type testCase struct { + file string + lineno int + input string + output string + errStr string + comments string +} +func escapeNewLines(in string) string { + return strings.ReplaceAll(in, "\n", "\\n") +} + +func testFile(t *testing.T, filename, tempDir string) { + t.Run(filename, func(t *testing.T) { + fail := false + expected := strings.Builder{} + for tcase := range iterateExecFile(filename) { + t.Run(fmt.Sprintf("%d : %s", tcase.lineno, tcase.comments), func(t *testing.T) { + if tcase.output == "" && tcase.errStr == "" { + tcase.output = tcase.input + } + expected.WriteString(fmt.Sprintf("%sINPUT\n%sEND\n", tcase.comments, escapeNewLines(tcase.input))) + tree, err := Parse(tcase.input) + if tcase.errStr != "" { + expected.WriteString(fmt.Sprintf("ERROR\n%sEND\n", escapeNewLines(err.Error()))) + if err == nil || tcase.errStr != err.Error() { + fail = true + t.Errorf("File: %s, Line: %d\nDiff:\n%s\n[%s] \n[%s]", filename, tcase.lineno, cmp.Diff(tcase.errStr, err.Error()), tcase.errStr, err.Error()) + } + } else { + if err != nil { + expected.WriteString(fmt.Sprintf("ERROR\n%sEND\n", escapeNewLines(err.Error()))) + fail = true + t.Errorf("File: %s, Line: %d\nDiff:\n%s\n[%s] \n[%s]", filename, tcase.lineno, cmp.Diff(tcase.errStr, err.Error()), tcase.errStr, err.Error()) + } else { + out := String(tree) + expected.WriteString(fmt.Sprintf("OUTPUT\n%sEND\n", escapeNewLines(out))) + if tcase.output != out { + fail = true + t.Errorf("Parsing failed. \nExpected/Got:\n%s\n%s", tcase.output, out) + } + } + } + }) + } + + if fail && tempDir != "" { + gotFile := fmt.Sprintf("%s/%s", tempDir, filename) + _ = ioutil.WriteFile(gotFile, []byte(strings.TrimSpace(expected.String())+"\n"), 0644) + fmt.Println(fmt.Sprintf("Errors found in parse tests. If the output is correct, run `cp %s/* testdata/` to update test expectations", tempDir)) // nolint + } + }) +} + +func iterateExecFile(name string) (testCaseIterator chan testCase) { + name = locateFile(name) + fd, err := os.OpenFile(name, os.O_RDONLY, 0) + if err != nil { + panic(fmt.Sprintf("Could not open file %s", name)) + } + testCaseIterator = make(chan testCase) + var comments string + go func() { + defer close(testCaseIterator) + + r := bufio.NewReader(fd) + lineno := 0 + for { + binput, err := r.ReadBytes('\n') + if err != nil { + if err != io.EOF { + panic(fmt.Errorf("error reading file %s: line %d: %s", name, lineno, err.Error())) + } + break + } + lineno++ + input := string(binput) + if input == "" || input == "\n" { + continue + } + if input[0] == '#' { + comments = comments + input + continue + } + input, lineno, _ = parsePartial(r, []string{"INPUT"}, lineno, name) + output, lineno, returnTypeNumber := parsePartial(r, []string{"OUTPUT, ERROR"}, lineno, name) + var errStr string + if returnTypeNumber == 1 { + errStr = output + output = "" + } + testCaseIterator <- testCase{ + file: name, + lineno: lineno, + input: input, + comments: comments, + output: output, + errStr: errStr, + + } + comments = "" + } + }() + return testCaseIterator +} + +func parsePartial(r *bufio.Reader, readType []string, lineno int, fileName string) (string, int, int) { + var returnTypeNumber int + for { + binput, err := r.ReadBytes('\n') + if err != nil { + if err != io.EOF { + panic(fmt.Errorf("error reading file %s: line %d: %s", fileName, lineno, err.Error())) + } + break + } + lineno++ + input := string(binput) + if input == "" || input == "\n" { + continue + } + input = strings.TrimSpace(input) + for i, str := range readType { + if input == str { + returnTypeNumber = i + break + } + } + panic(fmt.Errorf("error reading file %s: line %d: %s - Expected keyword", fileName, lineno, err.Error())) + } + input := "" + for { + l, err := r.ReadBytes('\n') + lineno++ + if err != nil { + panic(fmt.Sprintf("error reading file %s line# %d: %s", fileName, lineno, err.Error())) + } + str := strings.TrimSpace(string(l)) + if str == "END" { + break + } + if input == "" { + input += str + } else { + input += str + "\n" + } + } + return input, lineno, returnTypeNumber +} + +func locateFile(name string) string { + return "testdata/" + name +} diff --git a/go/vt/sqlparser/testdata/union_cases.txt b/go/vt/sqlparser/testdata/union_cases.txt new file mode 100644 index 00000000000..58222fde730 --- /dev/null +++ b/go/vt/sqlparser/testdata/union_cases.txt @@ -0,0 +1,6 @@ +INPUT +select 1 from dual union select 2 from dual +END +OUTPUT +select 1 from dual union select 2 from dual +END