Source file
src/go/build/read_test.go
1
2
3
4
5 package build
6
7 import (
8 "fmt"
9 "go/token"
10 "io"
11 "strings"
12 "testing"
13 )
14
15 const quote = "`"
16
17 type readTest struct {
18
19 in string
20 err string
21 }
22
23 var readGoInfoTests = []readTest{
24 {
25 `package p`,
26 "",
27 },
28 {
29 `package p; import "x"`,
30 "",
31 },
32 {
33 `package p; import . "x"`,
34 "",
35 },
36 {
37 `package p; import "x";ℙvar x = 1`,
38 "",
39 },
40 {
41 `package p
42
43 // comment
44
45 import "x"
46 import _ "x"
47 import a "x"
48
49 /* comment */
50
51 import (
52 "x" /* comment */
53 _ "x"
54 a "x" // comment
55 ` + quote + `x` + quote + `
56 _ /*comment*/ ` + quote + `x` + quote + `
57 a ` + quote + `x` + quote + `
58 )
59 import (
60 )
61 import ()
62 import()import()import()
63 import();import();import()
64
65 ℙvar x = 1
66 `,
67 "",
68 },
69 {
70 "\ufeff𝔻" + `package p; import "x";ℙvar x = 1`,
71 "",
72 },
73 }
74
75 var readCommentsTests = []readTest{
76 {
77 `ℙpackage p`,
78 "",
79 },
80 {
81 `ℙpackage p; import "x"`,
82 "",
83 },
84 {
85 `ℙpackage p; import . "x"`,
86 "",
87 },
88 {
89 "\ufeff𝔻" + `ℙpackage p; import . "x"`,
90 "",
91 },
92 {
93 `// foo
94
95 /* bar */
96
97 /* quux */ // baz
98
99 /*/ zot */
100
101 // asdf
102 ℙHello, world`,
103 "",
104 },
105 {
106 "\ufeff𝔻" + `// foo
107
108 /* bar */
109
110 /* quux */ // baz
111
112 /*/ zot */
113
114 // asdf
115 ℙHello, world`,
116 "",
117 },
118 }
119
120 func testRead(t *testing.T, tests []readTest, read func(io.Reader) ([]byte, error)) {
121 for i, tt := range tests {
122 beforeP, afterP, _ := strings.Cut(tt.in, "ℙ")
123 in := beforeP + afterP
124 testOut := beforeP
125
126 if beforeD, afterD, ok := strings.Cut(beforeP, "𝔻"); ok {
127 in = beforeD + afterD + afterP
128 testOut = afterD
129 }
130
131 r := strings.NewReader(in)
132 buf, err := read(r)
133 if err != nil {
134 if tt.err == "" {
135 t.Errorf("#%d: err=%q, expected success (%q)", i, err, string(buf))
136 } else if !strings.Contains(err.Error(), tt.err) {
137 t.Errorf("#%d: err=%q, expected %q", i, err, tt.err)
138 }
139 continue
140 }
141 if tt.err != "" {
142 t.Errorf("#%d: success, expected %q", i, tt.err)
143 continue
144 }
145
146 out := string(buf)
147 if out != testOut {
148 t.Errorf("#%d: wrong output:\nhave %q\nwant %q\n", i, out, testOut)
149 }
150 }
151 }
152
153 func TestReadGoInfo(t *testing.T) {
154 testRead(t, readGoInfoTests, func(r io.Reader) ([]byte, error) {
155 var info fileInfo
156 err := readGoInfo(r, &info)
157 return info.header, err
158 })
159 }
160
161 func TestReadComments(t *testing.T) {
162 testRead(t, readCommentsTests, readComments)
163 }
164
165 var readFailuresTests = []readTest{
166 {
167 `package`,
168 "syntax error",
169 },
170 {
171 "package p\n\x00\nimport `math`\n",
172 "unexpected NUL in input",
173 },
174 {
175 `package p; import`,
176 "syntax error",
177 },
178 {
179 `package p; import "`,
180 "syntax error",
181 },
182 {
183 "package p; import ` \n\n",
184 "syntax error",
185 },
186 {
187 `package p; import "x`,
188 "syntax error",
189 },
190 {
191 `package p; import _`,
192 "syntax error",
193 },
194 {
195 `package p; import _ "`,
196 "syntax error",
197 },
198 {
199 `package p; import _ "x`,
200 "syntax error",
201 },
202 {
203 `package p; import .`,
204 "syntax error",
205 },
206 {
207 `package p; import . "`,
208 "syntax error",
209 },
210 {
211 `package p; import . "x`,
212 "syntax error",
213 },
214 {
215 `package p; import (`,
216 "syntax error",
217 },
218 {
219 `package p; import ("`,
220 "syntax error",
221 },
222 {
223 `package p; import ("x`,
224 "syntax error",
225 },
226 {
227 `package p; import ("x"`,
228 "syntax error",
229 },
230 }
231
232 func TestReadFailuresIgnored(t *testing.T) {
233
234
235
236 tests := make([]readTest, len(readFailuresTests))
237 copy(tests, readFailuresTests)
238 for i := range tests {
239 tt := &tests[i]
240 if !strings.Contains(tt.err, "NUL") {
241 tt.err = ""
242 }
243 }
244 testRead(t, tests, func(r io.Reader) ([]byte, error) {
245 var info fileInfo
246 err := readGoInfo(r, &info)
247 return info.header, err
248 })
249 }
250
251 var readEmbedTests = []struct {
252 in, out string
253 }{
254 {
255 "package p\n",
256 "",
257 },
258 {
259 "package p\nimport \"embed\"\nvar i int\n//go:embed x y z\nvar files embed.FS",
260 `test:4:12:x
261 test:4:14:y
262 test:4:16:z`,
263 },
264 {
265 "package p\nimport \"embed\"\nvar i int\n//go:embed x \"\\x79\" `z`\nvar files embed.FS",
266 `test:4:12:x
267 test:4:14:y
268 test:4:21:z`,
269 },
270 {
271 "package p\nimport \"embed\"\nvar i int\n//go:embed x y\n//go:embed z\nvar files embed.FS",
272 `test:4:12:x
273 test:4:14:y
274 test:5:12:z`,
275 },
276 {
277 "package p\nimport \"embed\"\nvar i int\n\t //go:embed x y\n\t //go:embed z\n\t var files embed.FS",
278 `test:4:14:x
279 test:4:16:y
280 test:5:14:z`,
281 },
282 {
283 "package p\nimport \"embed\"\n//go:embed x y z\nvar files embed.FS",
284 `test:3:12:x
285 test:3:14:y
286 test:3:16:z`,
287 },
288 {
289 "\ufeffpackage p\nimport \"embed\"\n//go:embed x y z\nvar files embed.FS",
290 `test:3:12:x
291 test:3:14:y
292 test:3:16:z`,
293 },
294 {
295 "package p\nimport \"embed\"\nvar s = \"/*\"\n//go:embed x\nvar files embed.FS",
296 `test:4:12:x`,
297 },
298 {
299 `package p
300 import "embed"
301 var s = "\"\\\\"
302 //go:embed x
303 var files embed.FS`,
304 `test:4:15:x`,
305 },
306 {
307 "package p\nimport \"embed\"\nvar s = `/*`\n//go:embed x\nvar files embed.FS",
308 `test:4:12:x`,
309 },
310 {
311 "package p\nimport \"embed\"\nvar s = z/ *y\n//go:embed pointer\nvar pointer embed.FS",
312 "test:4:12:pointer",
313 },
314 {
315 "package p\n//go:embed x y z\n",
316 "",
317 },
318 {
319 "package p\n//go:embed x y z\nvar files embed.FS",
320 "",
321 },
322 {
323 "\ufeffpackage p\n//go:embed x y z\nvar files embed.FS",
324 "",
325 },
326 }
327
328 func TestReadEmbed(t *testing.T) {
329 fset := token.NewFileSet()
330 for i, tt := range readEmbedTests {
331 info := fileInfo{
332 name: "test",
333 fset: fset,
334 }
335 err := readGoInfo(strings.NewReader(tt.in), &info)
336 if err != nil {
337 t.Errorf("#%d: %v", i, err)
338 continue
339 }
340 b := &strings.Builder{}
341 sep := ""
342 for _, emb := range info.embeds {
343 fmt.Fprintf(b, "%s%v:%s", sep, emb.pos, emb.pattern)
344 sep = "\n"
345 }
346 got := b.String()
347 want := strings.Join(strings.Fields(tt.out), "\n")
348 if got != want {
349 t.Errorf("#%d: embeds:\n%s\nwant:\n%s", i, got, want)
350 }
351 }
352 }
353
View as plain text