github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/opt/optgen/lang/scanner_test.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 lang 12 13 import ( 14 "bytes" 15 "fmt" 16 "io" 17 "strconv" 18 "strings" 19 "testing" 20 "testing/iotest" 21 22 "github.com/cockroachdb/datadriven" 23 ) 24 25 func TestScanner(t *testing.T) { 26 datadriven.RunTest(t, "testdata/scanner", func(t *testing.T, d *datadriven.TestData) string { 27 // Only scan command supported. 28 if d.Cmd != "scan" { 29 t.FailNow() 30 } 31 32 // Check for "fail=count" command arg, which indicates reader failure 33 // test case. 34 count := -1 35 for _, arg := range d.CmdArgs { 36 if arg.Key != "fail" || len(arg.Vals) != 1 { 37 t.FailNow() 38 } 39 count, _ = strconv.Atoi(arg.Vals[0]) 40 } 41 42 r := io.Reader(strings.NewReader(d.Input)) 43 if count != -1 { 44 // Wrap the reader in readers that will fail once the specified 45 // count of bytes have been read. 46 r = &errorReader{r: iotest.OneByteReader(r), count: count} 47 } 48 s := NewScanner(r) 49 50 var buf bytes.Buffer 51 for { 52 tok := s.Scan() 53 if tok == EOF { 54 break 55 } 56 57 fmt.Fprintf(&buf, "(%v %s)\n", tok, s.Literal()) 58 59 if tok == ERROR { 60 break 61 } 62 } 63 64 return buf.String() 65 }) 66 } 67 68 // Separate test case for whitespace, since some editors normalize whitespace 69 // in the data driven test case file. 70 func TestScannerWhitespace(t *testing.T) { 71 // Use various ASCII whitespace chars + Unicode whitespace chars. 72 ws := " \t\r\n \u00A0\u1680" 73 s := NewScanner(strings.NewReader(ws)) 74 tok := s.Scan() 75 if tok != WHITESPACE { 76 t.Fatalf("expected whitespace, found %v", tok) 77 } 78 if s.Literal() != ws { 79 t.Fatal("whitespace did not match") 80 } 81 } 82 83 // errorReader returns io.ErrClosedPipe after count reads. 84 type errorReader struct { 85 r io.Reader 86 count int 87 } 88 89 func (r *errorReader) Read(p []byte) (int, error) { 90 r.count-- 91 if r.count <= 0 { 92 return 0, io.ErrClosedPipe 93 } 94 return r.r.Read(p) 95 }