1 // Copyright 2018 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 implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "src/vkscript/section_parser.h"
16
17 #include "gtest/gtest.h"
18 #include "src/shader_data.h"
19
20 namespace amber {
21 namespace vkscript {
22
23 using SectionParserTest = testing::Test;
24
TEST_F(SectionParserTest,SectionParserCommentSection)25 TEST_F(SectionParserTest, SectionParserCommentSection) {
26 std::string input = "[comment]\nThis is the comment body\n.Lots of Text.";
27
28 SectionParser p;
29 Result r = p.SplitSectionsForTesting(input);
30 ASSERT_TRUE(r.IsSuccess());
31
32 auto sections = p.Sections();
33 EXPECT_TRUE(sections.empty());
34 }
35
TEST_F(SectionParserTest,ParseShaderGlslVertex)36 TEST_F(SectionParserTest, ParseShaderGlslVertex) {
37 std::string shader = R"(#version 430
38 void main() {
39 })";
40 std::string input = "[vertex shader]\n" + shader;
41
42 SectionParser p;
43 Result r = p.SplitSectionsForTesting(input);
44 ASSERT_TRUE(r.IsSuccess());
45
46 auto sections = p.Sections();
47 ASSERT_EQ(1U, sections.size());
48 EXPECT_EQ(NodeType::kShader, sections[0].section_type);
49 EXPECT_EQ(kShaderTypeVertex, sections[0].shader_type);
50 EXPECT_EQ(kShaderFormatGlsl, sections[0].format);
51 EXPECT_EQ(shader, sections[0].contents);
52 }
53
TEST_F(SectionParserTest,ParseShaderGlslVertexPassthrough)54 TEST_F(SectionParserTest, ParseShaderGlslVertexPassthrough) {
55 std::string input = "[vertex shader passthrough]";
56
57 SectionParser p;
58 Result r = p.SplitSectionsForTesting(input);
59 ASSERT_TRUE(r.IsSuccess());
60
61 auto sections = p.Sections();
62 ASSERT_EQ(1U, sections.size());
63 EXPECT_EQ(NodeType::kShader, sections[0].section_type);
64 EXPECT_EQ(kShaderTypeVertex, sections[0].shader_type);
65 EXPECT_EQ(kShaderFormatSpirvAsm, sections[0].format);
66 EXPECT_EQ(kPassThroughShader, sections[0].contents);
67 }
68
TEST_F(SectionParserTest,SectionParserMultipleSections)69 TEST_F(SectionParserTest, SectionParserMultipleSections) {
70 std::string input = R"(
71 [comment]
72 This is a test.
73
74 [vertex shader passthrough]
75 [fragment shader]
76 #version 430
77 void main() {}
78
79 [geometry shader]
80 float4 main() {}
81
82 [comment]
83 Another comment section.
84 Multi line.
85
86 [indices]
87 1 2 3 4
88 5 6 7 8
89 [test]
90 test body.)";
91
92 SectionParser p;
93 Result r = p.SplitSectionsForTesting(input);
94 ASSERT_TRUE(r.IsSuccess()) << r.Error();
95
96 auto sections = p.Sections();
97 ASSERT_EQ(5U, sections.size());
98
99 // Passthrough vertext shader
100 EXPECT_EQ(NodeType::kShader, sections[0].section_type);
101 EXPECT_EQ(kShaderTypeVertex, sections[0].shader_type);
102 EXPECT_EQ(kShaderFormatSpirvAsm, sections[0].format);
103 EXPECT_EQ(kPassThroughShader, sections[0].contents);
104
105 // fragment shader
106 EXPECT_EQ(NodeType::kShader, sections[1].section_type);
107 EXPECT_EQ(kShaderTypeFragment, sections[1].shader_type);
108 EXPECT_EQ(kShaderFormatGlsl, sections[1].format);
109 EXPECT_EQ("#version 430\nvoid main() {}", sections[1].contents);
110
111 // geometry shader
112 EXPECT_EQ(NodeType::kShader, sections[2].section_type);
113 EXPECT_EQ(kShaderTypeGeometry, sections[2].shader_type);
114 EXPECT_EQ(kShaderFormatGlsl, sections[2].format);
115 EXPECT_EQ("float4 main() {}", sections[2].contents);
116
117 // indices
118 EXPECT_EQ(NodeType::kIndices, sections[3].section_type);
119 EXPECT_EQ(kShaderFormatText, sections[3].format);
120 EXPECT_EQ("1 2 3 4\n5 6 7 8", sections[3].contents);
121
122 // test
123 EXPECT_EQ(NodeType::kTest, sections[4].section_type);
124 EXPECT_EQ(kShaderFormatText, sections[4].format);
125 EXPECT_EQ("test body.", sections[4].contents);
126 }
127
TEST_F(SectionParserTest,SkipCommentLinesOutsideSections)128 TEST_F(SectionParserTest, SkipCommentLinesOutsideSections) {
129 std::string input = "# comment 1\n#comment 2\r\n[vertex shader]";
130
131 SectionParser p;
132 Result r = p.SplitSectionsForTesting(input);
133 ASSERT_TRUE(r.IsSuccess());
134
135 auto sections = p.Sections();
136 ASSERT_EQ(1U, sections.size());
137 EXPECT_EQ(NodeType::kShader, sections[0].section_type);
138 EXPECT_EQ(kShaderTypeVertex, sections[0].shader_type);
139 EXPECT_EQ(kShaderFormatGlsl, sections[0].format);
140 EXPECT_EQ("", sections[0].contents);
141 }
142
TEST_F(SectionParserTest,SkipBlankLinesOutsideSections)143 TEST_F(SectionParserTest, SkipBlankLinesOutsideSections) {
144 std::string input = "\n\r\n[vertex shader]";
145
146 SectionParser p;
147 Result r = p.SplitSectionsForTesting(input);
148 ASSERT_TRUE(r.IsSuccess()) << r.Error();
149
150 auto sections = p.Sections();
151 ASSERT_EQ(1U, sections.size());
152 EXPECT_EQ(NodeType::kShader, sections[0].section_type);
153 EXPECT_EQ(kShaderTypeVertex, sections[0].shader_type);
154 EXPECT_EQ(kShaderFormatGlsl, sections[0].format);
155 EXPECT_EQ("", sections[0].contents);
156 }
157
TEST_F(SectionParserTest,UnknownTextOutsideSection)158 TEST_F(SectionParserTest, UnknownTextOutsideSection) {
159 std::string input = "Invalid Text";
160
161 SectionParser p;
162 Result r = p.SplitSectionsForTesting(input);
163 EXPECT_FALSE(r.IsSuccess());
164 EXPECT_EQ("1: Invalid character", r.Error());
165 }
166
TEST_F(SectionParserTest,UnknownSectionName)167 TEST_F(SectionParserTest, UnknownSectionName) {
168 std::string input = "[Invalid Section]";
169
170 SectionParser p;
171 Result r = p.SplitSectionsForTesting(input);
172 EXPECT_FALSE(r.IsSuccess());
173 EXPECT_EQ("1: Invalid name: Invalid Section", r.Error());
174 }
175
TEST_F(SectionParserTest,MissingSectionClose)176 TEST_F(SectionParserTest, MissingSectionClose) {
177 std::string input = "[vertex shader\nMore Content";
178
179 SectionParser p;
180 Result r = p.SplitSectionsForTesting(input);
181 EXPECT_FALSE(r.IsSuccess());
182 EXPECT_EQ("1: Missing section close", r.Error());
183 }
184
TEST_F(SectionParserTest,NameToNodeType)185 TEST_F(SectionParserTest, NameToNodeType) {
186 struct {
187 const char* name;
188 NodeType section_type;
189 ShaderType shader_type;
190 ShaderFormat fmt;
191 } name_cases[] = {
192 {"comment", NodeType::kComment, kShaderTypeVertex, kShaderFormatText},
193 {"indices", NodeType::kIndices, kShaderTypeVertex, kShaderFormatText},
194 {"require", NodeType::kRequire, kShaderTypeVertex, kShaderFormatText},
195 {"test", NodeType::kTest, kShaderTypeVertex, kShaderFormatText},
196 {"vertex data", NodeType::kVertexData, kShaderTypeVertex,
197 kShaderFormatText},
198
199 {"compute shader", NodeType::kShader, kShaderTypeCompute,
200 kShaderFormatGlsl},
201 {"fragment shader", NodeType::kShader, kShaderTypeFragment,
202 kShaderFormatGlsl},
203 {"geometry shader", NodeType::kShader, kShaderTypeGeometry,
204 kShaderFormatGlsl},
205 {"tessellation control shader", NodeType::kShader,
206 kShaderTypeTessellationControl, kShaderFormatGlsl},
207 {"tessellation evaluation shader", NodeType::kShader,
208 kShaderTypeTessellationEvaluation, kShaderFormatGlsl},
209 {"vertex shader", NodeType::kShader, kShaderTypeVertex,
210 kShaderFormatGlsl},
211 {"compute shader spirv", NodeType::kShader, kShaderTypeCompute,
212 kShaderFormatSpirvAsm},
213 {"fragment shader spirv", NodeType::kShader, kShaderTypeFragment,
214 kShaderFormatSpirvAsm},
215 {"geometry shader spirv", NodeType::kShader, kShaderTypeGeometry,
216 kShaderFormatSpirvAsm},
217 {"tessellation control shader spirv", NodeType::kShader,
218 kShaderTypeTessellationControl, kShaderFormatSpirvAsm},
219 {"tessellation evaluation shader spirv", NodeType::kShader,
220 kShaderTypeTessellationEvaluation, kShaderFormatSpirvAsm},
221 {"vertex shader spirv", NodeType::kShader, kShaderTypeVertex,
222 kShaderFormatSpirvAsm},
223 {"compute shader spirv hex", NodeType::kShader, kShaderTypeCompute,
224 kShaderFormatSpirvHex},
225 {"fragment shader spirv hex", NodeType::kShader, kShaderTypeFragment,
226 kShaderFormatSpirvHex},
227 {"geometry shader spirv hex", NodeType::kShader, kShaderTypeGeometry,
228 kShaderFormatSpirvHex},
229 {"tessellation control shader spirv hex", NodeType::kShader,
230 kShaderTypeTessellationControl, kShaderFormatSpirvHex},
231 {"tessellation evaluation shader spirv hex", NodeType::kShader,
232 kShaderTypeTessellationEvaluation, kShaderFormatSpirvHex},
233 {"vertex shader spirv hex", NodeType::kShader, kShaderTypeVertex,
234 kShaderFormatSpirvHex},
235 {"vertex shader passthrough", NodeType::kShader, kShaderTypeVertex,
236 kShaderFormatDefault}};
237
238 for (auto name_case : name_cases) {
239 NodeType section_type = NodeType::kTest;
240 ShaderType shader_type = kShaderTypeVertex;
241 ShaderFormat fmt = kShaderFormatText;
242 SectionParser p;
243 Result r = p.NameToNodeTypeForTesting(name_case.name, §ion_type,
244 &shader_type, &fmt);
245
246 ASSERT_TRUE(r.IsSuccess()) << r.Error();
247 EXPECT_EQ(name_case.section_type, section_type) << name_case.name;
248 EXPECT_EQ(name_case.shader_type, shader_type) << name_case.name;
249 EXPECT_EQ(name_case.fmt, fmt) << name_case.name;
250 }
251 }
252
TEST_F(SectionParserTest,NameToNodeTypeInvalidName)253 TEST_F(SectionParserTest, NameToNodeTypeInvalidName) {
254 NodeType section_type = NodeType::kTest;
255 ShaderType shader_type = kShaderTypeVertex;
256 ShaderFormat fmt = kShaderFormatText;
257 SectionParser p;
258 Result r = p.NameToNodeTypeForTesting("InvalidName", §ion_type,
259 &shader_type, &fmt);
260 ASSERT_FALSE(r.IsSuccess());
261 EXPECT_EQ("Invalid name: InvalidName", r.Error());
262 }
263
TEST_F(SectionParserTest,NameToSectionInvalidSuffix)264 TEST_F(SectionParserTest, NameToSectionInvalidSuffix) {
265 struct {
266 const char* name;
267 } cases[] = {{"comment spirv"}, {"indices spirv"},
268 {"require spirv"}, {"test spirv"},
269 {"vertex data spirv"}, {"comment spirv hex"},
270 {"indices spirv hex"}, {"require spirv hex"},
271 {"test spirv hex"}, {"vertex data spirv hex"}};
272
273 for (auto name_case : cases) {
274 NodeType section_type = NodeType::kTest;
275 ShaderType shader_type = kShaderTypeVertex;
276 ShaderFormat fmt = kShaderFormatText;
277 SectionParser p;
278
279 Result r = p.NameToNodeTypeForTesting(name_case.name, §ion_type,
280 &shader_type, &fmt);
281 ASSERT_FALSE(r.IsSuccess()) << name_case.name;
282 EXPECT_EQ("Invalid source format: " + std::string(name_case.name),
283 r.Error());
284 }
285 }
286
TEST_F(SectionParserTest,HasShader)287 TEST_F(SectionParserTest, HasShader) {
288 EXPECT_TRUE(SectionParser::HasShader(NodeType::kShader));
289 }
290
TEST_F(SectionParserTest,HasNoShader)291 TEST_F(SectionParserTest, HasNoShader) {
292 const NodeType false_types[] = {NodeType::kComment, NodeType::kTest,
293 NodeType::kIndices, NodeType::kVertexData,
294 NodeType::kRequire};
295 for (auto type : false_types) {
296 EXPECT_FALSE(SectionParser::HasShader(type));
297 }
298 }
299
300 } // namespace vkscript
301 } // namespace amber
302