1 // Copyright 2020 The Tint Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "src/reader/wgsl/parser_impl_test_helper.h"
16
17 namespace tint {
18 namespace reader {
19 namespace wgsl {
20 namespace {
21
TEST_F(ParserImplTest,Decoration_Location)22 TEST_F(ParserImplTest, Decoration_Location) {
23 auto p = parser("location(4)");
24 auto deco = p->decoration();
25 EXPECT_TRUE(deco.matched);
26 EXPECT_FALSE(deco.errored);
27 ASSERT_NE(deco.value, nullptr);
28 auto* var_deco = deco.value->As<ast::Decoration>();
29 ASSERT_NE(var_deco, nullptr);
30 ASSERT_FALSE(p->has_error());
31 ASSERT_TRUE(var_deco->Is<ast::LocationDecoration>());
32
33 auto* loc = var_deco->As<ast::LocationDecoration>();
34 EXPECT_EQ(loc->value, 4u);
35 }
36
TEST_F(ParserImplTest,Decoration_Location_MissingLeftParen)37 TEST_F(ParserImplTest, Decoration_Location_MissingLeftParen) {
38 auto p = parser("location 4)");
39 auto deco = p->decoration();
40 EXPECT_FALSE(deco.matched);
41 EXPECT_TRUE(deco.errored);
42 EXPECT_EQ(deco.value, nullptr);
43 EXPECT_TRUE(p->has_error());
44 EXPECT_EQ(p->error(), "1:10: expected '(' for location decoration");
45 }
46
TEST_F(ParserImplTest,Decoration_Location_MissingRightParen)47 TEST_F(ParserImplTest, Decoration_Location_MissingRightParen) {
48 auto p = parser("location(4");
49 auto deco = p->decoration();
50 EXPECT_FALSE(deco.matched);
51 EXPECT_TRUE(deco.errored);
52 EXPECT_EQ(deco.value, nullptr);
53 EXPECT_TRUE(p->has_error());
54 EXPECT_EQ(p->error(), "1:11: expected ')' for location decoration");
55 }
56
TEST_F(ParserImplTest,Decoration_Location_MissingValue)57 TEST_F(ParserImplTest, Decoration_Location_MissingValue) {
58 auto p = parser("location()");
59 auto deco = p->decoration();
60 EXPECT_FALSE(deco.matched);
61 EXPECT_TRUE(deco.errored);
62 EXPECT_EQ(deco.value, nullptr);
63 EXPECT_TRUE(p->has_error());
64 EXPECT_EQ(p->error(),
65 "1:10: expected signed integer literal for location decoration");
66 }
67
TEST_F(ParserImplTest,Decoration_Location_MissingInvalid)68 TEST_F(ParserImplTest, Decoration_Location_MissingInvalid) {
69 auto p = parser("location(nan)");
70 auto deco = p->decoration();
71 EXPECT_FALSE(deco.matched);
72 EXPECT_TRUE(deco.errored);
73 EXPECT_EQ(deco.value, nullptr);
74 EXPECT_TRUE(p->has_error());
75 EXPECT_EQ(p->error(),
76 "1:10: expected signed integer literal for location decoration");
77 }
78
79 struct BuiltinData {
80 const char* input;
81 ast::Builtin result;
82 };
operator <<(std::ostream & out,BuiltinData data)83 inline std::ostream& operator<<(std::ostream& out, BuiltinData data) {
84 out << std::string(data.input);
85 return out;
86 }
87
88 class BuiltinTest : public ParserImplTestWithParam<BuiltinData> {};
89
TEST_P(BuiltinTest,Decoration_Builtin)90 TEST_P(BuiltinTest, Decoration_Builtin) {
91 auto params = GetParam();
92 auto p = parser(std::string("builtin(") + params.input + ")");
93
94 auto deco = p->decoration();
95 EXPECT_TRUE(deco.matched);
96 EXPECT_FALSE(deco.errored);
97 ASSERT_NE(deco.value, nullptr);
98 auto* var_deco = deco.value->As<ast::Decoration>();
99 ASSERT_FALSE(p->has_error()) << p->error();
100 ASSERT_NE(var_deco, nullptr);
101 ASSERT_TRUE(var_deco->Is<ast::BuiltinDecoration>());
102
103 auto* builtin = var_deco->As<ast::BuiltinDecoration>();
104 EXPECT_EQ(builtin->builtin, params.result);
105 }
106 INSTANTIATE_TEST_SUITE_P(
107 ParserImplTest,
108 BuiltinTest,
109 testing::Values(
110 BuiltinData{"position", ast::Builtin::kPosition},
111 BuiltinData{"vertex_index", ast::Builtin::kVertexIndex},
112 BuiltinData{"instance_index", ast::Builtin::kInstanceIndex},
113 BuiltinData{"front_facing", ast::Builtin::kFrontFacing},
114 BuiltinData{"frag_depth", ast::Builtin::kFragDepth},
115 BuiltinData{"local_invocation_id", ast::Builtin::kLocalInvocationId},
116 BuiltinData{"local_invocation_idx",
117 ast::Builtin::kLocalInvocationIndex},
118 BuiltinData{"local_invocation_index",
119 ast::Builtin::kLocalInvocationIndex},
120 BuiltinData{"global_invocation_id", ast::Builtin::kGlobalInvocationId},
121 BuiltinData{"workgroup_id", ast::Builtin::kWorkgroupId},
122 BuiltinData{"num_workgroups", ast::Builtin::kNumWorkgroups},
123 BuiltinData{"sample_index", ast::Builtin::kSampleIndex},
124 BuiltinData{"sample_mask", ast::Builtin::kSampleMask}));
125
TEST_F(ParserImplTest,Decoration_Builtin_MissingLeftParen)126 TEST_F(ParserImplTest, Decoration_Builtin_MissingLeftParen) {
127 auto p = parser("builtin position)");
128 auto deco = p->decoration();
129 EXPECT_FALSE(deco.matched);
130 EXPECT_TRUE(deco.errored);
131 EXPECT_EQ(deco.value, nullptr);
132 EXPECT_TRUE(p->has_error());
133 EXPECT_EQ(p->error(), "1:9: expected '(' for builtin decoration");
134 }
135
TEST_F(ParserImplTest,Decoration_Builtin_MissingRightParen)136 TEST_F(ParserImplTest, Decoration_Builtin_MissingRightParen) {
137 auto p = parser("builtin(position");
138 auto deco = p->decoration();
139 EXPECT_FALSE(deco.matched);
140 EXPECT_TRUE(deco.errored);
141 EXPECT_EQ(deco.value, nullptr);
142 EXPECT_TRUE(p->has_error());
143 EXPECT_EQ(p->error(), "1:17: expected ')' for builtin decoration");
144 }
145
TEST_F(ParserImplTest,Decoration_Builtin_MissingValue)146 TEST_F(ParserImplTest, Decoration_Builtin_MissingValue) {
147 auto p = parser("builtin()");
148 auto deco = p->decoration();
149 EXPECT_FALSE(deco.matched);
150 EXPECT_TRUE(deco.errored);
151 EXPECT_EQ(deco.value, nullptr);
152 EXPECT_TRUE(p->has_error());
153 EXPECT_EQ(p->error(), "1:9: expected identifier for builtin");
154 }
155
TEST_F(ParserImplTest,Decoration_Builtin_InvalidValue)156 TEST_F(ParserImplTest, Decoration_Builtin_InvalidValue) {
157 auto p = parser("builtin(other_thingy)");
158 auto deco = p->decoration();
159 EXPECT_FALSE(deco.matched);
160 EXPECT_TRUE(deco.errored);
161 EXPECT_EQ(deco.value, nullptr);
162 EXPECT_TRUE(p->has_error());
163 EXPECT_EQ(p->error(), "1:9: invalid value for builtin decoration");
164 }
165
TEST_F(ParserImplTest,Decoration_Builtin_MissingInvalid)166 TEST_F(ParserImplTest, Decoration_Builtin_MissingInvalid) {
167 auto p = parser("builtin(3)");
168 auto deco = p->decoration();
169 EXPECT_FALSE(deco.matched);
170 EXPECT_TRUE(deco.errored);
171 EXPECT_EQ(deco.value, nullptr);
172 EXPECT_TRUE(p->has_error());
173 EXPECT_EQ(p->error(), "1:9: expected identifier for builtin");
174 }
175
TEST_F(ParserImplTest,Decoration_Interpolate_Flat)176 TEST_F(ParserImplTest, Decoration_Interpolate_Flat) {
177 auto p = parser("interpolate(flat)");
178 auto deco = p->decoration();
179 EXPECT_TRUE(deco.matched);
180 EXPECT_FALSE(deco.errored);
181 ASSERT_NE(deco.value, nullptr);
182 auto* var_deco = deco.value->As<ast::Decoration>();
183 ASSERT_NE(var_deco, nullptr);
184 ASSERT_FALSE(p->has_error());
185 ASSERT_TRUE(var_deco->Is<ast::InterpolateDecoration>());
186
187 auto* interp = var_deco->As<ast::InterpolateDecoration>();
188 EXPECT_EQ(interp->type, ast::InterpolationType::kFlat);
189 EXPECT_EQ(interp->sampling, ast::InterpolationSampling::kNone);
190 }
191
TEST_F(ParserImplTest,Decoration_Interpolate_Perspective_Center)192 TEST_F(ParserImplTest, Decoration_Interpolate_Perspective_Center) {
193 auto p = parser("interpolate(perspective, center)");
194 auto deco = p->decoration();
195 EXPECT_TRUE(deco.matched);
196 EXPECT_FALSE(deco.errored);
197 ASSERT_NE(deco.value, nullptr);
198 auto* var_deco = deco.value->As<ast::Decoration>();
199 ASSERT_NE(var_deco, nullptr);
200 ASSERT_FALSE(p->has_error());
201 ASSERT_TRUE(var_deco->Is<ast::InterpolateDecoration>());
202
203 auto* interp = var_deco->As<ast::InterpolateDecoration>();
204 EXPECT_EQ(interp->type, ast::InterpolationType::kPerspective);
205 EXPECT_EQ(interp->sampling, ast::InterpolationSampling::kCenter);
206 }
207
TEST_F(ParserImplTest,Decoration_Interpolate_Perspective_Centroid)208 TEST_F(ParserImplTest, Decoration_Interpolate_Perspective_Centroid) {
209 auto p = parser("interpolate(perspective, centroid)");
210 auto deco = p->decoration();
211 EXPECT_TRUE(deco.matched);
212 EXPECT_FALSE(deco.errored);
213 ASSERT_NE(deco.value, nullptr);
214 auto* var_deco = deco.value->As<ast::Decoration>();
215 ASSERT_NE(var_deco, nullptr);
216 ASSERT_FALSE(p->has_error());
217 ASSERT_TRUE(var_deco->Is<ast::InterpolateDecoration>());
218
219 auto* interp = var_deco->As<ast::InterpolateDecoration>();
220 EXPECT_EQ(interp->type, ast::InterpolationType::kPerspective);
221 EXPECT_EQ(interp->sampling, ast::InterpolationSampling::kCentroid);
222 }
223
TEST_F(ParserImplTest,Decoration_Interpolate_Linear_Sample)224 TEST_F(ParserImplTest, Decoration_Interpolate_Linear_Sample) {
225 auto p = parser("interpolate(linear, sample)");
226 auto deco = p->decoration();
227 EXPECT_TRUE(deco.matched);
228 EXPECT_FALSE(deco.errored);
229 ASSERT_NE(deco.value, nullptr);
230 auto* var_deco = deco.value->As<ast::Decoration>();
231 ASSERT_NE(var_deco, nullptr);
232 ASSERT_FALSE(p->has_error());
233 ASSERT_TRUE(var_deco->Is<ast::InterpolateDecoration>());
234
235 auto* interp = var_deco->As<ast::InterpolateDecoration>();
236 EXPECT_EQ(interp->type, ast::InterpolationType::kLinear);
237 EXPECT_EQ(interp->sampling, ast::InterpolationSampling::kSample);
238 }
239
TEST_F(ParserImplTest,Decoration_Interpolate_MissingLeftParen)240 TEST_F(ParserImplTest, Decoration_Interpolate_MissingLeftParen) {
241 auto p = parser("interpolate flat)");
242 auto deco = p->decoration();
243 EXPECT_FALSE(deco.matched);
244 EXPECT_TRUE(deco.errored);
245 EXPECT_EQ(deco.value, nullptr);
246 EXPECT_TRUE(p->has_error());
247 EXPECT_EQ(p->error(), "1:13: expected '(' for interpolate decoration");
248 }
249
TEST_F(ParserImplTest,Decoration_Interpolate_MissingRightParen)250 TEST_F(ParserImplTest, Decoration_Interpolate_MissingRightParen) {
251 auto p = parser("interpolate(flat");
252 auto deco = p->decoration();
253 EXPECT_FALSE(deco.matched);
254 EXPECT_TRUE(deco.errored);
255 EXPECT_EQ(deco.value, nullptr);
256 EXPECT_TRUE(p->has_error());
257 EXPECT_EQ(p->error(), "1:17: expected ')' for interpolate decoration");
258 }
259
TEST_F(ParserImplTest,Decoration_Interpolate_MissingFirstValue)260 TEST_F(ParserImplTest, Decoration_Interpolate_MissingFirstValue) {
261 auto p = parser("interpolate()");
262 auto deco = p->decoration();
263 EXPECT_FALSE(deco.matched);
264 EXPECT_TRUE(deco.errored);
265 EXPECT_EQ(deco.value, nullptr);
266 EXPECT_TRUE(p->has_error());
267 EXPECT_EQ(p->error(), "1:13: invalid interpolation type");
268 }
269
TEST_F(ParserImplTest,Decoration_Interpolate_InvalidFirstValue)270 TEST_F(ParserImplTest, Decoration_Interpolate_InvalidFirstValue) {
271 auto p = parser("interpolate(other_thingy)");
272 auto deco = p->decoration();
273 EXPECT_FALSE(deco.matched);
274 EXPECT_TRUE(deco.errored);
275 EXPECT_EQ(deco.value, nullptr);
276 EXPECT_TRUE(p->has_error());
277 EXPECT_EQ(p->error(), "1:13: invalid interpolation type");
278 }
279
TEST_F(ParserImplTest,Decoration_Interpolate_MissingSecondValue)280 TEST_F(ParserImplTest, Decoration_Interpolate_MissingSecondValue) {
281 auto p = parser("interpolate(perspective,)");
282 auto deco = p->decoration();
283 EXPECT_FALSE(deco.matched);
284 EXPECT_TRUE(deco.errored);
285 EXPECT_EQ(deco.value, nullptr);
286 EXPECT_TRUE(p->has_error());
287 EXPECT_EQ(p->error(), "1:25: invalid interpolation sampling");
288 }
289
TEST_F(ParserImplTest,Decoration_Interpolate_InvalidSecondValue)290 TEST_F(ParserImplTest, Decoration_Interpolate_InvalidSecondValue) {
291 auto p = parser("interpolate(perspective, nope)");
292 auto deco = p->decoration();
293 EXPECT_FALSE(deco.matched);
294 EXPECT_TRUE(deco.errored);
295 EXPECT_EQ(deco.value, nullptr);
296 EXPECT_TRUE(p->has_error());
297 EXPECT_EQ(p->error(), "1:26: invalid interpolation sampling");
298 }
299
TEST_F(ParserImplTest,Decoration_Binding)300 TEST_F(ParserImplTest, Decoration_Binding) {
301 auto p = parser("binding(4)");
302 auto deco = p->decoration();
303 EXPECT_TRUE(deco.matched);
304 EXPECT_FALSE(deco.errored);
305 ASSERT_NE(deco.value, nullptr);
306 auto* var_deco = deco.value->As<ast::Decoration>();
307 ASSERT_NE(var_deco, nullptr);
308 ASSERT_FALSE(p->has_error());
309 ASSERT_TRUE(var_deco->Is<ast::BindingDecoration>());
310
311 auto* binding = var_deco->As<ast::BindingDecoration>();
312 EXPECT_EQ(binding->value, 4u);
313 }
314
TEST_F(ParserImplTest,Decoration_Binding_MissingLeftParen)315 TEST_F(ParserImplTest, Decoration_Binding_MissingLeftParen) {
316 auto p = parser("binding 4)");
317 auto deco = p->decoration();
318 EXPECT_FALSE(deco.matched);
319 EXPECT_TRUE(deco.errored);
320 EXPECT_EQ(deco.value, nullptr);
321 EXPECT_TRUE(p->has_error());
322 EXPECT_EQ(p->error(), "1:9: expected '(' for binding decoration");
323 }
324
TEST_F(ParserImplTest,Decoration_Binding_MissingRightParen)325 TEST_F(ParserImplTest, Decoration_Binding_MissingRightParen) {
326 auto p = parser("binding(4");
327 auto deco = p->decoration();
328 EXPECT_FALSE(deco.matched);
329 EXPECT_TRUE(deco.errored);
330 EXPECT_EQ(deco.value, nullptr);
331 EXPECT_TRUE(p->has_error());
332 EXPECT_EQ(p->error(), "1:10: expected ')' for binding decoration");
333 }
334
TEST_F(ParserImplTest,Decoration_Binding_MissingValue)335 TEST_F(ParserImplTest, Decoration_Binding_MissingValue) {
336 auto p = parser("binding()");
337 auto deco = p->decoration();
338 EXPECT_FALSE(deco.matched);
339 EXPECT_TRUE(deco.errored);
340 EXPECT_EQ(deco.value, nullptr);
341 EXPECT_TRUE(p->has_error());
342 EXPECT_EQ(p->error(),
343 "1:9: expected signed integer literal for binding decoration");
344 }
345
TEST_F(ParserImplTest,Decoration_Binding_MissingInvalid)346 TEST_F(ParserImplTest, Decoration_Binding_MissingInvalid) {
347 auto p = parser("binding(nan)");
348 auto deco = p->decoration();
349 EXPECT_FALSE(deco.matched);
350 EXPECT_TRUE(deco.errored);
351 EXPECT_EQ(deco.value, nullptr);
352 EXPECT_TRUE(p->has_error());
353 EXPECT_EQ(p->error(),
354 "1:9: expected signed integer literal for binding decoration");
355 }
356
TEST_F(ParserImplTest,Decoration_group)357 TEST_F(ParserImplTest, Decoration_group) {
358 auto p = parser("group(4)");
359 auto deco = p->decoration();
360 EXPECT_TRUE(deco.matched);
361 EXPECT_FALSE(deco.errored);
362 ASSERT_NE(deco.value, nullptr);
363 auto* var_deco = deco.value->As<ast::Decoration>();
364 ASSERT_FALSE(p->has_error());
365 ASSERT_NE(var_deco, nullptr);
366 ASSERT_TRUE(var_deco->Is<ast::GroupDecoration>());
367
368 auto* group = var_deco->As<ast::GroupDecoration>();
369 EXPECT_EQ(group->value, 4u);
370 }
371
TEST_F(ParserImplTest,Decoration_Group_MissingLeftParen)372 TEST_F(ParserImplTest, Decoration_Group_MissingLeftParen) {
373 auto p = parser("group 2)");
374 auto deco = p->decoration();
375 EXPECT_FALSE(deco.matched);
376 EXPECT_TRUE(deco.errored);
377 EXPECT_EQ(deco.value, nullptr);
378 EXPECT_TRUE(p->has_error());
379 EXPECT_EQ(p->error(), "1:7: expected '(' for group decoration");
380 }
381
TEST_F(ParserImplTest,Decoration_Group_MissingRightParen)382 TEST_F(ParserImplTest, Decoration_Group_MissingRightParen) {
383 auto p = parser("group(2");
384 auto deco = p->decoration();
385 EXPECT_FALSE(deco.matched);
386 EXPECT_TRUE(deco.errored);
387 EXPECT_EQ(deco.value, nullptr);
388 EXPECT_TRUE(p->has_error());
389 EXPECT_EQ(p->error(), "1:8: expected ')' for group decoration");
390 }
391
TEST_F(ParserImplTest,Decoration_Group_MissingValue)392 TEST_F(ParserImplTest, Decoration_Group_MissingValue) {
393 auto p = parser("group()");
394 auto deco = p->decoration();
395 EXPECT_FALSE(deco.matched);
396 EXPECT_TRUE(deco.errored);
397 EXPECT_EQ(deco.value, nullptr);
398 EXPECT_TRUE(p->has_error());
399 EXPECT_EQ(p->error(),
400 "1:7: expected signed integer literal for group decoration");
401 }
402
TEST_F(ParserImplTest,Decoration_Group_MissingInvalid)403 TEST_F(ParserImplTest, Decoration_Group_MissingInvalid) {
404 auto p = parser("group(nan)");
405 auto deco = p->decoration();
406 EXPECT_FALSE(deco.matched);
407 EXPECT_TRUE(deco.errored);
408 EXPECT_EQ(deco.value, nullptr);
409 EXPECT_TRUE(p->has_error());
410 EXPECT_EQ(p->error(),
411 "1:7: expected signed integer literal for group decoration");
412 }
413
414 } // namespace
415 } // namespace wgsl
416 } // namespace reader
417 } // namespace tint
418