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