1 // Copyright 2019 The Amber 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 parseried.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "gtest/gtest.h"
16 #include "src/amberscript/parser.h"
17
18 namespace amber {
19 namespace amberscript {
20
21 using AmberScriptParserTest = testing::Test;
22
TEST_F(AmberScriptParserTest,Struct)23 TEST_F(AmberScriptParserTest, Struct) {
24 std::string in = R"(
25 STRUCT my_struct
26 uint8 first
27 uint32 second
28 vec3<float> third
29 mat2x4<float> forth
30 END)";
31
32 Parser parser;
33 Result r = parser.Parse(in);
34 ASSERT_TRUE(r.IsSuccess()) << r.Error();
35
36 auto script = parser.GetScript();
37 auto type = script->GetType("my_struct");
38 ASSERT_TRUE(type != nullptr);
39 ASSERT_TRUE(type->IsStruct());
40
41 auto s = type->AsStruct();
42 EXPECT_FALSE(s->HasStride());
43
44 const auto& m = s->Members();
45 ASSERT_EQ(4U, m.size());
46 for (size_t i = 0; i < 4; ++i) {
47 ASSERT_TRUE(m[i].type->IsNumber()) << i;
48 EXPECT_FALSE(m[i].HasOffset());
49 EXPECT_FALSE(m[i].HasArrayStride());
50 EXPECT_FALSE(m[i].HasMatrixStride());
51 }
52
53 EXPECT_TRUE(type::Type::IsUint8(m[0].type->AsNumber()->GetFormatMode(),
54 m[0].type->AsNumber()->NumBits()));
55 EXPECT_TRUE(type::Type::IsUint32(m[1].type->AsNumber()->GetFormatMode(),
56 m[1].type->AsNumber()->NumBits()));
57
58 EXPECT_TRUE(m[2].type->IsVec());
59 EXPECT_EQ(3U, m[2].type->RowCount());
60 EXPECT_TRUE(type::Type::IsFloat32(m[2].type->AsNumber()->GetFormatMode(),
61 m[2].type->AsNumber()->NumBits()));
62
63 EXPECT_TRUE(m[3].type->IsMatrix());
64 EXPECT_EQ(4U, m[3].type->RowCount());
65 EXPECT_EQ(2U, m[3].type->ColumnCount());
66 EXPECT_TRUE(type::Type::IsFloat32(m[3].type->AsNumber()->GetFormatMode(),
67 m[3].type->AsNumber()->NumBits()));
68 }
69
TEST_F(AmberScriptParserTest,StructWithDuplicateName)70 TEST_F(AmberScriptParserTest, StructWithDuplicateName) {
71 std::string in = R"(
72 STRUCT my_struct
73 uint8 first
74 END
75
76 STRUCT my_struct
77 float second
78 END)";
79
80 Parser parser;
81 Result r = parser.Parse(in);
82 ASSERT_FALSE(r.IsSuccess());
83 EXPECT_EQ("6: duplicate type name provided", r.Error());
84 }
85
TEST_F(AmberScriptParserTest,StructWithStride)86 TEST_F(AmberScriptParserTest, StructWithStride) {
87 std::string in = R"(
88 STRUCT my_struct STRIDE 20
89 uint8 first
90 END)";
91
92 Parser parser;
93 Result r = parser.Parse(in);
94 ASSERT_TRUE(r.IsSuccess()) << r.Error();
95
96 auto script = parser.GetScript();
97 auto type = script->GetType("my_struct");
98 ASSERT_TRUE(type != nullptr);
99 ASSERT_TRUE(type->IsStruct());
100
101 auto s = type->AsStruct();
102 EXPECT_TRUE(s->HasStride());
103 EXPECT_EQ(20U, s->StrideInBytes());
104 }
105
TEST_F(AmberScriptParserTest,StructMissingName)106 TEST_F(AmberScriptParserTest, StructMissingName) {
107 std::string in = R"(
108 STRUCT
109 uint8 first
110 END)";
111
112 Parser parser;
113 Result r = parser.Parse(in);
114 EXPECT_FALSE(r.IsSuccess());
115 EXPECT_EQ("3: invalid STRUCT name provided", r.Error());
116 }
117
TEST_F(AmberScriptParserTest,StructMissingNameWithStride)118 TEST_F(AmberScriptParserTest, StructMissingNameWithStride) {
119 std::string in = R"(
120 STRUCT STRIDE 20
121 uint8 first
122 END)";
123
124 Parser parser;
125 Result r = parser.Parse(in);
126 EXPECT_FALSE(r.IsSuccess());
127 EXPECT_EQ("2: missing STRUCT name", r.Error());
128 }
129
TEST_F(AmberScriptParserTest,StructInvalidName)130 TEST_F(AmberScriptParserTest, StructInvalidName) {
131 std::string in = R"(
132 STRUCT 1234 STRIDE 20
133 uint8 first
134 END)";
135
136 Parser parser;
137 Result r = parser.Parse(in);
138 EXPECT_FALSE(r.IsSuccess());
139 EXPECT_EQ("2: invalid STRUCT name provided", r.Error());
140 }
141
TEST_F(AmberScriptParserTest,StructMissingStrideValue)142 TEST_F(AmberScriptParserTest, StructMissingStrideValue) {
143 std::string in = R"(
144 STRUCT foo STRIDE
145 uint8 first
146 END)";
147
148 Parser parser;
149 Result r = parser.Parse(in);
150 EXPECT_FALSE(r.IsSuccess());
151 EXPECT_EQ("3: missing value for STRIDE", r.Error());
152 }
153
TEST_F(AmberScriptParserTest,StructInvalidStrideValue)154 TEST_F(AmberScriptParserTest, StructInvalidStrideValue) {
155 std::string in = R"(
156 STRUCT foo STRIDE abc
157 uint8 first
158 END)";
159
160 Parser parser;
161 Result r = parser.Parse(in);
162 EXPECT_FALSE(r.IsSuccess());
163 EXPECT_EQ("2: invalid value for STRIDE", r.Error());
164 }
165
TEST_F(AmberScriptParserTest,StructMissingEND)166 TEST_F(AmberScriptParserTest, StructMissingEND) {
167 std::string in = R"(
168 STRUCT foo
169 uint8 first
170 )";
171
172 Parser parser;
173 Result r = parser.Parse(in);
174 EXPECT_FALSE(r.IsSuccess());
175 EXPECT_EQ("4: invalid type for STRUCT member", r.Error());
176 }
177
TEST_F(AmberScriptParserTest,StructExtraParams)178 TEST_F(AmberScriptParserTest, StructExtraParams) {
179 std::string in = R"(
180 STRUCT foo STRIDE 20 BAR
181 uint8 first
182 END)";
183
184 Parser parser;
185 Result r = parser.Parse(in);
186 EXPECT_FALSE(r.IsSuccess());
187 EXPECT_EQ("2: extra token BAR after STRUCT header", r.Error());
188 }
189
TEST_F(AmberScriptParserTest,StructMemberTypeInvalid)190 TEST_F(AmberScriptParserTest, StructMemberTypeInvalid) {
191 std::string in = R"(
192 STRUCT foo
193 123 first
194 END)";
195
196 Parser parser;
197 Result r = parser.Parse(in);
198 EXPECT_FALSE(r.IsSuccess());
199 EXPECT_EQ("3: invalid type for STRUCT member", r.Error());
200 }
201
TEST_F(AmberScriptParserTest,StructMemberTypeUnknown)202 TEST_F(AmberScriptParserTest, StructMemberTypeUnknown) {
203 std::string in = R"(
204 STRUCT foo
205 uint99 first
206 END)";
207
208 Parser parser;
209 Result r = parser.Parse(in);
210 EXPECT_FALSE(r.IsSuccess());
211 EXPECT_EQ("3: unknown type 'uint99' for STRUCT member", r.Error());
212 }
213
TEST_F(AmberScriptParserTest,StructMemberNameMissing)214 TEST_F(AmberScriptParserTest, StructMemberNameMissing) {
215 std::string in = R"(
216 STRUCT foo
217 uint8
218 END)";
219
220 Parser parser;
221 Result r = parser.Parse(in);
222 EXPECT_FALSE(r.IsSuccess());
223 EXPECT_EQ("4: missing name for STRUCT member", r.Error());
224 }
225
TEST_F(AmberScriptParserTest,StructMemberNameInvalid)226 TEST_F(AmberScriptParserTest, StructMemberNameInvalid) {
227 std::string in = R"(
228 STRUCT foo
229 uint8 123
230 END)";
231
232 Parser parser;
233 Result r = parser.Parse(in);
234 EXPECT_FALSE(r.IsSuccess());
235 EXPECT_EQ("3: invalid name for STRUCT member", r.Error());
236 }
237
TEST_F(AmberScriptParserTest,StructMemberNameDuplicate)238 TEST_F(AmberScriptParserTest, StructMemberNameDuplicate) {
239 std::string in = R"(
240 STRUCT foo
241 uint8 name
242 uint8 name
243 END)";
244
245 Parser parser;
246 Result r = parser.Parse(in);
247 EXPECT_FALSE(r.IsSuccess());
248 EXPECT_EQ("4: duplicate name for STRUCT member", r.Error());
249 }
250
TEST_F(AmberScriptParserTest,StructWithEmbeddedStruct)251 TEST_F(AmberScriptParserTest, StructWithEmbeddedStruct) {
252 std::string in = R"(
253 STRUCT sub_struct
254 uint8 first
255 END
256
257 STRUCT my_struct
258 float second
259 sub_struct third
260 END)";
261
262 Parser parser;
263 Result r = parser.Parse(in);
264 ASSERT_TRUE(r.IsSuccess()) << r.Error();
265
266 auto script = parser.GetScript();
267 auto type = script->GetType("my_struct");
268 ASSERT_TRUE(type != nullptr);
269 ASSERT_TRUE(type->IsStruct());
270
271 auto s = type->AsStruct();
272 EXPECT_FALSE(s->HasStride());
273
274 const auto& m = s->Members();
275 ASSERT_EQ(2U, m.size());
276
277 EXPECT_TRUE(m[0].type->IsNumber());
278 EXPECT_TRUE(m[1].type->IsStruct());
279 }
280
TEST_F(AmberScriptParserTest,StructDisallowsRecursiveInclusion)281 TEST_F(AmberScriptParserTest, StructDisallowsRecursiveInclusion) {
282 std::string in = R"(
283 STRUCT my_struct
284 float second
285 my_struct third
286 END)";
287
288 Parser parser;
289 Result r = parser.Parse(in);
290 ASSERT_FALSE(r.IsSuccess());
291 EXPECT_EQ("4: recursive types are not allowed", r.Error());
292 }
293
TEST_F(AmberScriptParserTest,StructMemberWithOffset)294 TEST_F(AmberScriptParserTest, StructMemberWithOffset) {
295 std::string in = R"(
296 STRUCT my_struct
297 uint8 first OFFSET 20
298 END)";
299
300 Parser parser;
301 Result r = parser.Parse(in);
302 ASSERT_TRUE(r.IsSuccess()) << r.Error();
303
304 auto script = parser.GetScript();
305 auto type = script->GetType("my_struct");
306 ASSERT_TRUE(type != nullptr);
307 ASSERT_TRUE(type->IsStruct());
308
309 auto s = type->AsStruct();
310 EXPECT_FALSE(s->HasStride());
311
312 const auto& m = s->Members();
313 ASSERT_EQ(1U, m.size());
314 EXPECT_TRUE(m[0].HasOffset());
315 EXPECT_FALSE(m[0].HasArrayStride());
316 EXPECT_FALSE(m[0].HasMatrixStride());
317 EXPECT_EQ(20, m[0].offset_in_bytes);
318 }
319
TEST_F(AmberScriptParserTest,StructMemberOffsetMissingValue)320 TEST_F(AmberScriptParserTest, StructMemberOffsetMissingValue) {
321 std::string in = R"(
322 STRUCT my_struct
323 uint8 first OFFSET
324 END)";
325
326 Parser parser;
327 Result r = parser.Parse(in);
328 EXPECT_FALSE(r.IsSuccess());
329 EXPECT_EQ("4: missing value for STRUCT member OFFSET", r.Error());
330 }
331
TEST_F(AmberScriptParserTest,StructMemberOffsetInvalidValue)332 TEST_F(AmberScriptParserTest, StructMemberOffsetInvalidValue) {
333 std::string in = R"(
334 STRUCT my_struct
335 uint8 first OFFSET abcd
336 END)";
337
338 Parser parser;
339 Result r = parser.Parse(in);
340 EXPECT_FALSE(r.IsSuccess());
341 EXPECT_EQ("3: invalid value for STRUCT member OFFSET", r.Error());
342 }
343
TEST_F(AmberScriptParserTest,DISABLED_StructMemberWithArrayStride)344 TEST_F(AmberScriptParserTest, DISABLED_StructMemberWithArrayStride) {
345 std::string in = R"(
346 STRUCT my_struct
347 uint8 first[2] ARRAY_STRIDE 20
348 END)";
349
350 Parser parser;
351 Result r = parser.Parse(in);
352 ASSERT_TRUE(r.IsSuccess()) << r.Error();
353
354 auto script = parser.GetScript();
355 auto type = script->GetType("my_struct");
356 ASSERT_TRUE(type != nullptr);
357 ASSERT_TRUE(type->IsStruct());
358
359 auto s = type->AsStruct();
360 EXPECT_FALSE(s->HasStride());
361
362 const auto& m = s->Members();
363 ASSERT_EQ(1U, m.size());
364 EXPECT_FALSE(m[0].HasOffset());
365 EXPECT_TRUE(m[0].HasArrayStride());
366 EXPECT_FALSE(m[0].HasMatrixStride());
367 EXPECT_EQ(20, m[0].array_stride_in_bytes);
368 }
369
TEST_F(AmberScriptParserTest,StructMemberArrayStrideMissingValue)370 TEST_F(AmberScriptParserTest, StructMemberArrayStrideMissingValue) {
371 std::string in = R"(
372 STRUCT my_struct
373 uint8 first ARRAY_STRIDE
374 END)";
375
376 Parser parser;
377 Result r = parser.Parse(in);
378 EXPECT_FALSE(r.IsSuccess());
379 EXPECT_EQ("4: missing value for STRUCT member ARRAY_STRIDE", r.Error());
380 }
381
TEST_F(AmberScriptParserTest,StructMemberArrayStrideInvalidValue)382 TEST_F(AmberScriptParserTest, StructMemberArrayStrideInvalidValue) {
383 std::string in = R"(
384 STRUCT my_struct
385 uint8 first ARRAY_STRIDE abcd
386 END)";
387
388 Parser parser;
389 Result r = parser.Parse(in);
390 EXPECT_FALSE(r.IsSuccess());
391 EXPECT_EQ("3: invalid value for STRUCT member ARRAY_STRIDE", r.Error());
392 }
393
TEST_F(AmberScriptParserTest,StrictInvalidTypeWithArrayStride)394 TEST_F(AmberScriptParserTest, StrictInvalidTypeWithArrayStride) {
395 std::string in = R"(
396 STRUCT s
397 uint32 a ARRAY_STRIDE 10
398 END)";
399
400 Parser parser;
401 Result r = parser.Parse(in);
402 ASSERT_FALSE(r.IsSuccess());
403 EXPECT_EQ("3: ARRAY_STRIDE only valid on array members", r.Error());
404 }
405
TEST_F(AmberScriptParserTest,StructMemberWithMatrixStride)406 TEST_F(AmberScriptParserTest, StructMemberWithMatrixStride) {
407 std::string in = R"(
408 STRUCT my_struct
409 mat2x2<float> first MATRIX_STRIDE 20
410 END)";
411
412 Parser parser;
413 Result r = parser.Parse(in);
414 ASSERT_TRUE(r.IsSuccess()) << r.Error();
415
416 auto script = parser.GetScript();
417 auto type = script->GetType("my_struct");
418 ASSERT_TRUE(type != nullptr);
419 ASSERT_TRUE(type->IsStruct());
420
421 auto s = type->AsStruct();
422 EXPECT_FALSE(s->HasStride());
423
424 const auto& m = s->Members();
425 ASSERT_EQ(1U, m.size());
426 EXPECT_FALSE(m[0].HasOffset());
427 EXPECT_FALSE(m[0].HasArrayStride());
428 EXPECT_TRUE(m[0].HasMatrixStride());
429 EXPECT_EQ(20, m[0].matrix_stride_in_bytes);
430 }
431
TEST_F(AmberScriptParserTest,StructMemberMatrixStrideMissingValue)432 TEST_F(AmberScriptParserTest, StructMemberMatrixStrideMissingValue) {
433 std::string in = R"(
434 STRUCT my_struct
435 mat2x2<float> first MATRIX_STRIDE
436 END)";
437
438 Parser parser;
439 Result r = parser.Parse(in);
440 EXPECT_FALSE(r.IsSuccess());
441 EXPECT_EQ("4: missing value for STRUCT member MATRIX_STRIDE", r.Error());
442 }
443
TEST_F(AmberScriptParserTest,StructMemberMatrixStrideInvalidValue)444 TEST_F(AmberScriptParserTest, StructMemberMatrixStrideInvalidValue) {
445 std::string in = R"(
446 STRUCT my_struct
447 mat2x2<float> first MATRIX_STRIDE abcd
448 END)";
449
450 Parser parser;
451 Result r = parser.Parse(in);
452 EXPECT_FALSE(r.IsSuccess());
453 EXPECT_EQ("3: invalid value for STRUCT member MATRIX_STRIDE", r.Error());
454 }
455
TEST_F(AmberScriptParserTest,StructInvalidTypeWithMatrixStride)456 TEST_F(AmberScriptParserTest, StructInvalidTypeWithMatrixStride) {
457 std::string in = R"(
458 STRUCT s
459 uint32 a MATRIX_STRIDE 10
460 END)";
461
462 Parser parser;
463 Result r = parser.Parse(in);
464 ASSERT_FALSE(r.IsSuccess());
465 EXPECT_EQ("3: MATRIX_STRIDE only valid on matrix members", r.Error());
466 }
467
TEST_F(AmberScriptParserTest,StructMemberExtraParam)468 TEST_F(AmberScriptParserTest, StructMemberExtraParam) {
469 std::string in = R"(
470 STRUCT my_struct
471 uint8 first 1234
472 END)";
473
474 Parser parser;
475 Result r = parser.Parse(in);
476 EXPECT_FALSE(r.IsSuccess());
477 EXPECT_EQ("3: extra param for STRUCT member", r.Error());
478 }
479
TEST_F(AmberScriptParserTest,StructMemberUnknownParam)480 TEST_F(AmberScriptParserTest, StructMemberUnknownParam) {
481 std::string in = R"(
482 STRUCT my_struct
483 uint8 first UNKNOWN
484 END)";
485
486 Parser parser;
487 Result r = parser.Parse(in);
488 EXPECT_FALSE(r.IsSuccess());
489 EXPECT_EQ("3: unknown param 'UNKNOWN' for STRUCT member", r.Error());
490 }
491
492 } // namespace amberscript
493 } // namespace amber
494