blob: ab36f7ea0abeea942526dcee181f9cc468ac5984 [file] [log] [blame]
Austin Engcc2516a2023-10-17 20:57:54 +00001// Copyright 2021 The Dawn & Tint Authors
Ben Claytonb85e6922022-02-02 23:07:11 +00002//
Austin Engcc2516a2023-10-17 20:57:54 +00003// Redistribution and use in source and binary forms, with or without
4// modification, are permitted provided that the following conditions are met:
Ben Claytonb85e6922022-02-02 23:07:11 +00005//
Austin Engcc2516a2023-10-17 20:57:54 +00006// 1. Redistributions of source code must retain the above copyright notice, this
7// list of conditions and the following disclaimer.
Ben Claytonb85e6922022-02-02 23:07:11 +00008//
Austin Engcc2516a2023-10-17 20:57:54 +00009// 2. Redistributions in binary form must reproduce the above copyright notice,
10// this list of conditions and the following disclaimer in the documentation
11// and/or other materials provided with the distribution.
12//
13// 3. Neither the name of the copyright holder nor the names of its
14// contributors may be used to endorse or promote products derived from
15// this software without specific prior written permission.
16//
17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
21// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Ben Claytonb85e6922022-02-02 23:07:11 +000027
28package resolver_test
29
30import (
31 "fmt"
32 "strings"
33 "testing"
34
Ben Claytoncde50092022-07-26 15:46:44 +000035 "dawn.googlesource.com/dawn/tools/src/tint/intrinsic/parser"
36 "dawn.googlesource.com/dawn/tools/src/tint/intrinsic/resolver"
Ben Claytonb85e6922022-02-02 23:07:11 +000037)
38
39func TestResolver(t *testing.T) {
40 type test struct {
41 src string
42 err string
43 }
44
45 success := ""
46 for _, test := range []test{
47 {
48 `type X`,
49 success,
50 }, {
51 `enum E {}`,
52 success,
53 }, {
54 `enum E {A B C}`,
55 success,
56 }, {
57 `type X`,
58 success,
59 }, {
Ben Claytone3e91c02022-06-01 20:44:50 +000060 `@display("Y") type X`,
Ben Claytonb85e6922022-02-02 23:07:11 +000061 success,
62 }, {
63 `
64type x
65match y: x`,
66 success,
67 }, {
68 `
69enum e {a b c}
Ben Claytonc768e642022-07-26 17:49:54 +000070match y: e.c | e.a | e.b`,
Ben Claytonb85e6922022-02-02 23:07:11 +000071 success,
72 }, {
73 `fn f()`,
74 success,
75 }, {
dan sinclair4ac9ba92024-08-19 19:21:19 +000076 `implicit(T) fn f()`,
Ben Claytonb85e6922022-02-02 23:07:11 +000077 success,
78 }, {
79 `
80type f32
Ben Clayton17770f52024-02-20 17:34:27 +000081fn f<T>(T) -> f32`,
82 success,
83 }, {
84 `
85type f32
dan sinclair4ac9ba92024-08-19 19:21:19 +000086implicit(N: num) fn f()`,
Ben Claytonb85e6922022-02-02 23:07:11 +000087 success,
88 }, {
89 `
90enum e { a b c }
dan sinclair4ac9ba92024-08-19 19:21:19 +000091implicit(N: e) fn f()`,
Ben Claytonb85e6922022-02-02 23:07:11 +000092 success,
93 }, {
94 `
95type f32
dan sinclair4ac9ba92024-08-19 19:21:19 +000096implicit(T) fn f(T) -> f32`,
Ben Claytonb85e6922022-02-02 23:07:11 +000097 success,
98 }, {
99 `
100type f32
dan sinclair4ac9ba92024-08-19 19:21:19 +0000101implicit(N: num) fn f<T: f32>()`,
Ben Clayton17770f52024-02-20 17:34:27 +0000102 success,
103 }, {
104 `
105type f32
dan sinclair4ac9ba92024-08-19 19:21:19 +0000106implicit(T: f32) fn f(T: f32) -> f32`,
Ben Clayton17770f52024-02-20 17:34:27 +0000107 success,
108 }, {
109 `
110type f32
Ben Claytonb85e6922022-02-02 23:07:11 +0000111type P<T>
112match m: f32
dan sinclair4ac9ba92024-08-19 19:21:19 +0000113implicit(T: m) fn f(P<T>) -> T`,
Ben Claytonb85e6922022-02-02 23:07:11 +0000114 success,
115 }, {
116 `
Ben Claytonb85e6922022-02-02 23:07:11 +0000117enum e { a }
Ben Claytonc768e642022-07-26 17:49:54 +0000118match m: e.a
119fn f(m)`,
Ben Claytonb85e6922022-02-02 23:07:11 +0000120 success,
121 }, {
122 `
123enum e { a b }
124type T<E: e>
Ben Claytonc768e642022-07-26 17:49:54 +0000125match m: e.a
Ben Claytonb85e6922022-02-02 23:07:11 +0000126fn f(T<m>)`,
127 success,
128 }, {
129 `
130enum e { a }
131type T<E: e>
Ben Claytonc768e642022-07-26 17:49:54 +0000132match m : e.a
133fn f(T<m>)`,
134 success,
135 }, {
136 `
137enum e { a }
138type T<E: e>
139match a : e.a
Ben Claytonb85e6922022-02-02 23:07:11 +0000140fn f(T<a>)`,
141 success,
142 }, {
143 `
144type T<E: num>
dan sinclair4ac9ba92024-08-19 19:21:19 +0000145implicit(E: num) fn f(T<E>)`,
Ben Claytonb85e6922022-02-02 23:07:11 +0000146 success,
147 }, {
dan sinclair4ac9ba92024-08-19 19:21:19 +0000148 `implicit(T) fn f(T)`,
Ben Claytonb85e6922022-02-02 23:07:11 +0000149 success,
150 }, {
151 `
152enum e { a b }
dan sinclair4ac9ba92024-08-19 19:21:19 +0000153implicit(E: e) fn f()`,
Ben Claytonb85e6922022-02-02 23:07:11 +0000154 success,
155 }, {
156 `
157enum e { a b }
Ben Claytonc768e642022-07-26 17:49:54 +0000158match m: e.a | e.b
dan sinclair4ac9ba92024-08-19 19:21:19 +0000159implicit(E: m) fn f()`,
Ben Claytonb85e6922022-02-02 23:07:11 +0000160 success,
161 }, {
162 `
163type f32
164type T<x>
Ben Claytone6e96de2022-05-09 18:08:23 +0000165fn f(T< T<f32> >)`,
Ben Claytonb85e6922022-02-02 23:07:11 +0000166 success,
167 }, {
Ben Clayton5a695972022-05-16 09:48:41 +0000168 `
Ben Clayton17770f52024-02-20 17:34:27 +0000169type a
170type b
171type c
172match S: a | b | c
173type V<N: num, T>
dan sinclair4ac9ba92024-08-19 19:21:19 +0000174implicit(N: num, T: S, U: S) fn f<I: V<N, T> >(V<N, U>) -> I`,
Ben Clayton17770f52024-02-20 17:34:27 +0000175 success,
176 }, {
177 `
Ben Clayton5a695972022-05-16 09:48:41 +0000178type f32
179op -(f32)`,
180 success,
181 }, {
182 `
183type f32
184type T<x>
185op +(T<f32>, T<f32>)`,
186 success,
187 }, {
188 `
189type f32
Ben Clayton54a104e2023-02-22 20:04:40 +0000190ctor f32(f32)`,
Ben Clayton5a695972022-05-16 09:48:41 +0000191 success,
192 }, {
193 `
194type f32
195type T<x>
Ben Clayton54a104e2023-02-22 20:04:40 +0000196ctor f32(T<f32>)`,
Ben Clayton5a695972022-05-16 09:48:41 +0000197 success,
198 }, {
199 `
200type f32
201type i32
202conv f32(i32)`,
203 success,
204 }, {
205 `
206type f32
207type T<x>
208conv f32(T<f32>)`,
209 success,
210 }, {
Ben Claytond8490322023-02-22 13:52:21 +0000211 `
212type f32
213@must_use fn f() -> f32`,
214 success,
215 }, {
Ben Claytonf6c20f12024-02-20 14:45:27 +0000216 `
217type f32
James Price53f93922024-06-11 18:24:06 +0000218@member_function fn f(f32)`,
219 success,
220 }, {
221 `
222type f32
Ben Claytonf6c20f12024-02-20 14:45:27 +0000223type P<T>
224match m: f32
225fn f(m)`,
226 success,
227 }, {
228 `
229type f32
230type P<T>
231match m: f32
232fn f(P<m>)`,
233 success,
234 }, {
Ben Claytonb85e6922022-02-02 23:07:11 +0000235 `enum E {A A}`,
236 `
Ben Claytonc768e642022-07-26 17:49:54 +0000237file.txt:1:11 duplicate enum entry 'A'
Ben Claytonb85e6922022-02-02 23:07:11 +0000238`,
239 },
240 {
241 `type X type X`,
242 `
243file.txt:1:13 'X' already declared
244First declared here: file.txt:1:6`,
245 }, {
Ben Claytone3e91c02022-06-01 20:44:50 +0000246 `@meow type X`,
Ben Claytonb85e6922022-02-02 23:07:11 +0000247 `
Ben Claytone3e91c02022-06-01 20:44:50 +0000248file.txt:1:2 unknown attribute
Ben Claytonb85e6922022-02-02 23:07:11 +0000249`,
250 }, {
Ben Claytone3e91c02022-06-01 20:44:50 +0000251 `@display("Y", "Z") type X`,
Ben Claytonb85e6922022-02-02 23:07:11 +0000252 `
Ben Claytone3e91c02022-06-01 20:44:50 +0000253file.txt:1:2 expected a single value for 'display' attribute`,
Ben Claytonb85e6922022-02-02 23:07:11 +0000254 }, {
255 `
256enum e { a }
257enum e { b }`,
258 `
259file.txt:2:6 'e' already declared
260First declared here: file.txt:1:6`,
261 }, {
262 `
263type X
264match X : X`,
265 `
266file.txt:2:7 'X' already declared
267First declared here: file.txt:1:6`,
268 }, {
269 `type T<X>
270match M : T`,
271 `file.txt:2:11 'T' requires 1 template arguments, but 0 were provided`,
272 }, {
273 `
274match x: y`,
275 `
276file.txt:1:10 cannot resolve 'y'
277`,
278 }, {
279 `
280type a
281match x: a | b`,
282 `
283file.txt:2:14 cannot resolve 'b'
284`,
285 }, {
286 `
287type a
Ben Claytonb85e6922022-02-02 23:07:11 +0000288type b
289match x: a | b | a`,
290 `
291file.txt:3:18 duplicate option 'a' in matcher
292First declared here: file.txt:3:10
293`,
294 }, {
295 `
296enum e { a c }
Ben Claytonc768e642022-07-26 17:49:54 +0000297match x: e.a | e.b | e.c`,
Ben Claytonb85e6922022-02-02 23:07:11 +0000298 `
Ben Claytonc768e642022-07-26 17:49:54 +0000299file.txt:2:18 enum 'e' does not contain 'b'
Ben Claytonb85e6922022-02-02 23:07:11 +0000300`,
301 }, {
302 `
303enum e { a }
Ben Claytonc768e642022-07-26 17:49:54 +0000304match x: e.a
305match x: e.a`,
Ben Claytonb85e6922022-02-02 23:07:11 +0000306 `
307file.txt:3:7 'x' already declared
308First declared here: file.txt:2:7
309`,
310 }, {
311 `
312type t
313match x: t
314match y: x`,
315 `
Ben Claytonc768e642022-07-26 17:49:54 +0000316file.txt:3:10 'x' resolves to type matcher 'x' but type is expected
Ben Claytonb85e6922022-02-02 23:07:11 +0000317`,
318 }, {
319 `fn f(u)`,
320 `file.txt:1:6 cannot resolve 'u'`,
321 }, {
322 `fn f() -> u`,
323 `file.txt:1:11 cannot resolve 'u'`,
324 }, {
dan sinclair4ac9ba92024-08-19 19:21:19 +0000325 `implicit(T: u) fn f()`,
326 `file.txt:1:13 cannot resolve 'u'`,
Ben Claytonb85e6922022-02-02 23:07:11 +0000327 }, {
328 `
329enum e { a }
330fn f() -> e`,
331 `file.txt:2:11 cannot use 'e' as return type. Must be a type or template type`,
332 }, {
333 `
334type T<x>
335fn f(T<u>)`,
336 `file.txt:2:8 cannot resolve 'u'`,
337 }, {
338 `
339type x
dan sinclair4ac9ba92024-08-19 19:21:19 +0000340implicit(T) fn f(T<x>)`,
341 `file.txt:2:18 'T' template parameters do not accept template arguments`,
Ben Claytonb85e6922022-02-02 23:07:11 +0000342 }, {
343 `
344type A<N: num>
345type B
346fn f(A<B>)`,
347 `file.txt:3:8 cannot use type 'B' as template number`,
348 }, {
349 `
Ben Claytonb85e6922022-02-02 23:07:11 +0000350type T
351type P<N: num>
352match m: T
353fn f(P<m>)`,
354 `file.txt:4:8 cannot use type matcher 'm' as template number`,
355 }, {
356 `
357type P<N: num>
358enum E { b }
359fn f(P<E>)`,
360 `file.txt:3:8 cannot use enum 'E' as template number`,
361 }, {
362 `
363type P<N: num>
364enum E { a b }
Ben Claytonc768e642022-07-26 17:49:54 +0000365match m: E.a | E.b
Ben Claytonb85e6922022-02-02 23:07:11 +0000366fn f(P<m>)`,
367 `file.txt:4:8 cannot use enum matcher 'm' as template number`,
368 }, {
369 `
370type P<N: num>
371enum E { a b }
Ben Claytonc768e642022-07-26 17:49:54 +0000372match m: E.a | E.b
dan sinclair4ac9ba92024-08-19 19:21:19 +0000373implicit(M: m) fn f(P<M>)`,
374 `file.txt:4:23 cannot use template enum 'E' as template number`,
Ben Claytonb85e6922022-02-02 23:07:11 +0000375 }, {
376 `
Ben Claytone6e96de2022-05-09 18:08:23 +0000377type i
378enum e { a }
379op << (i) -> e`,
380 `file.txt:3:14 cannot use 'e' as return type. Must be a type or template type`,
381 }, {
382 `
383type T<x>
384op << (T<u>)`,
385 `file.txt:2:10 cannot resolve 'u'`,
386 }, {
387 `
388op << ()`,
389 `file.txt:1:4 operators must have either 1 or 2 parameters`,
390 }, {
391 `
392type i
393op << (i, i, i)`,
394 `file.txt:2:4 operators must have either 1 or 2 parameters`,
395 }, {
396 `
397type x
dan sinclair4ac9ba92024-08-19 19:21:19 +0000398implicit(T) op << (T<x>)`,
399 `file.txt:2:20 'T' template parameters do not accept template arguments`,
Ben Claytone6e96de2022-05-09 18:08:23 +0000400 }, {
401 `
402type A<N: num>
403type B
404op << (A<B>)`,
405 `file.txt:3:10 cannot use type 'B' as template number`,
406 }, {
407 `
408type A<N>
409enum E { b }
Ben Claytonc768e642022-07-26 17:49:54 +0000410match M: E.b
411op << (A<M>)`,
412 `file.txt:4:10 cannot use enum matcher 'M' as template type`,
Ben Claytone6e96de2022-05-09 18:08:23 +0000413 }, {
414 `
415type T
416type P<N: num>
417match m: T
418op << (P<m>)`,
419 `file.txt:4:10 cannot use type matcher 'm' as template number`,
420 }, {
421 `
422type P<N: num>
423enum E { b }
424op << (P<E>)`,
425 `file.txt:3:10 cannot use enum 'E' as template number`,
426 }, {
427 `
428type P<N: num>
429enum E { a b }
Ben Claytonc768e642022-07-26 17:49:54 +0000430match m: E.a | E.b
Ben Claytone6e96de2022-05-09 18:08:23 +0000431op << (P<m>)`,
432 `file.txt:4:10 cannot use enum matcher 'm' as template number`,
433 }, {
434 `
435type P<N: num>
436enum E { a b }
Ben Claytonc768e642022-07-26 17:49:54 +0000437match m: E.a | E.b
dan sinclair4ac9ba92024-08-19 19:21:19 +0000438implicit(M: m) op << (P<M>)`,
439 `file.txt:4:25 cannot use template enum 'E' as template number`,
Ben Claytone6e96de2022-05-09 18:08:23 +0000440 }, {
441 `
Ben Clayton5a695972022-05-16 09:48:41 +0000442type i
443enum e { a }
Ben Clayton54a104e2023-02-22 20:04:40 +0000444ctor F(i) -> e`,
Ben Clayton5a695972022-05-16 09:48:41 +0000445 `file.txt:3:14 cannot use 'e' as return type. Must be a type or template type`,
446 }, {
447 `
448type T<x>
Ben Clayton54a104e2023-02-22 20:04:40 +0000449ctor F(T<u>)`,
Ben Clayton5a695972022-05-16 09:48:41 +0000450 `file.txt:2:10 cannot resolve 'u'`,
451 }, {
452 `
453type x
dan sinclair4ac9ba92024-08-19 19:21:19 +0000454implicit(T) ctor F(T<x>)`,
455 `file.txt:2:20 'T' template parameters do not accept template arguments`,
Ben Clayton5a695972022-05-16 09:48:41 +0000456 }, {
457 `
458type A<N: num>
459type B
Ben Clayton54a104e2023-02-22 20:04:40 +0000460ctor F(A<B>)`,
Ben Clayton5a695972022-05-16 09:48:41 +0000461 `file.txt:3:10 cannot use type 'B' as template number`,
462 }, {
463 `
464type A<N>
465enum E { b }
Ben Claytonc768e642022-07-26 17:49:54 +0000466match M: E.b
Ben Clayton54a104e2023-02-22 20:04:40 +0000467ctor F(A<M>)`,
Ben Claytonc768e642022-07-26 17:49:54 +0000468 `file.txt:4:10 cannot use enum matcher 'M' as template type`,
Ben Clayton5a695972022-05-16 09:48:41 +0000469 }, {
470 `
471type T
472type P<N: num>
473match m: T
Ben Clayton54a104e2023-02-22 20:04:40 +0000474ctor F(P<m>)`,
Ben Clayton5a695972022-05-16 09:48:41 +0000475 `file.txt:4:10 cannot use type matcher 'm' as template number`,
476 }, {
477 `
478type P<N: num>
479enum E { b }
Ben Clayton54a104e2023-02-22 20:04:40 +0000480ctor F(P<E>)`,
Ben Clayton5a695972022-05-16 09:48:41 +0000481 `file.txt:3:10 cannot use enum 'E' as template number`,
482 }, {
483 `
484type P<N: num>
485enum E { a b }
Ben Claytonc768e642022-07-26 17:49:54 +0000486match m: E.a | E.b
Ben Clayton54a104e2023-02-22 20:04:40 +0000487ctor F(P<m>)`,
Ben Clayton5a695972022-05-16 09:48:41 +0000488 `file.txt:4:10 cannot use enum matcher 'm' as template number`,
489 }, {
490 `
491type P<N: num>
492enum E { a b }
Ben Claytonc768e642022-07-26 17:49:54 +0000493match m: E.a | E.b
dan sinclair4ac9ba92024-08-19 19:21:19 +0000494implicit(M: m) ctor F(P<M>)`,
495 `file.txt:4:25 cannot use template enum 'E' as template number`,
Ben Clayton5a695972022-05-16 09:48:41 +0000496 }, {
497 `
498conv F()`,
499 `file.txt:1:6 conversions must have a single parameter`,
500 }, {
501 `
502type i
503conv F(i, i, i)`,
504 `file.txt:2:6 conversions must have a single parameter`,
505 }, {
506 `
507type i
508enum e { a }
509conv F(i) -> e`,
510 `file.txt:3:14 cannot use 'e' as return type. Must be a type or template type`,
511 }, {
512 `
513type T<x>
514conv F(T<u>)`,
515 `file.txt:2:10 cannot resolve 'u'`,
516 }, {
517 `
518type x
dan sinclair4ac9ba92024-08-19 19:21:19 +0000519implicit(T) conv F(T<x>)`,
520 `file.txt:2:20 'T' template parameters do not accept template arguments`,
Ben Clayton5a695972022-05-16 09:48:41 +0000521 }, {
522 `
523type A<N: num>
524type B
525conv F(A<B>)`,
526 `file.txt:3:10 cannot use type 'B' as template number`,
527 }, {
528 `
529type A<N>
530enum E { b }
Ben Claytonc768e642022-07-26 17:49:54 +0000531match M: E.b
532conv F(A<M>)`,
533 `file.txt:4:10 cannot use enum matcher 'M' as template type`,
Ben Clayton5a695972022-05-16 09:48:41 +0000534 }, {
535 `
536type T
537type P<N: num>
538match m: T
539conv F(P<m>)`,
540 `file.txt:4:10 cannot use type matcher 'm' as template number`,
541 }, {
542 `
543type P<N: num>
544enum E { b }
545conv F(P<E>)`,
546 `file.txt:3:10 cannot use enum 'E' as template number`,
547 }, {
548 `
549type P<N: num>
550enum E { a b }
Ben Claytonc768e642022-07-26 17:49:54 +0000551match m: E.a | E.b
Ben Clayton5a695972022-05-16 09:48:41 +0000552conv F(P<m>)`,
553 `file.txt:4:10 cannot use enum matcher 'm' as template number`,
554 }, {
555 `
556type P<N: num>
557enum E { a b }
Ben Claytonc768e642022-07-26 17:49:54 +0000558match m: E.a | E.b
dan sinclair4ac9ba92024-08-19 19:21:19 +0000559implicit(M: m) conv F(P<M>)`,
560 `file.txt:4:25 cannot use template enum 'E' as template number`,
Ben Clayton55ceebe2022-12-14 21:18:23 +0000561 }, {
562 `
Ben Claytond8490322023-02-22 13:52:21 +0000563@must_use fn f()`,
564 `file.txt:1:2 @must_use can only be used on a function with a return type`,
Ben Clayton17770f52024-02-20 17:34:27 +0000565 }, {
566 `
567type f32
James Price53f93922024-06-11 18:24:06 +0000568@member_function(0) fn f(f32)`,
569 `file.txt:2:2 unexpected value for member_function attribute`,
570 }, {
571 `
572@member_function fn f()`,
573 `file.txt:1:2 @member_function can only be used on a function with at least one parameter`,
574 }, {
575 `
dan sinclair4ac9ba92024-08-19 19:21:19 +0000576implicit(T) fn f<T>()`,
577 `file.txt:1:18 'T' already declared
578First declared here: file.txt:1:10`,
Ben Claytonb85e6922022-02-02 23:07:11 +0000579 },
580 } {
581
582 ast, err := parser.Parse(strings.TrimSpace(string(test.src)), "file.txt")
583 if err != nil {
Ben Claytonc768e642022-07-26 17:49:54 +0000584 t.Errorf("While parsing:\n%s\nUnexpected parser error: %v", test.src, err)
Ben Claytonb85e6922022-02-02 23:07:11 +0000585 continue
586 }
587
588 expectErr := strings.TrimSpace(test.err)
589 _, err = resolver.Resolve(ast)
590 if err != nil {
591 gotErr := strings.TrimSpace(fmt.Sprint(err))
592 if gotErr != expectErr {
593 t.Errorf("While parsing:\n%s\nGot error:\n%s\nExpected:\n%s", test.src, gotErr, expectErr)
594 }
595 } else if expectErr != success {
596 t.Errorf("While parsing:\n%s\nGot no error, expected error:\n%s", test.src, expectErr)
597 }
598 }
599}