1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 package parser
34
35 import (
36 "regexp"
37 "testing"
38
39 "cuelang.org/go/cue/errors"
40 "cuelang.org/go/cue/scanner"
41 "cuelang.org/go/cue/token"
42 "cuelang.org/go/internal/source"
43 )
44
45 func getPos(f *token.File, offset int) token.Pos {
46 if f != nil {
47 return f.Pos(offset, 0)
48 }
49 return token.NoPos
50 }
51
52
53
54
55
56
57 var errRx = regexp.MustCompile(`^/\* *ERROR *(HERE)? *"([^"]*)" *\*/$`)
58
59
60
61 func expectedErrors(t *testing.T, file *token.File, src []byte) map[token.Pos]string {
62 errors := make(map[token.Pos]string)
63
64 var s scanner.Scanner
65
66
67
68
69 s.Init(file, src, nil, scanner.ScanComments)
70 var prev token.Pos
71 var here token.Pos
72
73 for {
74 pos, tok, lit := s.Scan()
75 pos = pos.WithRel(0)
76 switch tok {
77 case token.EOF:
78 return errors
79 case token.COMMENT:
80 s := errRx.FindStringSubmatch(lit)
81 if len(s) == 3 {
82 pos := prev
83 if s[1] == "HERE" {
84 pos = here
85 }
86 errors[pos] = string(s[2])
87 }
88 default:
89 prev = pos
90 var l int
91 if tok.IsLiteral() {
92 l = len(lit)
93 } else {
94 l = len(tok.String())
95 }
96 here = prev.Add(l)
97 }
98 }
99 }
100
101
102
103 func compareErrors(t *testing.T, file *token.File, expected map[token.Pos]string, found []errors.Error) {
104 t.Helper()
105 for _, error := range found {
106
107
108 ePos := error.Position()
109 eMsg := error.Error()
110 pos := getPos(file, ePos.Offset()).WithRel(0)
111 if msg, found := expected[pos]; found {
112
113 rx, err := regexp.Compile(msg)
114 if err != nil {
115 t.Errorf("%s: %v", ePos, err)
116 continue
117 }
118 if match := rx.MatchString(eMsg); !match {
119 t.Errorf("%s: %q does not match %q", ePos, eMsg, msg)
120 continue
121 }
122
123 delete(expected, pos)
124 } else {
125
126
127
128
129 t.Errorf("%s: unexpected error: -%q-", ePos, eMsg)
130 }
131 }
132
133
134 if len(expected) > 0 {
135 t.Errorf("%d errors not reported:", len(expected))
136 for pos, msg := range expected {
137 t.Errorf("%s: -%q-\n", pos, msg)
138 }
139 }
140 }
141
142 func checkErrors(t *testing.T, filename string, input interface{}) {
143 t.Helper()
144 src, err := source.Read(filename, input)
145 if err != nil {
146 t.Error(err)
147 return
148 }
149
150 f, err := ParseFile(filename, src, DeclarationErrors, AllErrors)
151 file := f.Pos().File()
152 found := errors.Errors(err)
153
154
155
156 if file == nil {
157 t.Fatal("no token.File for ast.File")
158 }
159 expected := expectedErrors(t, file, src)
160
161
162 compareErrors(t, file, expected, found)
163 }
164
165 func TestFuzz(t *testing.T) {
166 testCases := []string{
167 "(({\"\\(0)\"(",
168 "{{\"\\(0\xbf\"(",
169 "a:y for x n{b:\"\"(\"\\(" +
170 "\"\"\\\"(",
171 }
172 for _, tc := range testCases {
173 t.Run("", func(t *testing.T) {
174 _, _ = ParseFile("go-fuzz", []byte(tc))
175 })
176 }
177 }
178
View as plain text