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 var in, testOut string
123 j := strings.Index(tt.in, "ℙ")
124 if j < 0 {
125 in = tt.in
126 testOut = tt.in
127 } else {
128 in = tt.in[:j] + tt.in[j+len("ℙ"):]
129 testOut = tt.in[:j]
130 }
131 d := strings.Index(tt.in, "𝔻")
132 if d >= 0 {
133 in = in[:d] + in[d+len("𝔻"):]
134 testOut = testOut[d+len("𝔻"):]
135 }
136 r := strings.NewReader(in)
137 buf, err := read(r)
138 if err != nil {
139 if tt.err == "" {
140 t.Errorf("#%d: err=%q, expected success (%q)", i, err, string(buf))
141 } else if !strings.Contains(err.Error(), tt.err) {
142 t.Errorf("#%d: err=%q, expected %q", i, err, tt.err)
143 }
144 continue
145 }
146 if tt.err != "" {
147 t.Errorf("#%d: success, expected %q", i, tt.err)
148 continue
149 }
150
151 out := string(buf)
152 if out != testOut {
153 t.Errorf("#%d: wrong output:\nhave %q\nwant %q\n", i, out, testOut)
154 }
155 }
156 }
157
158 func TestReadGoInfo(t *testing.T) {
159 testRead(t, readGoInfoTests, func(r io.Reader) ([]byte, error) {
160 var info fileInfo
161 err := readGoInfo(r, &info)
162 return info.header, err
163 })
164 }
165
166 func TestReadComments(t *testing.T) {
167 testRead(t, readCommentsTests, readComments)
168 }
169
170 var readFailuresTests = []readTest{
171 {
172 `package`,
173 "syntax error",
174 },
175 {
176 "package p\n\x00\nimport `math`\n",
177 "unexpected NUL in input",
178 },
179 {
180 `package p; import`,
181 "syntax error",
182 },
183 {
184 `package p; import "`,
185 "syntax error",
186 },
187 {
188 "package p; import ` \n\n",
189 "syntax error",
190 },
191 {
192 `package p; import "x`,
193 "syntax error",
194 },
195 {
196 `package p; import _`,
197 "syntax error",
198 },
199 {
200 `package p; import _ "`,
201 "syntax error",
202 },
203 {
204 `package p; import _ "x`,
205 "syntax error",
206 },
207 {
208 `package p; import .`,
209 "syntax error",
210 },
211 {
212 `package p; import . "`,
213 "syntax error",
214 },
215 {
216 `package p; import . "x`,
217 "syntax error",
218 },
219 {
220 `package p; import (`,
221 "syntax error",
222 },
223 {
224 `package p; import ("`,
225 "syntax error",
226 },
227 {
228 `package p; import ("x`,
229 "syntax error",
230 },
231 {
232 `package p; import ("x"`,
233 "syntax error",
234 },
235 }
236
237 func TestReadFailuresIgnored(t *testing.T) {
238
239
240
241 tests := make([]readTest, len(readFailuresTests))
242 copy(tests, readFailuresTests)
243 for i := range tests {
244 tt := &tests[i]
245 if !strings.Contains(tt.err, "NUL") {
246 tt.err = ""
247 }
248 }
249 testRead(t, tests, func(r io.Reader) ([]byte, error) {
250 var info fileInfo
251 err := readGoInfo(r, &info)
252 return info.header, err
253 })
254 }
255
256 var readEmbedTests = []struct {
257 in, out string
258 }{
259 {
260 "package p\n",
261 "",
262 },
263 {
264 "package p\nimport \"embed\"\nvar i int\n//go:embed x y z\nvar files embed.FS",
265 `test:4:12:x
266 test:4:14:y
267 test:4:16:z`,
268 },
269 {
270 "package p\nimport \"embed\"\nvar i int\n//go:embed x \"\\x79\" `z`\nvar files embed.FS",
271 `test:4:12:x
272 test:4:14:y
273 test:4:21:z`,
274 },
275 {
276 "package p\nimport \"embed\"\nvar i int\n//go:embed x y\n//go:embed z\nvar files embed.FS",
277 `test:4:12:x
278 test:4:14:y
279 test:5:12:z`,
280 },
281 {
282 "package p\nimport \"embed\"\nvar i int\n\t //go:embed x y\n\t //go:embed z\n\t var files embed.FS",
283 `test:4:14:x
284 test:4:16:y
285 test:5:14:z`,
286 },
287 {
288 "package p\nimport \"embed\"\n//go:embed x y z\nvar files embed.FS",
289 `test:3:12:x
290 test:3:14:y
291 test:3:16:z`,
292 },
293 {
294 "\ufeffpackage p\nimport \"embed\"\n//go:embed x y z\nvar files embed.FS",
295 `test:3:12:x
296 test:3:14:y
297 test:3:16:z`,
298 },
299 {
300 "package p\nimport \"embed\"\nvar s = \"/*\"\n//go:embed x\nvar files embed.FS",
301 `test:4:12:x`,
302 },
303 {
304 `package p
305 import "embed"
306 var s = "\"\\\\"
307 //go:embed x
308 var files embed.FS`,
309 `test:4:15:x`,
310 },
311 {
312 "package p\nimport \"embed\"\nvar s = `/*`\n//go:embed x\nvar files embed.FS",
313 `test:4:12:x`,
314 },
315 {
316 "package p\nimport \"embed\"\nvar s = z/ *y\n//go:embed pointer\nvar pointer embed.FS",
317 "test:4:12:pointer",
318 },
319 {
320 "package p\n//go:embed x y z\n",
321 "",
322 },
323 {
324 "package p\n//go:embed x y z\nvar files embed.FS",
325 "",
326 },
327 {
328 "\ufeffpackage p\n//go:embed x y z\nvar files embed.FS",
329 "",
330 },
331 }
332
333 func TestReadEmbed(t *testing.T) {
334 fset := token.NewFileSet()
335 for i, tt := range readEmbedTests {
336 info := fileInfo{
337 name: "test",
338 fset: fset,
339 }
340 err := readGoInfo(strings.NewReader(tt.in), &info)
341 if err != nil {
342 t.Errorf("#%d: %v", i, err)
343 continue
344 }
345 b := &strings.Builder{}
346 sep := ""
347 for _, emb := range info.embeds {
348 fmt.Fprintf(b, "%s%v:%s", sep, emb.pos, emb.pattern)
349 sep = "\n"
350 }
351 got := b.String()
352 want := strings.Join(strings.Fields(tt.out), "\n")
353 if got != want {
354 t.Errorf("#%d: embeds:\n%s\nwant:\n%s", i, got, want)
355 }
356 }
357 }
358
View as plain text