• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "src/shader_data.h"
18 
19 namespace amber {
20 namespace amberscript {
21 
22 using AmberScriptParserTest = testing::Test;
23 
TEST_F(AmberScriptParserTest,ShaderPassThrough)24 TEST_F(AmberScriptParserTest, ShaderPassThrough) {
25   std::string in = "SHADER vertex my_shader1 PASSTHROUGH";
26 
27   Parser parser;
28   Result r = parser.Parse(in);
29   ASSERT_TRUE(r.IsSuccess()) << r.Error();
30 
31   auto script = parser.GetScript();
32   const auto& shaders = script->GetShaders();
33   ASSERT_EQ(1U, shaders.size());
34 
35   const auto* shader = shaders[0].get();
36   EXPECT_EQ("my_shader1", shader->GetName());
37   EXPECT_EQ(kShaderTypeVertex, shader->GetType());
38   EXPECT_EQ(kShaderFormatSpirvAsm, shader->GetFormat());
39   EXPECT_EQ(kPassThroughShader, shader->GetData());
40 }
41 
TEST_F(AmberScriptParserTest,ShaderInvalidShaderTypeToken)42 TEST_F(AmberScriptParserTest, ShaderInvalidShaderTypeToken) {
43   std::string in = "SHADER 1234 my_shader PASSTHROUGH";
44 
45   Parser parser;
46   Result r = parser.Parse(in);
47   ASSERT_FALSE(r.IsSuccess());
48   EXPECT_EQ("1: invalid token when looking for shader type", r.Error());
49 }
50 
TEST_F(AmberScriptParserTest,ShaderInvalidShaderNameToken)51 TEST_F(AmberScriptParserTest, ShaderInvalidShaderNameToken) {
52   std::string in = "SHADER vertex 12345 PASSTHROUGH";
53 
54   Parser parser;
55   Result r = parser.Parse(in);
56   ASSERT_FALSE(r.IsSuccess());
57   EXPECT_EQ("1: invalid token when looking for shader name", r.Error());
58 }
59 
TEST_F(AmberScriptParserTest,ShaderInvalidShaderFormatToken)60 TEST_F(AmberScriptParserTest, ShaderInvalidShaderFormatToken) {
61   std::string in = "SHADER vertex my_shader 1234";
62 
63   Parser parser;
64   Result r = parser.Parse(in);
65   ASSERT_FALSE(r.IsSuccess());
66   EXPECT_EQ("1: invalid token when looking for shader format", r.Error());
67 }
68 
69 struct NameData {
70   const char* name;
71 };
72 
73 using AmberScriptParserShaderPassThroughTest = testing::TestWithParam<NameData>;
TEST_P(AmberScriptParserShaderPassThroughTest,ShaderPassThroughWithoutVertex)74 TEST_P(AmberScriptParserShaderPassThroughTest, ShaderPassThroughWithoutVertex) {
75   auto test_data = GetParam();
76 
77   std::string in =
78       "SHADER " + std::string(test_data.name) + " my_shader PASSTHROUGH";
79 
80   Parser parser;
81   Result r = parser.Parse(in);
82   ASSERT_FALSE(r.IsSuccess());
83   EXPECT_EQ(
84       "1: invalid shader type for PASSTHROUGH. Only vertex PASSTHROUGH "
85       "allowed",
86       r.Error());
87 }
88 INSTANTIATE_TEST_SUITE_P(
89     AmberScriptParserShaderPassThroughTests,
90     AmberScriptParserShaderPassThroughTest,
91     testing::Values(NameData{"fragment"},
92                     NameData{"geometry"},
93                     NameData{"tessellation_evaluation"},
94                     NameData{"tessellation_control"},
95                     NameData{"compute"},
96                     NameData{"multi"}));  // NOLINT(whitespace/parens)
97 
TEST_F(AmberScriptParserTest,ShaderPassThroughUnknownShaderType)98 TEST_F(AmberScriptParserTest, ShaderPassThroughUnknownShaderType) {
99   std::string in = "SHADER UNKNOWN my_shader PASSTHROUGH";
100 
101   Parser parser;
102   Result r = parser.Parse(in);
103   ASSERT_FALSE(r.IsSuccess());
104   EXPECT_EQ("1: unknown shader type: UNKNOWN", r.Error());
105 }
106 
TEST_F(AmberScriptParserTest,ShaderPassThroughMissingName)107 TEST_F(AmberScriptParserTest, ShaderPassThroughMissingName) {
108   std::string in = "SHADER vertex PASSTHROUGH";
109 
110   Parser parser;
111   Result r = parser.Parse(in);
112   ASSERT_FALSE(r.IsSuccess());
113   EXPECT_EQ("1: invalid token when looking for shader format", r.Error());
114 }
115 
TEST_F(AmberScriptParserTest,ShaderPassThroughExtraParameters)116 TEST_F(AmberScriptParserTest, ShaderPassThroughExtraParameters) {
117   std::string in = "SHADER vertex my_shader PASSTHROUGH INVALID";
118 
119   Parser parser;
120   Result r = parser.Parse(in);
121   ASSERT_FALSE(r.IsSuccess());
122   EXPECT_EQ("1: extra parameters after SHADER PASSTHROUGH", r.Error());
123 }
124 
TEST_F(AmberScriptParserTest,Shader)125 TEST_F(AmberScriptParserTest, Shader) {
126   std::string shader_result = R"(
127 # Shader has a comment in it.
128 void main() {
129   gl_FragColor = vec3(2, 3, 4);
130 }
131 )";
132 
133   std::string in = R"(#!amber
134 SHADER geometry shader_name GLSL
135 )" + shader_result +
136                    "END";
137 
138   Parser parser;
139   Result r = parser.Parse(in);
140   ASSERT_TRUE(r.IsSuccess()) << r.Error();
141 
142   auto script = parser.GetScript();
143   const auto& shaders = script->GetShaders();
144   ASSERT_EQ(1U, shaders.size());
145 
146   const auto* shader = shaders[0].get();
147   EXPECT_EQ("shader_name", shader->GetName());
148   EXPECT_EQ(kShaderTypeGeometry, shader->GetType());
149   EXPECT_EQ(kShaderFormatGlsl, shader->GetFormat());
150   EXPECT_EQ(shader_result, shader->GetData());
151 }
152 
TEST_F(AmberScriptParserTest,ShaderInvalidFormat)153 TEST_F(AmberScriptParserTest, ShaderInvalidFormat) {
154   std::string in = R"(#!amber
155 SHADER geometry shader_name INVALID
156 # Shader has a comment in it.
157 void main() {
158   gl_FragColor = vec3(2, 3, 4);
159 }
160 END)";
161 
162   Parser parser;
163   Result r = parser.Parse(in);
164   ASSERT_FALSE(r.IsSuccess());
165   EXPECT_EQ("2: unknown shader format: INVALID", r.Error());
166 }
167 
TEST_F(AmberScriptParserTest,ShaderMissingFormat)168 TEST_F(AmberScriptParserTest, ShaderMissingFormat) {
169   std::string in = R"(#!amber
170 SHADER geometry shader_name
171 # Shader has a comment in it.
172 void main() {
173   gl_FragColor = vec3(2, 3, 4);
174 }
175 END)";
176 
177   Parser parser;
178   Result r = parser.Parse(in);
179   ASSERT_FALSE(r.IsSuccess());
180   EXPECT_EQ("3: invalid token when looking for shader format", r.Error());
181 }
182 
TEST_F(AmberScriptParserTest,ShaderEmpty)183 TEST_F(AmberScriptParserTest, ShaderEmpty) {
184   std::string in = R"(#!amber
185 SHADER geometry shader_name GLSL
186 END)";
187 
188   Parser parser;
189   Result r = parser.Parse(in);
190   ASSERT_FALSE(r.IsSuccess());
191   EXPECT_EQ("3: SHADER must not be empty", r.Error());
192 }
193 
TEST_F(AmberScriptParserTest,ShaderMissingName)194 TEST_F(AmberScriptParserTest, ShaderMissingName) {
195   std::string in = R"(#!amber
196 SHADER geometry GLSL
197 # Shader has a comment in it.
198 void main() {
199   gl_FragColor = vec3(2, 3, 4);
200 }
201 END)";
202 
203   Parser parser;
204   Result r = parser.Parse(in);
205   ASSERT_FALSE(r.IsSuccess());
206   EXPECT_EQ("3: invalid token when looking for shader format", r.Error());
207 }
208 
TEST_F(AmberScriptParserTest,ShaderMissingEnd)209 TEST_F(AmberScriptParserTest, ShaderMissingEnd) {
210   std::string in = R"(#!amber
211 SHADER geometry shader_name GLSL
212 # Shader has a comment in it.
213 void main() {
214   gl_FragColor = vec3(2, 3, 4);
215 })";
216 
217   Parser parser;
218   Result r = parser.Parse(in);
219   ASSERT_FALSE(r.IsSuccess());
220   EXPECT_EQ("6: SHADER missing END command", r.Error());
221 }
222 
TEST_F(AmberScriptParserTest,ShaderExtraParameter)223 TEST_F(AmberScriptParserTest, ShaderExtraParameter) {
224   std::string in = R"(#!amber
225 SHADER geometry shader_name GLSL INVALID
226 # Shader has a comment in it.
227 void main() {
228   gl_FragColor = vec3(2, 3, 4);
229 }
230 END)";
231 
232   Parser parser;
233   Result r = parser.Parse(in);
234   ASSERT_FALSE(r.IsSuccess());
235   EXPECT_EQ("2: extra parameters after SHADER command", r.Error());
236 }
237 
238 struct ShaderTypeData {
239   const char* name;
240   ShaderType type;
241 };
242 
243 using AmberScriptParserShaderTypeTest = testing::TestWithParam<ShaderTypeData>;
TEST_P(AmberScriptParserShaderTypeTest,ShaderFormats)244 TEST_P(AmberScriptParserShaderTypeTest, ShaderFormats) {
245   auto test_data = GetParam();
246 
247   std::string shader_result = R"(
248 void main() {
249   gl_FragColor = vec3(2, 3, 4);
250 }
251 )";
252 
253   std::string in = "SHADER " + std::string(test_data.name) +
254                    R"( my_shader GLSL
255 )" + shader_result +
256                    "END";
257 
258   Parser parser;
259   Result r = parser.Parse(in);
260   ASSERT_TRUE(r.IsSuccess()) << r.Error();
261 
262   auto script = parser.GetScript();
263   const auto& shaders = script->GetShaders();
264   ASSERT_EQ(1U, shaders.size());
265 
266   const auto* shader = shaders[0].get();
267   EXPECT_EQ("my_shader", shader->GetName());
268   EXPECT_EQ(test_data.type, shader->GetType());
269   EXPECT_EQ(kShaderFormatGlsl, shader->GetFormat());
270   EXPECT_EQ(shader_result, shader->GetData());
271 }
272 INSTANTIATE_TEST_SUITE_P(
273     AmberScriptParserTestsShaderType,
274     AmberScriptParserShaderTypeTest,
275     testing::Values(
276         ShaderTypeData{"vertex", kShaderTypeVertex},
277         ShaderTypeData{"fragment", kShaderTypeFragment},
278         ShaderTypeData{"geometry", kShaderTypeGeometry},
279         ShaderTypeData{"tessellation_evaluation",
280                        kShaderTypeTessellationEvaluation},
281         ShaderTypeData{"tessellation_control", kShaderTypeTessellationControl},
282         ShaderTypeData{"compute", kShaderTypeCompute},
283         ShaderTypeData{"multi",
284                        kShaderTypeMulti}));  // NOLINT(whitespace/parens)
285 
286 struct ShaderFormatData {
287   const char* name;
288   ShaderFormat format;
289 };
290 
291 using AmberScriptParserShaderFormatTest =
292     testing::TestWithParam<ShaderFormatData>;
TEST_P(AmberScriptParserShaderFormatTest,ShaderFormats)293 TEST_P(AmberScriptParserShaderFormatTest, ShaderFormats) {
294   auto test_data = GetParam();
295 
296   std::string shader_result = R"(void main() {
297   gl_FragColor = vec3(2, 3, 4);
298 }
299 )";
300 
301   std::string in = "SHADER vertex my_shader " + std::string(test_data.name) +
302                    "\n" + shader_result + "END";
303 
304   Parser parser;
305   Result r = parser.Parse(in);
306   ASSERT_TRUE(r.IsSuccess()) << r.Error();
307 
308   auto script = parser.GetScript();
309   const auto& shaders = script->GetShaders();
310   ASSERT_EQ(1U, shaders.size());
311 
312   const auto* shader = shaders[0].get();
313   EXPECT_EQ("my_shader", shader->GetName());
314   EXPECT_EQ(kShaderTypeVertex, shader->GetType());
315   EXPECT_EQ(test_data.format, shader->GetFormat());
316   EXPECT_EQ(shader_result, shader->GetData());
317 }
318 INSTANTIATE_TEST_SUITE_P(
319     AmberScriptParserTestsShaderFormat,
320     AmberScriptParserShaderFormatTest,
321     testing::Values(ShaderFormatData{"GLSL", kShaderFormatGlsl},
322                     ShaderFormatData{"SPIRV-ASM", kShaderFormatSpirvAsm},
323                     ShaderFormatData{
324                         "SPIRV-HEX",
325                         kShaderFormatSpirvHex}));  // NOLINT(whitespace/parens)
326 
TEST_F(AmberScriptParserTest,DuplicateShaderName)327 TEST_F(AmberScriptParserTest, DuplicateShaderName) {
328   std::string in = R"(
329 SHADER vertex my_shader GLSL
330 # shader
331 END
332 SHADER fragment my_shader GLSL
333 # another shader
334 END)";
335 
336   Parser parser;
337   Result r = parser.Parse(in);
338   ASSERT_FALSE(r.IsSuccess());
339   EXPECT_EQ("7: duplicate shader name provided", r.Error());
340 }
341 
TEST_F(AmberScriptParserTest,OpenCLCKernel)342 TEST_F(AmberScriptParserTest, OpenCLCKernel) {
343   std::string in = R"(
344 SHADER compute my_shader OPENCL-C
345 # shader
346 END
347 )";
348 
349   Parser parser;
350   Result r = parser.Parse(in);
351   ASSERT_TRUE(r.IsSuccess());
352 }
353 
TEST_F(AmberScriptParserTest,OpenCLCMultiKernel)354 TEST_F(AmberScriptParserTest, OpenCLCMultiKernel) {
355   std::string in = R"(
356 SHADER multi my_shader OPENCL-C
357 # shader
358 END
359 )";
360 
361   Parser parser;
362   Result r = parser.Parse(in);
363   ASSERT_TRUE(r.IsSuccess());
364 }
365 
366 }  // namespace amberscript
367 }  // namespace amber
368