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/command_parser.h"
16 
17 #include "gtest/gtest.h"
18 #include "src/pipeline.h"
19 #include "src/vkscript/section_parser.h"
20 
21 namespace amber {
22 namespace vkscript {
23 
24 using CommandParserTest = testing::Test;
25 
TEST_F(CommandParserTest,MultipleCommands)26 TEST_F(CommandParserTest, MultipleCommands) {
27   std::string data = R"(# this is the test data
28 draw rect 1.2 2.3 200 400.2
29 # another comment
30 clear color 255 128 1 100 # set clear color
31 clear
32 # done)";
33 
34   Pipeline pipeline(PipelineType::kGraphics);
35   Script script;
36   CommandParser cp(&script, &pipeline, 1, data);
37   Result r = cp.Parse();
38   ASSERT_TRUE(r.IsSuccess()) << r.Error();
39 
40   auto& cmds = cp.Commands();
41   ASSERT_EQ(3U, cmds.size());
42   ASSERT_TRUE(cmds[0]->IsDrawRect());
43 
44   auto* draw_cmd = cmds[0]->AsDrawRect();
45   EXPECT_FALSE(draw_cmd->IsOrtho());
46   EXPECT_FALSE(draw_cmd->IsPatch());
47   EXPECT_FLOAT_EQ(1.2f, draw_cmd->GetX());
48   EXPECT_FLOAT_EQ(2.3f, draw_cmd->GetY());
49   EXPECT_FLOAT_EQ(200.0f, draw_cmd->GetWidth());
50   EXPECT_FLOAT_EQ(400.2f, draw_cmd->GetHeight());
51 
52   ASSERT_TRUE(cmds[1]->IsClearColor());
53 
54   auto* clear_cmd = cmds[1]->AsClearColor();
55   EXPECT_EQ(255, clear_cmd->GetR());
56   EXPECT_EQ(128, clear_cmd->GetG());
57   EXPECT_EQ(1, clear_cmd->GetB());
58   EXPECT_EQ(100, clear_cmd->GetA());
59 
60   ASSERT_TRUE(cmds[2]->IsClear());
61 }
62 
TEST_F(CommandParserTest,DISABLED_DrawArraysNonInstancedFollowedByCommand)63 TEST_F(CommandParserTest, DISABLED_DrawArraysNonInstancedFollowedByCommand) {}
64 
TEST_F(CommandParserTest,DISABLED_DrawArraysInstancedFollowedByCommand)65 TEST_F(CommandParserTest, DISABLED_DrawArraysInstancedFollowedByCommand) {}
66 
TEST_F(CommandParserTest,DISABLED_UnknownCommand)67 TEST_F(CommandParserTest, DISABLED_UnknownCommand) {}
68 
TEST_F(CommandParserTest,DrawRect)69 TEST_F(CommandParserTest, DrawRect) {
70   std::string data = "draw rect 1.2 2.3 200 400.2";
71 
72   Pipeline pipeline(PipelineType::kGraphics);
73   Script script;
74   CommandParser cp(&script, &pipeline, 1, data);
75   Result r = cp.Parse();
76   ASSERT_TRUE(r.IsSuccess()) << r.Error();
77 
78   auto& cmds = cp.Commands();
79   ASSERT_EQ(1U, cmds.size());
80   ASSERT_TRUE(cmds[0]->IsDrawRect());
81 
82   auto* cmd = cmds[0]->AsDrawRect();
83   EXPECT_FALSE(cmd->IsOrtho());
84   EXPECT_FALSE(cmd->IsPatch());
85   EXPECT_FLOAT_EQ(1.2f, cmd->GetX());
86   EXPECT_FLOAT_EQ(2.3f, cmd->GetY());
87   EXPECT_FLOAT_EQ(200.0f, cmd->GetWidth());
88   EXPECT_FLOAT_EQ(400.2f, cmd->GetHeight());
89 }
90 
TEST_F(CommandParserTest,DrawRectWithOrth)91 TEST_F(CommandParserTest, DrawRectWithOrth) {
92   std::string data = "draw rect ortho 1.2 2.3 200 400.2";
93 
94   Pipeline pipeline(PipelineType::kGraphics);
95   Script script;
96   CommandParser cp(&script, &pipeline, 1, data);
97   Result r = cp.Parse();
98   ASSERT_TRUE(r.IsSuccess()) << r.Error();
99 
100   auto& cmds = cp.Commands();
101   ASSERT_EQ(1U, cmds.size());
102   ASSERT_TRUE(cmds[0]->IsDrawRect());
103 
104   auto* cmd = cmds[0]->AsDrawRect();
105   EXPECT_TRUE(cmd->IsOrtho());
106   EXPECT_FALSE(cmd->IsPatch());
107   EXPECT_FLOAT_EQ(1.2f, cmd->GetX());
108   EXPECT_FLOAT_EQ(2.3f, cmd->GetY());
109   EXPECT_FLOAT_EQ(200.0f, cmd->GetWidth());
110   EXPECT_FLOAT_EQ(400.2f, cmd->GetHeight());
111 }
112 
TEST_F(CommandParserTest,DrawRectWithPatch)113 TEST_F(CommandParserTest, DrawRectWithPatch) {
114   std::string data = "draw rect patch 1.2 2.3 200 400.2";
115 
116   Pipeline pipeline(PipelineType::kGraphics);
117   Script script;
118   CommandParser cp(&script, &pipeline, 1, data);
119   Result r = cp.Parse();
120   ASSERT_TRUE(r.IsSuccess()) << r.Error();
121 
122   auto& cmds = cp.Commands();
123   ASSERT_EQ(1U, cmds.size());
124   ASSERT_TRUE(cmds[0]->IsDrawRect());
125 
126   auto* cmd = cmds[0]->AsDrawRect();
127   EXPECT_FALSE(cmd->IsOrtho());
128   EXPECT_TRUE(cmd->IsPatch());
129   EXPECT_FLOAT_EQ(1.2f, cmd->GetX());
130   EXPECT_FLOAT_EQ(2.3f, cmd->GetY());
131   EXPECT_FLOAT_EQ(200.0f, cmd->GetWidth());
132   EXPECT_FLOAT_EQ(400.2f, cmd->GetHeight());
133 }
134 
TEST_F(CommandParserTest,DrawRectWithOrthAndPatch)135 TEST_F(CommandParserTest, DrawRectWithOrthAndPatch) {
136   std::string data = "draw rect ortho patch 1.2 2.3 200 400.2";
137 
138   Pipeline pipeline(PipelineType::kGraphics);
139   Script script;
140   CommandParser cp(&script, &pipeline, 1, data);
141   Result r = cp.Parse();
142   ASSERT_TRUE(r.IsSuccess()) << r.Error();
143 
144   auto& cmds = cp.Commands();
145   ASSERT_EQ(1U, cmds.size());
146   ASSERT_TRUE(cmds[0]->IsDrawRect());
147 
148   auto* cmd = cmds[0]->AsDrawRect();
149   EXPECT_TRUE(cmd->IsOrtho());
150   EXPECT_TRUE(cmd->IsPatch());
151   EXPECT_FLOAT_EQ(1.2f, cmd->GetX());
152   EXPECT_FLOAT_EQ(2.3f, cmd->GetY());
153   EXPECT_FLOAT_EQ(200.0f, cmd->GetWidth());
154   EXPECT_FLOAT_EQ(400.2f, cmd->GetHeight());
155 }
156 
TEST_F(CommandParserTest,DrawRectTooShort)157 TEST_F(CommandParserTest, DrawRectTooShort) {
158   std::string data = "draw rect 1.2 2.3 400.2";
159 
160   Pipeline pipeline(PipelineType::kGraphics);
161   Script script;
162   CommandParser cp(&script, &pipeline, 1, data);
163   Result r = cp.Parse();
164   ASSERT_FALSE(r.IsSuccess());
165   EXPECT_EQ("1: Invalid conversion to double", r.Error());
166 }
167 
TEST_F(CommandParserTest,DrawRectExtraParameters)168 TEST_F(CommandParserTest, DrawRectExtraParameters) {
169   std::string data = "draw rect ortho patch 1.2 2.3 200 400.2 EXTRA";
170 
171   Pipeline pipeline(PipelineType::kGraphics);
172   Script script;
173   CommandParser cp(&script, &pipeline, 1, data);
174   Result r = cp.Parse();
175   ASSERT_FALSE(r.IsSuccess());
176   EXPECT_EQ("1: Extra parameter to draw rect command: EXTRA", r.Error());
177 }
178 
TEST_F(CommandParserTest,DrawArrays)179 TEST_F(CommandParserTest, DrawArrays) {
180   std::string data = "draw arrays GL_LINES 2 4";
181 
182   Pipeline pipeline(PipelineType::kGraphics);
183   Script script;
184   CommandParser cp(&script, &pipeline, 1, data);
185   Result r = cp.Parse();
186   ASSERT_TRUE(r.IsSuccess()) << r.Error();
187 
188   auto& cmds = cp.Commands();
189   ASSERT_EQ(1U, cmds.size());
190   ASSERT_TRUE(cmds[0]->IsDrawArrays());
191 
192   auto* cmd = cmds[0]->AsDrawArrays();
193   EXPECT_FALSE(cmd->IsIndexed());
194   EXPECT_EQ(static_cast<uint32_t>(1U), cmd->GetInstanceCount());
195   EXPECT_EQ(Topology::kLineList, cmd->GetTopology());
196   EXPECT_EQ(2U, cmd->GetFirstVertexIndex());
197   EXPECT_EQ(4U, cmd->GetVertexCount());
198 }
199 
TEST_F(CommandParserTest,DrawArraysIndexed)200 TEST_F(CommandParserTest, DrawArraysIndexed) {
201   std::string data = "draw arrays indexed TRIANGLE_FAN 2 4";
202 
203   Pipeline pipeline(PipelineType::kGraphics);
204   Script script;
205   CommandParser cp(&script, &pipeline, 1, data);
206   Result r = cp.Parse();
207   ASSERT_TRUE(r.IsSuccess()) << r.Error();
208 
209   auto& cmds = cp.Commands();
210   ASSERT_EQ(1U, cmds.size());
211   ASSERT_TRUE(cmds[0]->IsDrawArrays());
212 
213   auto* cmd = cmds[0]->AsDrawArrays();
214   EXPECT_TRUE(cmd->IsIndexed());
215   EXPECT_EQ(static_cast<uint32_t>(1U), cmd->GetInstanceCount());
216   EXPECT_EQ(Topology::kTriangleFan, cmd->GetTopology());
217   EXPECT_EQ(2U, cmd->GetFirstVertexIndex());
218   EXPECT_EQ(4U, cmd->GetVertexCount());
219 }
220 
TEST_F(CommandParserTest,DrawArraysExtraParams)221 TEST_F(CommandParserTest, DrawArraysExtraParams) {
222   std::string data = "draw arrays indexed TRIANGLE_FAN 2 4 EXTRA_PARAM";
223 
224   Pipeline pipeline(PipelineType::kGraphics);
225   Script script;
226   CommandParser cp(&script, &pipeline, 1, data);
227   Result r = cp.Parse();
228   ASSERT_FALSE(r.IsSuccess());
229   EXPECT_EQ("1: Extra parameter to draw arrays command: EXTRA_PARAM",
230             r.Error());
231 }
232 
TEST_F(CommandParserTest,DrawArraysInstanced)233 TEST_F(CommandParserTest, DrawArraysInstanced) {
234   std::string data = "draw arrays instanced LINE_LIST_WITH_ADJACENCY 2 9";
235 
236   Pipeline pipeline(PipelineType::kGraphics);
237   Script script;
238   CommandParser cp(&script, &pipeline, 1, data);
239   Result r = cp.Parse();
240   ASSERT_TRUE(r.IsSuccess()) << r.Error();
241 
242   auto& cmds = cp.Commands();
243   ASSERT_EQ(1U, cmds.size());
244   ASSERT_TRUE(cmds[0]->IsDrawArrays());
245 
246   auto* cmd = cmds[0]->AsDrawArrays();
247   EXPECT_FALSE(cmd->IsIndexed());
248   EXPECT_EQ(static_cast<uint32_t>(1U), cmd->GetInstanceCount());
249   EXPECT_EQ(Topology::kLineListWithAdjacency, cmd->GetTopology());
250   EXPECT_EQ(2U, cmd->GetFirstVertexIndex());
251   EXPECT_EQ(9U, cmd->GetVertexCount());
252 }
253 
TEST_F(CommandParserTest,DrawArraysInstancedExtraParams)254 TEST_F(CommandParserTest, DrawArraysInstancedExtraParams) {
255   std::string data =
256       "draw arrays instanced LINE_LIST_WITH_ADJACENCY 2 9 4 EXTRA_COMMAND";
257 
258   Pipeline pipeline(PipelineType::kGraphics);
259   Script script;
260   CommandParser cp(&script, &pipeline, 1, data);
261   Result r = cp.Parse();
262   ASSERT_FALSE(r.IsSuccess());
263   EXPECT_EQ("1: Extra parameter to draw arrays command: EXTRA_COMMAND",
264             r.Error());
265 }
266 
TEST_F(CommandParserTest,DrawArraysIndexedAndInstanced)267 TEST_F(CommandParserTest, DrawArraysIndexedAndInstanced) {
268   std::string data =
269       "draw arrays indexed instanced LINE_LIST_WITH_ADJACENCY 3 9";
270 
271   Pipeline pipeline(PipelineType::kGraphics);
272   Script script;
273   CommandParser cp(&script, &pipeline, 1, data);
274   Result r = cp.Parse();
275   ASSERT_TRUE(r.IsSuccess()) << r.Error();
276 
277   auto& cmds = cp.Commands();
278   ASSERT_EQ(1U, cmds.size());
279   ASSERT_TRUE(cmds[0]->IsDrawArrays());
280 
281   auto* cmd = cmds[0]->AsDrawArrays();
282   EXPECT_TRUE(cmd->IsIndexed());
283   EXPECT_EQ(static_cast<uint32_t>(1U), cmd->GetInstanceCount());
284   EXPECT_EQ(Topology::kLineListWithAdjacency, cmd->GetTopology());
285   EXPECT_EQ(3U, cmd->GetFirstVertexIndex());
286   EXPECT_EQ(9U, cmd->GetVertexCount());
287 }
288 
TEST_F(CommandParserTest,DrawArraysInstancedWithCount)289 TEST_F(CommandParserTest, DrawArraysInstancedWithCount) {
290   std::string data = "draw arrays instanced LINE_LIST_WITH_ADJACENCY 3 9 12";
291 
292   Pipeline pipeline(PipelineType::kGraphics);
293   Script script;
294   CommandParser cp(&script, &pipeline, 1, data);
295   Result r = cp.Parse();
296   ASSERT_TRUE(r.IsSuccess()) << r.Error();
297 
298   auto& cmds = cp.Commands();
299   ASSERT_EQ(1U, cmds.size());
300   ASSERT_TRUE(cmds[0]->IsDrawArrays());
301 
302   auto* cmd = cmds[0]->AsDrawArrays();
303   EXPECT_FALSE(cmd->IsIndexed());
304   EXPECT_EQ(12U, cmd->GetInstanceCount());
305   EXPECT_EQ(Topology::kLineListWithAdjacency, cmd->GetTopology());
306   EXPECT_EQ(3U, cmd->GetFirstVertexIndex());
307   EXPECT_EQ(9U, cmd->GetVertexCount());
308 }
309 
TEST_F(CommandParserTest,DrawArraysBadTopology)310 TEST_F(CommandParserTest, DrawArraysBadTopology) {
311   std::string data = "draw arrays UNKNOWN_TOPO 1 4";
312 
313   Pipeline pipeline(PipelineType::kGraphics);
314   Script script;
315   CommandParser cp(&script, &pipeline, 1, data);
316   Result r = cp.Parse();
317   ASSERT_FALSE(r.IsSuccess());
318   EXPECT_EQ("1: Unknown parameter to draw arrays: UNKNOWN_TOPO", r.Error());
319 }
320 
TEST_F(CommandParserTest,DrawArraysTooShort)321 TEST_F(CommandParserTest, DrawArraysTooShort) {
322   std::string data = "draw arrays PATCH_LIST 1";
323 
324   Pipeline pipeline(PipelineType::kGraphics);
325   Script script;
326   CommandParser cp(&script, &pipeline, 1, data);
327   Result r = cp.Parse();
328   ASSERT_FALSE(r.IsSuccess());
329   EXPECT_EQ("1: Missing integer vertex count value for draw arrays: ",
330             r.Error());
331 }
332 
TEST_F(CommandParserTest,DrawArraysInstanceCountWithoutInstanced)333 TEST_F(CommandParserTest, DrawArraysInstanceCountWithoutInstanced) {
334   std::string data = "draw arrays PATCH_LIST 1 2 3";
335 
336   Pipeline pipeline(PipelineType::kGraphics);
337   Script script;
338   CommandParser cp(&script, &pipeline, 1, data);
339   Result r = cp.Parse();
340   ASSERT_FALSE(r.IsSuccess());
341   EXPECT_EQ("1: Extra parameter to draw arrays command: 3", r.Error());
342 }
343 
TEST_F(CommandParserTest,DrawArraysMissingTopology)344 TEST_F(CommandParserTest, DrawArraysMissingTopology) {
345   std::string data = "draw arrays 1 2";
346 
347   Pipeline pipeline(PipelineType::kGraphics);
348   Script script;
349   CommandParser cp(&script, &pipeline, 1, data);
350   Result r = cp.Parse();
351   ASSERT_FALSE(r.IsSuccess());
352   EXPECT_EQ("1: Missing draw arrays topology", r.Error());
353 }
354 
TEST_F(CommandParserTest,Compute)355 TEST_F(CommandParserTest, Compute) {
356   std::string data = "compute 1 2 3";
357 
358   Pipeline pipeline(PipelineType::kGraphics);
359   Script script;
360   CommandParser cp(&script, &pipeline, 1, data);
361   Result r = cp.Parse();
362   ASSERT_TRUE(r.IsSuccess()) << r.Error();
363 
364   auto& cmds = cp.Commands();
365   ASSERT_EQ(1U, cmds.size());
366   ASSERT_TRUE(cmds[0]->IsCompute());
367 
368   auto* cmd = cmds[0]->AsCompute();
369   EXPECT_EQ(1U, cmd->GetX());
370   EXPECT_EQ(2U, cmd->GetY());
371   EXPECT_EQ(3U, cmd->GetZ());
372 }
373 
TEST_F(CommandParserTest,ComputeTooShort)374 TEST_F(CommandParserTest, ComputeTooShort) {
375   std::string data = "compute 1 2";
376 
377   Pipeline pipeline(PipelineType::kGraphics);
378   Script script;
379   CommandParser cp(&script, &pipeline, 1, data);
380   Result r = cp.Parse();
381   ASSERT_FALSE(r.IsSuccess());
382   EXPECT_EQ("1: Missing integer value for compute Z entry: ", r.Error());
383 }
384 
TEST_F(CommandParserTest,ComputeInvalidX)385 TEST_F(CommandParserTest, ComputeInvalidX) {
386   std::string data = "compute 1.2 2 3";
387 
388   Pipeline pipeline(PipelineType::kGraphics);
389   Script script;
390   CommandParser cp(&script, &pipeline, 1, data);
391   Result r = cp.Parse();
392   ASSERT_FALSE(r.IsSuccess());
393   EXPECT_EQ("1: Missing integer value for compute X entry: 1.2", r.Error());
394 }
395 
TEST_F(CommandParserTest,ComputeInvalidY)396 TEST_F(CommandParserTest, ComputeInvalidY) {
397   std::string data = "compute 1 a 3";
398 
399   Pipeline pipeline(PipelineType::kGraphics);
400   Script script;
401   CommandParser cp(&script, &pipeline, 1, data);
402   Result r = cp.Parse();
403   ASSERT_FALSE(r.IsSuccess());
404   EXPECT_EQ("1: Missing integer value for compute Y entry: a", r.Error());
405 }
406 
TEST_F(CommandParserTest,ComputeInvalidZ)407 TEST_F(CommandParserTest, ComputeInvalidZ) {
408   std::string data = "compute 1 2 1.5";
409 
410   Pipeline pipeline(PipelineType::kGraphics);
411   Script script;
412   CommandParser cp(&script, &pipeline, 1, data);
413   Result r = cp.Parse();
414   ASSERT_FALSE(r.IsSuccess());
415   EXPECT_EQ("1: Missing integer value for compute Z entry: 1.5", r.Error());
416 }
417 
TEST_F(CommandParserTest,ComputeExtraCommands)418 TEST_F(CommandParserTest, ComputeExtraCommands) {
419   std::string data = "compute 1 2 3 EXTRA";
420 
421   Pipeline pipeline(PipelineType::kGraphics);
422   Script script;
423   CommandParser cp(&script, &pipeline, 1, data);
424   Result r = cp.Parse();
425   ASSERT_FALSE(r.IsSuccess());
426   EXPECT_EQ("1: Extra parameter to compute command: EXTRA", r.Error());
427 }
428 
TEST_F(CommandParserTest,Clear)429 TEST_F(CommandParserTest, Clear) {
430   std::string data = "clear";
431 
432   Pipeline pipeline(PipelineType::kGraphics);
433   Script script;
434   CommandParser cp(&script, &pipeline, 1, data);
435   Result r = cp.Parse();
436   ASSERT_TRUE(r.IsSuccess()) << r.Error();
437 
438   auto& cmds = cp.Commands();
439   ASSERT_EQ(1U, cmds.size());
440   ASSERT_TRUE(cmds[0]->IsClear());
441 }
442 
TEST_F(CommandParserTest,ClearExtraParams)443 TEST_F(CommandParserTest, ClearExtraParams) {
444   std::string data = "clear EXTRA";
445 
446   Pipeline pipeline(PipelineType::kGraphics);
447   Script script;
448   CommandParser cp(&script, &pipeline, 1, data);
449   Result r = cp.Parse();
450   ASSERT_FALSE(r.IsSuccess());
451   EXPECT_EQ("1: Extra parameter to clear command: EXTRA", r.Error());
452 }
453 
TEST_F(CommandParserTest,ClearDepth)454 TEST_F(CommandParserTest, ClearDepth) {
455   std::string data = "clear depth 0.8";
456 
457   Pipeline pipeline(PipelineType::kGraphics);
458   Script script;
459   CommandParser cp(&script, &pipeline, 1, data);
460   Result r = cp.Parse();
461   ASSERT_TRUE(r.IsSuccess()) << r.Error();
462 
463   auto& cmds = cp.Commands();
464   ASSERT_EQ(1U, cmds.size());
465   ASSERT_TRUE(cmds[0]->IsClearDepth());
466 
467   auto* cmd = cmds[0]->AsClearDepth();
468   EXPECT_FLOAT_EQ(0.8f, cmd->GetValue());
469 }
470 
TEST_F(CommandParserTest,ClearDepthMissingValue)471 TEST_F(CommandParserTest, ClearDepthMissingValue) {
472   std::string data = "clear depth";
473 
474   Pipeline pipeline(PipelineType::kGraphics);
475   Script script;
476   CommandParser cp(&script, &pipeline, 1, data);
477   Result r = cp.Parse();
478   ASSERT_FALSE(r.IsSuccess());
479   EXPECT_EQ("1: Invalid conversion to double", r.Error());
480 }
481 
TEST_F(CommandParserTest,ClearDepthExtraParameters)482 TEST_F(CommandParserTest, ClearDepthExtraParameters) {
483   std::string data = "clear depth 0.2 EXTRA";
484 
485   Pipeline pipeline(PipelineType::kGraphics);
486   Script script;
487   CommandParser cp(&script, &pipeline, 1, data);
488   Result r = cp.Parse();
489   ASSERT_FALSE(r.IsSuccess());
490   EXPECT_EQ("1: Extra parameter to clear depth command: EXTRA", r.Error());
491 }
492 
TEST_F(CommandParserTest,ClearStencil)493 TEST_F(CommandParserTest, ClearStencil) {
494   std::string data = "clear stencil 8";
495 
496   Pipeline pipeline(PipelineType::kGraphics);
497   Script script;
498   CommandParser cp(&script, &pipeline, 1, data);
499   Result r = cp.Parse();
500   ASSERT_TRUE(r.IsSuccess()) << r.Error();
501 
502   auto& cmds = cp.Commands();
503   ASSERT_EQ(1U, cmds.size());
504   ASSERT_TRUE(cmds[0]->IsClearStencil());
505 
506   auto* cmd = cmds[0]->AsClearStencil();
507   EXPECT_EQ(8U, cmd->GetValue());
508 }
509 
TEST_F(CommandParserTest,ClearStencilMissingValue)510 TEST_F(CommandParserTest, ClearStencilMissingValue) {
511   std::string data = "clear stencil";
512 
513   Pipeline pipeline(PipelineType::kGraphics);
514   Script script;
515   CommandParser cp(&script, &pipeline, 1, data);
516   Result r = cp.Parse();
517   ASSERT_FALSE(r.IsSuccess());
518   EXPECT_EQ("1: Missing stencil value for clear stencil command: ", r.Error());
519 }
520 
TEST_F(CommandParserTest,ClearStencilExtraParameters)521 TEST_F(CommandParserTest, ClearStencilExtraParameters) {
522   std::string data = "clear stencil 2 EXTRA";
523 
524   Pipeline pipeline(PipelineType::kGraphics);
525   Script script;
526   CommandParser cp(&script, &pipeline, 1, data);
527   Result r = cp.Parse();
528   ASSERT_FALSE(r.IsSuccess());
529   EXPECT_EQ("1: Extra parameter to clear stencil command: EXTRA", r.Error());
530 }
531 
TEST_F(CommandParserTest,ClearStencilNotInteger)532 TEST_F(CommandParserTest, ClearStencilNotInteger) {
533   std::string data = "clear stencil 2.3";
534 
535   Pipeline pipeline(PipelineType::kGraphics);
536   Script script;
537   CommandParser cp(&script, &pipeline, 1, data);
538   Result r = cp.Parse();
539   ASSERT_FALSE(r.IsSuccess());
540   EXPECT_EQ("1: Invalid stencil value for clear stencil command: 2.3",
541             r.Error());
542 }
543 
TEST_F(CommandParserTest,ClearColor)544 TEST_F(CommandParserTest, ClearColor) {
545   std::string data = "clear color 0.8 0.4 0.2 1.3";
546 
547   Pipeline pipeline(PipelineType::kGraphics);
548   Script script;
549   CommandParser cp(&script, &pipeline, 1, data);
550   Result r = cp.Parse();
551   ASSERT_TRUE(r.IsSuccess()) << r.Error();
552 
553   auto& cmds = cp.Commands();
554   ASSERT_EQ(1U, cmds.size());
555   ASSERT_TRUE(cmds[0]->IsClearColor());
556 
557   auto* cmd = cmds[0]->AsClearColor();
558   EXPECT_FLOAT_EQ(0.8f, cmd->GetR());
559   EXPECT_FLOAT_EQ(0.4f, cmd->GetG());
560   EXPECT_FLOAT_EQ(0.2f, cmd->GetB());
561   EXPECT_FLOAT_EQ(1.3f, cmd->GetA());
562 }
563 
TEST_F(CommandParserTest,ClearColorMissingParams)564 TEST_F(CommandParserTest, ClearColorMissingParams) {
565   std::string data = "clear color 0.8 0.4 0.2";
566 
567   Pipeline pipeline(PipelineType::kGraphics);
568   Script script;
569   CommandParser cp(&script, &pipeline, 1, data);
570   Result r = cp.Parse();
571   ASSERT_FALSE(r.IsSuccess());
572   EXPECT_EQ("1: Invalid conversion to double", r.Error());
573 }
574 
TEST_F(CommandParserTest,ClearColorExtraParams)575 TEST_F(CommandParserTest, ClearColorExtraParams) {
576   std::string data = "clear color 0.8 0.4 0.2 1.3 EXTRA";
577 
578   Pipeline pipeline(PipelineType::kGraphics);
579   Script script;
580   CommandParser cp(&script, &pipeline, 1, data);
581   Result r = cp.Parse();
582   ASSERT_FALSE(r.IsSuccess());
583   EXPECT_EQ("1: Extra parameter to clear color command: EXTRA", r.Error());
584 }
585 
TEST_F(CommandParserTest,ClearColorBadR)586 TEST_F(CommandParserTest, ClearColorBadR) {
587   std::string data = "clear color a 0.4 0.2 0.4";
588 
589   Pipeline pipeline(PipelineType::kGraphics);
590   Script script;
591   CommandParser cp(&script, &pipeline, 1, data);
592   Result r = cp.Parse();
593   ASSERT_FALSE(r.IsSuccess());
594   EXPECT_EQ("1: Invalid conversion to double", r.Error());
595 }
596 
TEST_F(CommandParserTest,ClearColorBadG)597 TEST_F(CommandParserTest, ClearColorBadG) {
598   std::string data = "clear color 0.2 a 0.2 0.4";
599 
600   Pipeline pipeline(PipelineType::kGraphics);
601   Script script;
602   CommandParser cp(&script, &pipeline, 1, data);
603   Result r = cp.Parse();
604   ASSERT_FALSE(r.IsSuccess());
605   EXPECT_EQ("1: Invalid conversion to double", r.Error());
606 }
607 
TEST_F(CommandParserTest,ClearColorBadB)608 TEST_F(CommandParserTest, ClearColorBadB) {
609   std::string data = "clear color 0.2 0.4 a 0.2";
610 
611   Pipeline pipeline(PipelineType::kGraphics);
612   Script script;
613   CommandParser cp(&script, &pipeline, 1, data);
614   Result r = cp.Parse();
615   ASSERT_FALSE(r.IsSuccess());
616   EXPECT_EQ("1: Invalid conversion to double", r.Error());
617 }
618 
TEST_F(CommandParserTest,ClearColorBadA)619 TEST_F(CommandParserTest, ClearColorBadA) {
620   std::string data = "clear color 0.2 0.4 0.2 a";
621 
622   Pipeline pipeline(PipelineType::kGraphics);
623   Script script;
624   CommandParser cp(&script, &pipeline, 1, data);
625   Result r = cp.Parse();
626   ASSERT_FALSE(r.IsSuccess());
627   EXPECT_EQ("1: Invalid conversion to double", r.Error());
628 }
629 
TEST_F(CommandParserTest,PatchParameterVertices)630 TEST_F(CommandParserTest, PatchParameterVertices) {
631   std::string data = "patch parameter vertices 9";
632 
633   Pipeline pipeline(PipelineType::kGraphics);
634   Script script;
635   CommandParser cp(&script, &pipeline, 1, data);
636   Result r = cp.Parse();
637   ASSERT_TRUE(r.IsSuccess()) << r.Error();
638 
639   auto& cmds = cp.Commands();
640   ASSERT_EQ(1U, cmds.size());
641   ASSERT_TRUE(cmds[0]->IsPatchParameterVertices());
642 
643   auto* cmd = cmds[0]->AsPatchParameterVertices();
644   EXPECT_EQ(9U, cmd->GetControlPointCount());
645 }
646 
TEST_F(CommandParserTest,PatchParameterVerticesMissingParameter)647 TEST_F(CommandParserTest, PatchParameterVerticesMissingParameter) {
648   std::string data = "patch vertices 5";
649 
650   Pipeline pipeline(PipelineType::kGraphics);
651   Script script;
652   CommandParser cp(&script, &pipeline, 1, data);
653   Result r = cp.Parse();
654   ASSERT_FALSE(r.IsSuccess());
655   EXPECT_EQ("1: Missing parameter flag to patch command: vertices", r.Error());
656 }
657 
TEST_F(CommandParserTest,PatchParameterVerticesMissingVertices)658 TEST_F(CommandParserTest, PatchParameterVerticesMissingVertices) {
659   std::string data = "patch parameter 5";
660 
661   Pipeline pipeline(PipelineType::kGraphics);
662   Script script;
663   CommandParser cp(&script, &pipeline, 1, data);
664   Result r = cp.Parse();
665   ASSERT_FALSE(r.IsSuccess());
666   EXPECT_EQ("1: Missing vertices flag to patch command: 5", r.Error());
667 }
668 
TEST_F(CommandParserTest,PatchParameterVerticesMissingParam)669 TEST_F(CommandParserTest, PatchParameterVerticesMissingParam) {
670   std::string data = "patch parameter vertices";
671 
672   Pipeline pipeline(PipelineType::kGraphics);
673   Script script;
674   CommandParser cp(&script, &pipeline, 1, data);
675   Result r = cp.Parse();
676   ASSERT_FALSE(r.IsSuccess());
677   EXPECT_EQ("1: Invalid count parameter for patch parameter vertices: ",
678             r.Error());
679 }
680 
TEST_F(CommandParserTest,PatchParameterVerticesInvalidParam)681 TEST_F(CommandParserTest, PatchParameterVerticesInvalidParam) {
682   std::string data = "patch parameter vertices invalid";
683 
684   Pipeline pipeline(PipelineType::kGraphics);
685   Script script;
686   CommandParser cp(&script, &pipeline, 1, data);
687   Result r = cp.Parse();
688   ASSERT_FALSE(r.IsSuccess());
689   EXPECT_EQ("1: Invalid count parameter for patch parameter vertices: invalid",
690             r.Error());
691 }
692 
TEST_F(CommandParserTest,PatchParameterVerticesExtraParam)693 TEST_F(CommandParserTest, PatchParameterVerticesExtraParam) {
694   std::string data = "patch parameter vertices 3 EXTRA";
695 
696   Pipeline pipeline(PipelineType::kGraphics);
697   Script script;
698   CommandParser cp(&script, &pipeline, 1, data);
699   Result r = cp.Parse();
700   ASSERT_FALSE(r.IsSuccess());
701   EXPECT_EQ("1: Extra parameter for patch parameter vertices command: EXTRA",
702             r.Error());
703 }
704 
705 struct EntryInfo {
706   const char* name;
707   ShaderType type;
708 };
709 static const EntryInfo kEntryPoints[] = {
710     {"vertex", kShaderTypeVertex},
711     {"fragment", kShaderTypeFragment},
712     {"geometry", kShaderTypeGeometry},
713     {"compute", kShaderTypeCompute},
714     {"tessellation evaluation", kShaderTypeTessellationEvaluation},
715     {"tessellation control", kShaderTypeTessellationControl},
716 };
717 
TEST_F(CommandParserTest,EntryPoint)718 TEST_F(CommandParserTest, EntryPoint) {
719   for (const auto& ep : kEntryPoints) {
720     std::string data = std::string(ep.name) + " entrypoint main";
721 
722     Pipeline pipeline(PipelineType::kGraphics);
723     Script script;
724     CommandParser cp(&script, &pipeline, 1, data);
725     Result r = cp.Parse();
726     ASSERT_TRUE(r.IsSuccess()) << r.Error();
727 
728     auto& cmds = cp.Commands();
729     ASSERT_EQ(1U, cmds.size());
730     ASSERT_TRUE(cmds[0]->IsEntryPoint());
731 
732     auto* cmd = cmds[0]->AsEntryPoint();
733     EXPECT_EQ(ep.type, cmd->GetShaderType());
734     EXPECT_EQ("main", cmd->GetEntryPointName());
735   }
736 }
737 
TEST_F(CommandParserTest,EntryPointNameMissing)738 TEST_F(CommandParserTest, EntryPointNameMissing) {
739   for (const auto& ep : kEntryPoints) {
740     std::string data = std::string(ep.name) + " entrypoint";
741 
742     Pipeline pipeline(PipelineType::kGraphics);
743     Script script;
744     CommandParser cp(&script, &pipeline, 1, data);
745     Result r = cp.Parse();
746     ASSERT_FALSE(r.IsSuccess());
747     EXPECT_EQ("1: Missing entrypoint name", r.Error());
748   }
749 }
750 
TEST_F(CommandParserTest,EntryPointEntryPointMissing)751 TEST_F(CommandParserTest, EntryPointEntryPointMissing) {
752   for (const auto& ep : kEntryPoints) {
753     // Skip compute because compute is also a command ....
754     if (std::string(ep.name) == "compute")
755       continue;
756 
757     std::string data = std::string(ep.name) + " main";
758 
759     Pipeline pipeline(PipelineType::kGraphics);
760     Script script;
761     CommandParser cp(&script, &pipeline, 1, data);
762     Result r = cp.Parse();
763     ASSERT_FALSE(r.IsSuccess());
764     EXPECT_EQ("1: Unknown command: " + std::string(ep.name), r.Error());
765   }
766 }
767 
TEST_F(CommandParserTest,EntryPointExtraParam)768 TEST_F(CommandParserTest, EntryPointExtraParam) {
769   for (const auto& ep : kEntryPoints) {
770     std::string data = std::string(ep.name) + " entrypoint main EXTRA";
771 
772     Pipeline pipeline(PipelineType::kGraphics);
773     Script script;
774     CommandParser cp(&script, &pipeline, 1, data);
775     Result r = cp.Parse();
776     ASSERT_FALSE(r.IsSuccess());
777     EXPECT_EQ("1: Extra parameter for entrypoint command: EXTRA", r.Error());
778   }
779 }
780 
TEST_F(CommandParserTest,EntryPointInvalidValue)781 TEST_F(CommandParserTest, EntryPointInvalidValue) {
782   for (const auto& ep : kEntryPoints) {
783     std::string data = std::string(ep.name) + " entrypoint 123";
784 
785     Pipeline pipeline(PipelineType::kGraphics);
786     Script script;
787     CommandParser cp(&script, &pipeline, 1, data);
788     Result r = cp.Parse();
789     ASSERT_FALSE(r.IsSuccess());
790     EXPECT_EQ("1: Entrypoint name must be a string: 123", r.Error());
791   }
792 }
793 
TEST_F(CommandParserTest,TessellationEntryPointRequiresASuffix)794 TEST_F(CommandParserTest, TessellationEntryPointRequiresASuffix) {
795   std::string data = "tessellation entrypoint main";
796 
797   Pipeline pipeline(PipelineType::kGraphics);
798   Script script;
799   CommandParser cp(&script, &pipeline, 1, data);
800   Result r = cp.Parse();
801   ASSERT_FALSE(r.IsSuccess());
802   EXPECT_EQ(
803       "1: Tessellation entrypoint must have <evaluation|control> in name: "
804       "entrypoint",
805       r.Error());
806 }
807 
TEST_F(CommandParserTest,TessellationEntryPointRequiresAKnownSuffix)808 TEST_F(CommandParserTest, TessellationEntryPointRequiresAKnownSuffix) {
809   std::string data = "tessellation unknown entrypoint main";
810 
811   Pipeline pipeline(PipelineType::kGraphics);
812   Script script;
813   CommandParser cp(&script, &pipeline, 1, data);
814   Result r = cp.Parse();
815   ASSERT_FALSE(r.IsSuccess());
816   EXPECT_EQ(
817       "1: Tessellation entrypoint must have <evaluation|control> in name: "
818       "unknown",
819       r.Error());
820 }
821 
TEST_F(CommandParserTest,InvalidEntryPoint)822 TEST_F(CommandParserTest, InvalidEntryPoint) {
823   std::string data = "unknown entrypoint main";
824 
825   Pipeline pipeline(PipelineType::kGraphics);
826   Script script;
827   CommandParser cp(&script, &pipeline, 1, data);
828   Result r = cp.Parse();
829   ASSERT_FALSE(r.IsSuccess());
830   EXPECT_EQ("1: Unknown command: unknown", r.Error());
831 }
832 
833 using CommandParserProbeTest = testing::TestWithParam<bool>;
834 
TEST_P(CommandParserProbeTest,ProbeRgb)835 TEST_P(CommandParserProbeTest, ProbeRgb) {
836   bool is_relative = GetParam();
837 
838   std::string data = (is_relative ? std::string("relative ") : std::string()) +
839                      "probe rgb 25 30 0.2 0.4 0.6";
840 
841   Pipeline pipeline(PipelineType::kGraphics);
842   auto color_buf = pipeline.GenerateDefaultColorAttachmentBuffer();
843   pipeline.AddColorAttachment(color_buf.get(), 0, 0);
844 
845   Script script;
846   CommandParser cp(&script, &pipeline, 1, data);
847   Result r = cp.Parse();
848   ASSERT_TRUE(r.IsSuccess()) << data << std::endl << r.Error();
849 
850   auto& cmds = cp.Commands();
851   ASSERT_EQ(1U, cmds.size());
852   ASSERT_TRUE(cmds[0]->IsProbe());
853 
854   auto* cmd = cmds[0]->AsProbe();
855   EXPECT_EQ(is_relative, cmd->IsRelative());
856   EXPECT_FALSE(cmd->IsWholeWindow());
857   EXPECT_FALSE(cmd->IsProbeRect());
858   EXPECT_FALSE(cmd->IsRGBA());
859 
860   EXPECT_FLOAT_EQ(25U, cmd->GetX());
861   EXPECT_FLOAT_EQ(30U, cmd->GetY());
862   EXPECT_FLOAT_EQ(1U, cmd->GetWidth());
863   EXPECT_FLOAT_EQ(1U, cmd->GetHeight());
864 
865   EXPECT_FLOAT_EQ(0.2f, cmd->GetR());
866   EXPECT_FLOAT_EQ(0.4f, cmd->GetG());
867   EXPECT_FLOAT_EQ(0.6f, cmd->GetB());
868 }
869 
TEST_P(CommandParserProbeTest,ProbeRgba)870 TEST_P(CommandParserProbeTest, ProbeRgba) {
871   bool is_relative = GetParam();
872 
873   std::string data = (is_relative ? std::string("relative ") : std::string()) +
874                      "probe rgba 25 30 1 255 9 4";
875 
876   Pipeline pipeline(PipelineType::kGraphics);
877   auto color_buf = pipeline.GenerateDefaultColorAttachmentBuffer();
878   pipeline.AddColorAttachment(color_buf.get(), 0, 0);
879 
880   Script script;
881   CommandParser cp(&script, &pipeline, 1, data);
882   Result r = cp.Parse();
883   ASSERT_TRUE(r.IsSuccess()) << data << std::endl << r.Error();
884 
885   auto& cmds = cp.Commands();
886   ASSERT_EQ(1U, cmds.size());
887   ASSERT_TRUE(cmds[0]->IsProbe());
888 
889   auto* cmd = cmds[0]->AsProbe();
890   EXPECT_EQ(is_relative, cmd->IsRelative());
891   EXPECT_FALSE(cmd->IsWholeWindow());
892   EXPECT_FALSE(cmd->IsProbeRect());
893   EXPECT_TRUE(cmd->IsRGBA());
894 
895   EXPECT_FLOAT_EQ(25U, cmd->GetX());
896   EXPECT_FLOAT_EQ(30U, cmd->GetY());
897   EXPECT_FLOAT_EQ(1U, cmd->GetWidth());
898   EXPECT_FLOAT_EQ(1U, cmd->GetHeight());
899 
900   EXPECT_FLOAT_EQ(1.0f, cmd->GetR());
901   EXPECT_FLOAT_EQ(255.0f, cmd->GetG());
902   EXPECT_FLOAT_EQ(9.0f, cmd->GetB());
903   EXPECT_FLOAT_EQ(4.0f, cmd->GetA());
904 }
905 
TEST_P(CommandParserProbeTest,ProbeRect)906 TEST_P(CommandParserProbeTest, ProbeRect) {
907   bool is_relative = GetParam();
908 
909   std::string data = (is_relative ? std::string("relative ") : std::string()) +
910                      "probe rect rgba 25 30 200 400 1 255 9 4";
911 
912   Pipeline pipeline(PipelineType::kGraphics);
913   auto color_buf = pipeline.GenerateDefaultColorAttachmentBuffer();
914   pipeline.AddColorAttachment(color_buf.get(), 0, 0);
915 
916   Script script;
917   CommandParser cp(&script, &pipeline, 1, data);
918   Result r = cp.Parse();
919   ASSERT_TRUE(r.IsSuccess()) << data << std::endl << r.Error();
920 
921   auto& cmds = cp.Commands();
922   ASSERT_EQ(1U, cmds.size());
923   ASSERT_TRUE(cmds[0]->IsProbe());
924 
925   auto* cmd = cmds[0]->AsProbe();
926   EXPECT_EQ(is_relative, cmd->IsRelative());
927   EXPECT_FALSE(cmd->IsWholeWindow());
928   EXPECT_TRUE(cmd->IsProbeRect());
929   EXPECT_TRUE(cmd->IsRGBA());
930 
931   EXPECT_FLOAT_EQ(25U, cmd->GetX());
932   EXPECT_FLOAT_EQ(30U, cmd->GetY());
933   EXPECT_FLOAT_EQ(200U, cmd->GetWidth());
934   EXPECT_FLOAT_EQ(400U, cmd->GetHeight());
935 
936   EXPECT_FLOAT_EQ(1.0f, cmd->GetR());
937   EXPECT_FLOAT_EQ(255.0f, cmd->GetG());
938   EXPECT_FLOAT_EQ(9.0f, cmd->GetB());
939   EXPECT_FLOAT_EQ(4.0f, cmd->GetA());
940 }
941 
TEST_P(CommandParserProbeTest,ProbeNotRect)942 TEST_P(CommandParserProbeTest, ProbeNotRect) {
943   bool is_relative = GetParam();
944 
945   std::string data = (is_relative ? std::string("relative ") : std::string()) +
946                      "probe rgba 25 30 1 255 9 4";
947 
948   Pipeline pipeline(PipelineType::kGraphics);
949   auto color_buf = pipeline.GenerateDefaultColorAttachmentBuffer();
950   pipeline.AddColorAttachment(color_buf.get(), 0, 0);
951 
952   Script script;
953   CommandParser cp(&script, &pipeline, 1, data);
954   Result r = cp.Parse();
955   ASSERT_TRUE(r.IsSuccess()) << data << std::endl << r.Error();
956 
957   auto& cmds = cp.Commands();
958   ASSERT_EQ(1U, cmds.size());
959   ASSERT_TRUE(cmds[0]->IsProbe());
960 
961   auto* cmd = cmds[0]->AsProbe();
962   EXPECT_EQ(is_relative, cmd->IsRelative());
963   EXPECT_FALSE(cmd->IsWholeWindow());
964   EXPECT_FALSE(cmd->IsProbeRect());
965   EXPECT_TRUE(cmd->IsRGBA());
966 
967   EXPECT_FLOAT_EQ(25U, cmd->GetX());
968   EXPECT_FLOAT_EQ(30U, cmd->GetY());
969   EXPECT_FLOAT_EQ(1.0f, cmd->GetWidth());
970   EXPECT_FLOAT_EQ(1.0f, cmd->GetHeight());
971 
972   EXPECT_FLOAT_EQ(1.0f, cmd->GetR());
973   EXPECT_FLOAT_EQ(255.0f, cmd->GetG());
974   EXPECT_FLOAT_EQ(9.0f, cmd->GetB());
975   EXPECT_FLOAT_EQ(4.0f, cmd->GetA());
976 }
977 
978 INSTANTIATE_TEST_SUITE_P(ProbeTests,
979                          CommandParserProbeTest,
980                          testing::Values(false,
981                                          true));  // NOLINT(whitespace/parens)
982 
TEST_F(CommandParserTest,ProbeAllRGB)983 TEST_F(CommandParserTest, ProbeAllRGB) {
984   std::string data = "probe all rgb 0.2 0.3 0.4";
985 
986   Pipeline pipeline(PipelineType::kGraphics);
987   auto color_buf = pipeline.GenerateDefaultColorAttachmentBuffer();
988   pipeline.AddColorAttachment(color_buf.get(), 0, 0);
989 
990   Script script;
991   CommandParser cp(&script, &pipeline, 1, data);
992   Result r = cp.Parse();
993   ASSERT_TRUE(r.IsSuccess()) << r.Error();
994 
995   auto& cmds = cp.Commands();
996   ASSERT_EQ(1U, cmds.size());
997   ASSERT_TRUE(cmds[0]->IsProbe());
998 
999   auto* cmd = cmds[0]->AsProbe();
1000   EXPECT_FALSE(cmd->IsRelative());
1001   EXPECT_TRUE(cmd->IsWholeWindow());
1002   EXPECT_TRUE(cmd->IsProbeRect());
1003   EXPECT_FALSE(cmd->IsRGBA());
1004 
1005   EXPECT_FLOAT_EQ(0.2f, cmd->GetR());
1006   EXPECT_FLOAT_EQ(0.3f, cmd->GetG());
1007   EXPECT_FLOAT_EQ(0.4f, cmd->GetB());
1008 }
1009 
TEST_F(CommandParserTest,ProbeAllRGBA)1010 TEST_F(CommandParserTest, ProbeAllRGBA) {
1011   std::string data = "probe all rgba 0.2 0.3 0.4 0.5";
1012 
1013   Pipeline pipeline(PipelineType::kGraphics);
1014   auto color_buf = pipeline.GenerateDefaultColorAttachmentBuffer();
1015   pipeline.AddColorAttachment(color_buf.get(), 0, 0);
1016 
1017   Script script;
1018   CommandParser cp(&script, &pipeline, 1, data);
1019   Result r = cp.Parse();
1020   ASSERT_TRUE(r.IsSuccess()) << r.Error();
1021 
1022   auto& cmds = cp.Commands();
1023   ASSERT_EQ(1U, cmds.size());
1024   ASSERT_TRUE(cmds[0]->IsProbe());
1025 
1026   auto* cmd = cmds[0]->AsProbe();
1027   EXPECT_FALSE(cmd->IsRelative());
1028   EXPECT_TRUE(cmd->IsWholeWindow());
1029   EXPECT_TRUE(cmd->IsProbeRect());
1030   EXPECT_TRUE(cmd->IsRGBA());
1031 
1032   EXPECT_FLOAT_EQ(0.2f, cmd->GetR());
1033   EXPECT_FLOAT_EQ(0.3f, cmd->GetG());
1034   EXPECT_FLOAT_EQ(0.4f, cmd->GetB());
1035   EXPECT_FLOAT_EQ(0.5f, cmd->GetA());
1036 }
1037 
TEST_F(CommandParserTest,ProbeCommandRectBrackets)1038 TEST_F(CommandParserTest, ProbeCommandRectBrackets) {
1039   std::string data = "relative probe rect rgb (0.5, 0.6, 0.3, 0.4) 1 2 3";
1040 
1041   Pipeline pipeline(PipelineType::kGraphics);
1042   auto color_buf = pipeline.GenerateDefaultColorAttachmentBuffer();
1043   pipeline.AddColorAttachment(color_buf.get(), 0, 0);
1044 
1045   Script script;
1046   CommandParser cp(&script, &pipeline, 1, data);
1047   Result r = cp.Parse();
1048   ASSERT_TRUE(r.IsSuccess()) << r.Error();
1049 
1050   auto& cmds = cp.Commands();
1051   ASSERT_EQ(1U, cmds.size());
1052   ASSERT_TRUE(cmds[0]->IsProbe());
1053 
1054   auto* cmd = cmds[0]->AsProbe();
1055   EXPECT_TRUE(cmd->IsRelative());
1056   EXPECT_FALSE(cmd->IsWholeWindow());
1057   EXPECT_TRUE(cmd->IsProbeRect());
1058   EXPECT_FALSE(cmd->IsRGBA());
1059 
1060   EXPECT_FLOAT_EQ(0.5f, cmd->GetX());
1061   EXPECT_FLOAT_EQ(0.6f, cmd->GetY());
1062   EXPECT_FLOAT_EQ(0.3f, cmd->GetWidth());
1063   EXPECT_FLOAT_EQ(0.4f, cmd->GetHeight());
1064 
1065   EXPECT_FLOAT_EQ(1.0f, cmd->GetR());
1066   EXPECT_FLOAT_EQ(2.0f, cmd->GetG());
1067   EXPECT_FLOAT_EQ(3.0f, cmd->GetB());
1068 }
1069 
TEST_F(CommandParserTest,ProbeCommandNotRectBrackets)1070 TEST_F(CommandParserTest, ProbeCommandNotRectBrackets) {
1071   std::string data = "relative probe rgb (0.5, 0.6) 1 2 3";
1072 
1073   Pipeline pipeline(PipelineType::kGraphics);
1074   auto color_buf = pipeline.GenerateDefaultColorAttachmentBuffer();
1075   pipeline.AddColorAttachment(color_buf.get(), 0, 0);
1076 
1077   Script script;
1078   CommandParser cp(&script, &pipeline, 1, data);
1079   Result r = cp.Parse();
1080   ASSERT_TRUE(r.IsSuccess()) << r.Error();
1081 
1082   auto& cmds = cp.Commands();
1083   ASSERT_EQ(1U, cmds.size());
1084   ASSERT_TRUE(cmds[0]->IsProbe());
1085 
1086   auto* cmd = cmds[0]->AsProbe();
1087   EXPECT_TRUE(cmd->IsRelative());
1088   EXPECT_FALSE(cmd->IsWholeWindow());
1089   EXPECT_FALSE(cmd->IsProbeRect());
1090   EXPECT_FALSE(cmd->IsRGBA());
1091 
1092   EXPECT_FLOAT_EQ(0.5f, cmd->GetX());
1093   EXPECT_FLOAT_EQ(0.6f, cmd->GetY());
1094   EXPECT_FLOAT_EQ(1.0f, cmd->GetWidth());
1095   EXPECT_FLOAT_EQ(1.0f, cmd->GetHeight());
1096 
1097   EXPECT_FLOAT_EQ(1.0f, cmd->GetR());
1098   EXPECT_FLOAT_EQ(2.0f, cmd->GetG());
1099   EXPECT_FLOAT_EQ(3.0f, cmd->GetB());
1100 }
1101 
TEST_F(CommandParserTest,ProbeCommandColorBrackets)1102 TEST_F(CommandParserTest, ProbeCommandColorBrackets) {
1103   std::string data = "relative probe rect rgb 0.5 0.6 0.3 0.4 (1, 2, 3)";
1104 
1105   Pipeline pipeline(PipelineType::kGraphics);
1106   auto color_buf = pipeline.GenerateDefaultColorAttachmentBuffer();
1107   pipeline.AddColorAttachment(color_buf.get(), 0, 0);
1108 
1109   Script script;
1110   CommandParser cp(&script, &pipeline, 1, data);
1111   Result r = cp.Parse();
1112   ASSERT_TRUE(r.IsSuccess()) << r.Error();
1113 
1114   auto& cmds = cp.Commands();
1115   ASSERT_EQ(1U, cmds.size());
1116   ASSERT_TRUE(cmds[0]->IsProbe());
1117 
1118   auto* cmd = cmds[0]->AsProbe();
1119   EXPECT_TRUE(cmd->IsRelative());
1120   EXPECT_FALSE(cmd->IsWholeWindow());
1121   EXPECT_TRUE(cmd->IsProbeRect());
1122   EXPECT_FALSE(cmd->IsRGBA());
1123 
1124   EXPECT_FLOAT_EQ(0.5f, cmd->GetX());
1125   EXPECT_FLOAT_EQ(0.6f, cmd->GetY());
1126   EXPECT_FLOAT_EQ(0.3f, cmd->GetWidth());
1127   EXPECT_FLOAT_EQ(0.4f, cmd->GetHeight());
1128 
1129   EXPECT_FLOAT_EQ(1.0f, cmd->GetR());
1130   EXPECT_FLOAT_EQ(2.0f, cmd->GetG());
1131   EXPECT_FLOAT_EQ(3.0f, cmd->GetB());
1132 }
1133 
TEST_F(CommandParserTest,ProbeCommandColorOptionalCommas)1134 TEST_F(CommandParserTest, ProbeCommandColorOptionalCommas) {
1135   std::string data = "relative probe rect rgb 0.5, 0.6, 0.3 0.4 1 2 3";
1136 
1137   Pipeline pipeline(PipelineType::kGraphics);
1138   auto color_buf = pipeline.GenerateDefaultColorAttachmentBuffer();
1139   pipeline.AddColorAttachment(color_buf.get(), 0, 0);
1140 
1141   Script script;
1142   CommandParser cp(&script, &pipeline, 1, data);
1143   Result r = cp.Parse();
1144   ASSERT_TRUE(r.IsSuccess()) << r.Error();
1145 
1146   auto& cmds = cp.Commands();
1147   ASSERT_EQ(1U, cmds.size());
1148   ASSERT_TRUE(cmds[0]->IsProbe());
1149 
1150   auto* cmd = cmds[0]->AsProbe();
1151   EXPECT_TRUE(cmd->IsRelative());
1152   EXPECT_FALSE(cmd->IsWholeWindow());
1153   EXPECT_TRUE(cmd->IsProbeRect());
1154   EXPECT_FALSE(cmd->IsRGBA());
1155 
1156   EXPECT_FLOAT_EQ(0.5f, cmd->GetX());
1157   EXPECT_FLOAT_EQ(0.6f, cmd->GetY());
1158   EXPECT_FLOAT_EQ(0.3f, cmd->GetWidth());
1159   EXPECT_FLOAT_EQ(0.4f, cmd->GetHeight());
1160 
1161   EXPECT_FLOAT_EQ(1.0f, cmd->GetR());
1162   EXPECT_FLOAT_EQ(2.0f, cmd->GetG());
1163   EXPECT_FLOAT_EQ(3.0f, cmd->GetB());
1164 }
1165 
TEST_F(CommandParserTest,ProbeErrors)1166 TEST_F(CommandParserTest, ProbeErrors) {
1167   struct {
1168     const char* str;
1169     const char* err;
1170   } probes[] = {
1171       {"probe rgba ab 30 0.2 0.3 0.4 0.5", "Invalid conversion to double"},
1172       {"relative probe rgba ab 30 0.2 0.3 0.4 0.5",
1173        "Invalid conversion to double"},
1174       {"probe rect rgba ab 30 2 3 0.2 0.3 0.4 0.5",
1175        "Invalid conversion to double"},
1176       {"relative probe rect rgba ab 30 2 3 0.2 0.3 0.4 0.5",
1177        "Invalid conversion to double"},
1178 
1179       {"probe rgba 30 ab 0.2 0.3 0.4 0.5", "Invalid conversion to double"},
1180       {"relative probe rgba 30 ab 0.2 0.3 0.4 0.5",
1181        "Invalid conversion to double"},
1182       {"probe rect rgba 30 ab 2 3 0.2 0.3 0.4 0.5",
1183        "Invalid conversion to double"},
1184       {"relative probe rect rgba 30 ab 2 3 0.2 0.3 0.4 0.5",
1185        "Invalid conversion to double"},
1186 
1187       {"probe rect rgba 30 40 ab 3 0.2 0.3 0.4 0.5",
1188        "Invalid conversion to double"},
1189       {"relative probe rect rgba 30 40 ab 3 0.2 0.3 0.4 0.5",
1190        "Invalid conversion to double"},
1191 
1192       {"probe rect rgba 30 40 3 ab 0.2 0.3 0.4 0.5",
1193        "Invalid conversion to double"},
1194       {"relative probe rect rgba 30 40 3 ab 0.2 0.3 0.4 0.5",
1195        "Invalid conversion to double"},
1196 
1197       {"probe rgba 10 30 ab 0.3 0.4 0.5", "Invalid conversion to double"},
1198       {"relative probe rgba 10 30 ab 0.3 0.4 0.5",
1199        "Invalid conversion to double"},
1200       {"probe rect rgba 10 30 2 3 ab 0.3 0.4 0.5",
1201        "Invalid conversion to double"},
1202       {"relative probe rect rgba 10 30 2 3 ab 0.3 0.4 0.5",
1203        "Invalid conversion to double"},
1204 
1205       {"probe rgba 10 30 0.2 ab 0.4 0.5", "Invalid conversion to double"},
1206       {"relative probe rgba 10 30 0.2 ab 0.4 0.5",
1207        "Invalid conversion to double"},
1208       {"probe rect rgba 10 30 2 3 0.2 ab 0.4 0.5",
1209        "Invalid conversion to double"},
1210       {"relative probe rect rgba 10 30 2 3 0.2 ab 0.4 0.5",
1211        "Invalid conversion to double"},
1212 
1213       {"probe rgba 10 30 0.2 0.3 ab 0.5", "Invalid conversion to double"},
1214       {"relative probe rgba 10 30 0.2 0.3 ab 0.5",
1215        "Invalid conversion to double"},
1216       {"probe rect rgba 10 30 2 3 0.2 0.3 ab 0.5",
1217        "Invalid conversion to double"},
1218       {"relative probe rect rgba 10 30 2 3 0.2 0.3 ab 0.5",
1219        "Invalid conversion to double"},
1220 
1221       {"probe rgba 10 30 0.2 0.3 0.4 ab", "Invalid conversion to double"},
1222       {"relative probe rgba 10 30 0.2 0.3 0.4 ab",
1223        "Invalid conversion to double"},
1224       {"probe rect rgba 10 30 2 3 0.2 0.3 0.4 ab",
1225        "Invalid conversion to double"},
1226       {"relative probe rect rgba 10 30 2 3 0.2 0.3 0.4 ab",
1227        "Invalid conversion to double"},
1228 
1229       {"probe all rgb ab 2 3", "Invalid conversion to double"},
1230       {"probe all rgb 2 ab 4", "Invalid conversion to double"},
1231       {"probe all rgb 2 3 ab", "Invalid conversion to double"},
1232 
1233       {"probe all rgba ab 2 3 4", "Invalid conversion to double"},
1234       {"probe all rgba 2 ab 4 5", "Invalid conversion to double"},
1235       {"probe all rgba 2 3 ab 5", "Invalid conversion to double"},
1236       {"probe all rgba 2 3 4 ab", "Invalid conversion to double"},
1237 
1238       {"probe rgb 10 30 0.2 0.3 0.4 extra",
1239        "Extra parameter to probe command: extra"},
1240       {"probe rgba 10 30 0.2 0.3 0.4 0.4 extra",
1241        "Extra parameter to probe command: extra"},
1242       {"relative probe rgb 10 30 0.2 0.3 0.4 extra",
1243        "Extra parameter to probe command: extra"},
1244       {"relative probe rgba 10 30 0.2 0.3 0.4 0.4 extra",
1245        "Extra parameter to probe command: extra"},
1246       {"probe rect rgb 10 30 40 50 0.2 0.3 0.4 extra",
1247        "Extra parameter to probe command: extra"},
1248       {"probe rect rgba 10 30 40 50 0.2 0.3 0.4 0.4 extra",
1249        "Extra parameter to probe command: extra"},
1250       {"relative probe rect rgb 10 30 40 50 0.2 0.3 0.4 extra",
1251        "Extra parameter to probe command: extra"},
1252       {"relative probe rect rgba 10 30 40 50 0.2 0.3 0.4 0.4 extra",
1253        "Extra parameter to probe command: extra"},
1254       {"probe all rgb 2 3 4 extra", "Extra parameter to probe command: extra"},
1255       {"probe all rgba 2 3 4 5 extra",
1256        "Extra parameter to probe command: extra"},
1257 
1258       {"relative probe rect rgb 0.5 0.6 0.3 0.4 1 2 3)",
1259        "Missing open bracket for probe command"},
1260       {"relative probe rect rgb (0.5 0.6 0.3 0.4 1 2 3",
1261        "Missing close bracket for probe command"},
1262       {"relative probe rect rgb 0.5 0.6 0.3 0.4) 1 2 3",
1263        "Missing open bracket for probe command"},
1264       {"relative probe rect rgb 0.5 0.6 0.3 0.4 (1, 2, 3",
1265        "Missing close bracket for probe command"},
1266       {"relative probe rect rgb (0.5, 0.6, 0.3, 0.4, 1, 2, 3)",
1267        "Missing close bracket for probe command"},
1268   };
1269 
1270   for (const auto& probe : probes) {
1271     Pipeline pipeline(PipelineType::kGraphics);
1272     auto color_buf = pipeline.GenerateDefaultColorAttachmentBuffer();
1273     pipeline.AddColorAttachment(color_buf.get(), 0, 0);
1274 
1275     Script script;
1276     CommandParser cp(&script, &pipeline, 1, probe.str);
1277     Result r = cp.Parse();
1278     EXPECT_FALSE(r.IsSuccess()) << probe.str;
1279     EXPECT_EQ(std::string("1: ") + probe.err, r.Error()) << probe.str;
1280   }
1281 }
1282 
TEST_F(CommandParserTest,RelativeWithoutProbe)1283 TEST_F(CommandParserTest, RelativeWithoutProbe) {
1284   std::string data = "relative unknown";
1285 
1286   Pipeline pipeline(PipelineType::kGraphics);
1287   Script script;
1288   CommandParser cp(&script, &pipeline, 1, data);
1289   Result r = cp.Parse();
1290   ASSERT_FALSE(r.IsSuccess());
1291   EXPECT_EQ("1: relative must be used with probe: unknown", r.Error());
1292 }
1293 
TEST_F(CommandParserTest,ProbeWithInvalidRGBA)1294 TEST_F(CommandParserTest, ProbeWithInvalidRGBA) {
1295   std::string data = "probe 1";
1296 
1297   Pipeline pipeline(PipelineType::kGraphics);
1298   auto color_buf = pipeline.GenerateDefaultColorAttachmentBuffer();
1299   pipeline.AddColorAttachment(color_buf.get(), 0, 0);
1300 
1301   Script script;
1302   CommandParser cp(&script, &pipeline, 1, data);
1303   Result r = cp.Parse();
1304   ASSERT_FALSE(r.IsSuccess());
1305   EXPECT_EQ("1: Invalid token in probe command: 1", r.Error());
1306 }
1307 
TEST_F(CommandParserTest,ProbeWithRectAndInvalidRGB)1308 TEST_F(CommandParserTest, ProbeWithRectAndInvalidRGB) {
1309   std::string data = "probe rect 1";
1310 
1311   Pipeline pipeline(PipelineType::kGraphics);
1312   auto color_buf = pipeline.GenerateDefaultColorAttachmentBuffer();
1313   pipeline.AddColorAttachment(color_buf.get(), 0, 0);
1314 
1315   Script script;
1316   CommandParser cp(&script, &pipeline, 1, data);
1317   Result r = cp.Parse();
1318   ASSERT_FALSE(r.IsSuccess());
1319   EXPECT_EQ("1: Invalid token in probe command: 1", r.Error());
1320 }
1321 
TEST_F(CommandParserTest,ProbeWithRectMissingFormat)1322 TEST_F(CommandParserTest, ProbeWithRectMissingFormat) {
1323   std::string data = "probe rect unknown";
1324 
1325   Pipeline pipeline(PipelineType::kGraphics);
1326   auto color_buf = pipeline.GenerateDefaultColorAttachmentBuffer();
1327   pipeline.AddColorAttachment(color_buf.get(), 0, 0);
1328 
1329   Script script;
1330   CommandParser cp(&script, &pipeline, 1, data);
1331   Result r = cp.Parse();
1332   ASSERT_FALSE(r.IsSuccess());
1333   EXPECT_EQ("1: Invalid format specified to probe command: unknown", r.Error());
1334 }
1335 
TEST_F(CommandParserTest,ProbeAllMissingFormat)1336 TEST_F(CommandParserTest, ProbeAllMissingFormat) {
1337   std::string data = "probe all unknown";
1338 
1339   Pipeline pipeline(PipelineType::kGraphics);
1340   auto color_buf = pipeline.GenerateDefaultColorAttachmentBuffer();
1341   pipeline.AddColorAttachment(color_buf.get(), 0, 0);
1342 
1343   Script script;
1344   CommandParser cp(&script, &pipeline, 1, data);
1345   Result r = cp.Parse();
1346   ASSERT_FALSE(r.IsSuccess());
1347   EXPECT_EQ("1: Invalid format specified to probe command: unknown", r.Error());
1348 }
1349 
TEST_F(CommandParserTest,ProbeAlWithInvalidRGB)1350 TEST_F(CommandParserTest, ProbeAlWithInvalidRGB) {
1351   std::string data = "probe all unknown";
1352 
1353   Pipeline pipeline(PipelineType::kGraphics);
1354   auto color_buf = pipeline.GenerateDefaultColorAttachmentBuffer();
1355   pipeline.AddColorAttachment(color_buf.get(), 0, 0);
1356 
1357   Script script;
1358   CommandParser cp(&script, &pipeline, 1, data);
1359   Result r = cp.Parse();
1360   ASSERT_FALSE(r.IsSuccess());
1361   EXPECT_EQ("1: Invalid format specified to probe command: unknown", r.Error());
1362 }
1363 
1364 struct TopologyTestData {
1365   const char* name;
1366   Topology value;
1367 };
1368 using CommandDataPipelineTopologyParser =
1369     testing::TestWithParam<TopologyTestData>;
1370 
TEST_P(CommandDataPipelineTopologyParser,Topology)1371 TEST_P(CommandDataPipelineTopologyParser, Topology) {
1372   const auto& test_data = GetParam();
1373 
1374   std::string data = "topology " + std::string(test_data.name);
1375 
1376   Pipeline pipeline(PipelineType::kGraphics);
1377   Script script;
1378   CommandParser cp(&script, &pipeline, 1, data);
1379   Result r = cp.Parse();
1380   ASSERT_TRUE(r.IsSuccess()) << r.Error();
1381   EXPECT_EQ(test_data.value, cp.PipelineDataForTesting()->GetTopology());
1382 }
1383 
1384 INSTANTIATE_TEST_SUITE_P(
1385     TopologyTests,
1386     CommandDataPipelineTopologyParser,
1387     testing::Values(
1388         TopologyTestData{"VK_PRIMITIVE_TOPOLOGY_PATCH_LIST",
1389                          Topology::kPatchList},
1390         TopologyTestData{"VK_PRIMITIVE_TOPOLOGY_POINT_LIST",
1391                          Topology::kPointList},
1392         TopologyTestData{"VK_PRIMITIVE_TOPOLOGY_LINE_LIST",
1393                          Topology::kLineList},
1394         TopologyTestData{"VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY",
1395                          Topology::kLineListWithAdjacency},
1396         TopologyTestData{"VK_PRIMITIVE_TOPOLOGY_LINE_STRIP",
1397                          Topology::kLineStrip},
1398         TopologyTestData{"VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY",
1399                          Topology::kLineStripWithAdjacency},
1400         TopologyTestData{"VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN",
1401                          Topology::kTriangleFan},
1402         TopologyTestData{"VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST",
1403                          Topology::kTriangleList},
1404         TopologyTestData{"VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY",
1405                          Topology::kTriangleListWithAdjacency},
1406         TopologyTestData{"VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP",
1407                          Topology::kTriangleStrip},
1408         TopologyTestData{
1409             "VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY",
1410             Topology::
1411                 kTriangleStripWithAdjacency}));  // NOLINT(whitespace/parens)
1412 
1413 struct PipelineDataInvalidTest {
1414   const char* name;
1415   const char* arg;
1416 };
1417 using CommandDataPipelineDataInvalidParser =
1418     testing::TestWithParam<PipelineDataInvalidTest>;
1419 
TEST_P(CommandDataPipelineDataInvalidParser,InvalidPipelineParamValue)1420 TEST_P(CommandDataPipelineDataInvalidParser, InvalidPipelineParamValue) {
1421   const auto& test_data = GetParam();
1422 
1423   std::string data = std::string(test_data.name) + " 123";
1424 
1425   Pipeline pipeline(PipelineType::kGraphics);
1426   Script script;
1427   CommandParser cp(&script, &pipeline, 1, data);
1428   Result r = cp.Parse();
1429   ASSERT_FALSE(r.IsSuccess());
1430   EXPECT_EQ(
1431       std::string("1: Invalid value for ") + test_data.name + " command: 123",
1432       r.Error());
1433 }
1434 
TEST_P(CommandDataPipelineDataInvalidParser,MissingTopologyValue)1435 TEST_P(CommandDataPipelineDataInvalidParser, MissingTopologyValue) {
1436   const auto& test_data = GetParam();
1437 
1438   std::string data = test_data.name;
1439 
1440   Pipeline pipeline(PipelineType::kGraphics);
1441   Script script;
1442   CommandParser cp(&script, &pipeline, 1, data);
1443   Result r = cp.Parse();
1444   ASSERT_FALSE(r.IsSuccess());
1445   EXPECT_EQ(std::string("1: Missing value for ") + test_data.name + " command",
1446             r.Error());
1447 }
1448 
TEST_P(CommandDataPipelineDataInvalidParser,UnknownPipelineParamValue)1449 TEST_P(CommandDataPipelineDataInvalidParser, UnknownPipelineParamValue) {
1450   const auto& test_data = GetParam();
1451 
1452   std::string data = std::string(test_data.name) + " UNKNOWN";
1453 
1454   Pipeline pipeline(PipelineType::kGraphics);
1455   Script script;
1456   CommandParser cp(&script, &pipeline, 1, data);
1457   Result r = cp.Parse();
1458   ASSERT_FALSE(r.IsSuccess());
1459   EXPECT_EQ(std::string("1: Unknown value for ") + test_data.name +
1460                 " command: UNKNOWN",
1461             r.Error());
1462 }
1463 
TEST_P(CommandDataPipelineDataInvalidParser,ExtraPipelineParamValue)1464 TEST_P(CommandDataPipelineDataInvalidParser, ExtraPipelineParamValue) {
1465   const auto& test_data = GetParam();
1466 
1467   // CullMode consumes all parameters, so skip this test.
1468   if (std::string(test_data.name) == "cullMode")
1469     return;
1470 
1471   std::string data =
1472       std::string(test_data.name) + " " + test_data.arg + " EXTRA";
1473 
1474   Pipeline pipeline(PipelineType::kGraphics);
1475   Script script;
1476   CommandParser cp(&script, &pipeline, 1, data);
1477   Result r = cp.Parse();
1478   ASSERT_FALSE(r.IsSuccess());
1479   EXPECT_EQ(std::string("1: Extra parameter for ") + test_data.name +
1480                 " command: EXTRA",
1481             r.Error());
1482 }
1483 
1484 INSTANTIATE_TEST_SUITE_P(
1485     PipelineDataInvalidTests,
1486     CommandDataPipelineDataInvalidParser,
1487     testing::Values(
1488         PipelineDataInvalidTest{"topology", "VK_PRIMITIVE_TOPOLOGY_POINT_LIST"},
1489         PipelineDataInvalidTest{"polygonMode", "VK_POLYGON_MODE_POINT"},
1490         PipelineDataInvalidTest{"cullMode", "VK_CULL_MODE_BACK_BIT"},
1491         PipelineDataInvalidTest{"frontFace", "VK_FRONT_FACE_COUNTER_CLOCKWISE"},
1492         PipelineDataInvalidTest{
1493             "logicOp", "VK_LOGIC_OP_NO_OP"}));  // NOLINT(whitespace/parens)
1494 
TEST_F(CommandParserTest,BooleanTrue)1495 TEST_F(CommandParserTest, BooleanTrue) {
1496   struct {
1497     const char* name;
1498   } data[] = {{"TRUE"}, {"true"}, {"TRuE"}};
1499 
1500   for (const auto& d : data) {
1501     Pipeline pipeline(PipelineType::kGraphics);
1502     Script script;
1503     CommandParser cp(&script, &pipeline, 1, "unused");
1504 
1505     bool value = false;
1506     Result r = cp.ParseBooleanForTesting(d.name, &value);
1507     EXPECT_TRUE(r.IsSuccess()) << r.Error();
1508     EXPECT_TRUE(value);
1509   }
1510 }
1511 
TEST_F(CommandParserTest,BooleanFalse)1512 TEST_F(CommandParserTest, BooleanFalse) {
1513   struct {
1514     const char* name;
1515   } data[] = {{"FALSE"}, {"false"}, {"FAlsE"}};
1516 
1517   for (const auto& d : data) {
1518     Pipeline pipeline(PipelineType::kGraphics);
1519     Script script;
1520     CommandParser cp(&script, &pipeline, 1, "unused");
1521 
1522     bool value = true;
1523     Result r = cp.ParseBooleanForTesting(d.name, &value);
1524     EXPECT_TRUE(r.IsSuccess()) << d.name << " " << r.Error();
1525     EXPECT_FALSE(value);
1526   }
1527 }
1528 
TEST_F(CommandParserTest,BooleanInvalid)1529 TEST_F(CommandParserTest, BooleanInvalid) {
1530   struct {
1531     const char* name;
1532   } data[] = {{""}, {"Invalid"}};
1533 
1534   for (const auto& d : data) {
1535     Pipeline pipeline(PipelineType::kGraphics);
1536     Script script;
1537     CommandParser cp(&script, &pipeline, 1, "unused");
1538 
1539     bool value = true;
1540     Result r = cp.ParseBooleanForTesting(d.name, &value);
1541     ASSERT_FALSE(r.IsSuccess()) << d.name;
1542     EXPECT_EQ(
1543         std::string("Invalid value passed as a boolean string: ") + d.name,
1544         r.Error());
1545   }
1546 }
1547 
TEST_F(CommandParserTest,PrimitiveRestartEnable)1548 TEST_F(CommandParserTest, PrimitiveRestartEnable) {
1549   std::string data = "primitiveRestartEnable true";
1550 
1551   Pipeline pipeline(PipelineType::kGraphics);
1552   Script script;
1553   CommandParser cp(&script, &pipeline, 1, data);
1554   Result r = cp.Parse();
1555   ASSERT_TRUE(r.IsSuccess()) << r.Error();
1556   EXPECT_TRUE(cp.PipelineDataForTesting()->GetEnablePrimitiveRestart());
1557 }
1558 
TEST_F(CommandParserTest,PrimitiveRestartDisable)1559 TEST_F(CommandParserTest, PrimitiveRestartDisable) {
1560   std::string data = "primitiveRestartEnable false";
1561 
1562   Pipeline pipeline(PipelineType::kGraphics);
1563   Script script;
1564   CommandParser cp(&script, &pipeline, 1, data);
1565   Result r = cp.Parse();
1566   ASSERT_TRUE(r.IsSuccess()) << r.Error();
1567   EXPECT_FALSE(cp.PipelineDataForTesting()->GetEnablePrimitiveRestart());
1568 }
1569 
TEST_F(CommandParserTest,DepthClampEnable)1570 TEST_F(CommandParserTest, DepthClampEnable) {
1571   std::string data = "depthClampEnable true";
1572 
1573   Pipeline pipeline(PipelineType::kGraphics);
1574   Script script;
1575   CommandParser cp(&script, &pipeline, 1, data);
1576   Result r = cp.Parse();
1577   ASSERT_TRUE(r.IsSuccess()) << r.Error();
1578   EXPECT_TRUE(cp.PipelineDataForTesting()->GetEnableDepthClamp());
1579 }
1580 
TEST_F(CommandParserTest,DepthClampDisable)1581 TEST_F(CommandParserTest, DepthClampDisable) {
1582   std::string data = "depthClampEnable false";
1583 
1584   Pipeline pipeline(PipelineType::kGraphics);
1585   Script script;
1586   CommandParser cp(&script, &pipeline, 1, data);
1587   Result r = cp.Parse();
1588   ASSERT_TRUE(r.IsSuccess()) << r.Error();
1589   EXPECT_FALSE(cp.PipelineDataForTesting()->GetEnableDepthClamp());
1590 }
1591 
TEST_F(CommandParserTest,RasterizerDiscardEnable)1592 TEST_F(CommandParserTest, RasterizerDiscardEnable) {
1593   std::string data = "rasterizerDiscardEnable true";
1594 
1595   Pipeline pipeline(PipelineType::kGraphics);
1596   Script script;
1597   CommandParser cp(&script, &pipeline, 1, data);
1598   Result r = cp.Parse();
1599   ASSERT_TRUE(r.IsSuccess()) << r.Error();
1600   EXPECT_TRUE(cp.PipelineDataForTesting()->GetEnableRasterizerDiscard());
1601 }
1602 
TEST_F(CommandParserTest,RasterizerDiscardDisable)1603 TEST_F(CommandParserTest, RasterizerDiscardDisable) {
1604   std::string data = "rasterizerDiscardEnable false";
1605 
1606   Pipeline pipeline(PipelineType::kGraphics);
1607   Script script;
1608   CommandParser cp(&script, &pipeline, 1, data);
1609   Result r = cp.Parse();
1610   ASSERT_TRUE(r.IsSuccess()) << r.Error();
1611   EXPECT_FALSE(cp.PipelineDataForTesting()->GetEnableRasterizerDiscard());
1612 }
1613 
TEST_F(CommandParserTest,DepthBiasEnable)1614 TEST_F(CommandParserTest, DepthBiasEnable) {
1615   std::string data = "depthBiasEnable true";
1616 
1617   Pipeline pipeline(PipelineType::kGraphics);
1618   Script script;
1619   CommandParser cp(&script, &pipeline, 1, data);
1620   Result r = cp.Parse();
1621   ASSERT_TRUE(r.IsSuccess()) << r.Error();
1622   EXPECT_TRUE(cp.PipelineDataForTesting()->GetEnableDepthBias());
1623 }
1624 
TEST_F(CommandParserTest,DepthBiasDisable)1625 TEST_F(CommandParserTest, DepthBiasDisable) {
1626   std::string data = "depthBiasEnable false";
1627 
1628   Pipeline pipeline(PipelineType::kGraphics);
1629   Script script;
1630   CommandParser cp(&script, &pipeline, 1, data);
1631   Result r = cp.Parse();
1632   ASSERT_TRUE(r.IsSuccess()) << r.Error();
1633   EXPECT_FALSE(cp.PipelineDataForTesting()->GetEnableDepthBias());
1634 }
1635 
TEST_F(CommandParserTest,LogicOpEnable)1636 TEST_F(CommandParserTest, LogicOpEnable) {
1637   std::string data = "logicOpEnable true";
1638 
1639   Pipeline pipeline(PipelineType::kGraphics);
1640   Script script;
1641   CommandParser cp(&script, &pipeline, 1, data);
1642   Result r = cp.Parse();
1643   ASSERT_TRUE(r.IsSuccess()) << r.Error();
1644   EXPECT_TRUE(cp.PipelineDataForTesting()->GetEnableLogicOp());
1645 }
1646 
TEST_F(CommandParserTest,LogicOpDisable)1647 TEST_F(CommandParserTest, LogicOpDisable) {
1648   std::string data = "logicOpEnable false";
1649 
1650   Pipeline pipeline(PipelineType::kGraphics);
1651   Script script;
1652   CommandParser cp(&script, &pipeline, 1, data);
1653   Result r = cp.Parse();
1654   ASSERT_TRUE(r.IsSuccess()) << r.Error();
1655   EXPECT_FALSE(cp.PipelineDataForTesting()->GetEnableLogicOp());
1656 }
1657 
TEST_F(CommandParserTest,BlendEnable)1658 TEST_F(CommandParserTest, BlendEnable) {
1659   std::string data = "blendEnable true";
1660 
1661   Pipeline pipeline(PipelineType::kGraphics);
1662   Script script;
1663   CommandParser cp(&script, &pipeline, 1, data);
1664   Result r = cp.Parse();
1665   ASSERT_TRUE(r.IsSuccess()) << r.Error();
1666   EXPECT_TRUE(cp.PipelineDataForTesting()->GetEnableBlend());
1667 }
1668 
TEST_F(CommandParserTest,BlendDisable)1669 TEST_F(CommandParserTest, BlendDisable) {
1670   std::string data = "blendEnable false";
1671 
1672   Pipeline pipeline(PipelineType::kGraphics);
1673   Script script;
1674   CommandParser cp(&script, &pipeline, 1, data);
1675   Result r = cp.Parse();
1676   ASSERT_TRUE(r.IsSuccess()) << r.Error();
1677   EXPECT_FALSE(cp.PipelineDataForTesting()->GetEnableBlend());
1678 }
1679 
TEST_F(CommandParserTest,DepthTestEnable)1680 TEST_F(CommandParserTest, DepthTestEnable) {
1681   std::string data = "depthTestEnable true";
1682 
1683   Pipeline pipeline(PipelineType::kGraphics);
1684   Script script;
1685   CommandParser cp(&script, &pipeline, 1, data);
1686   Result r = cp.Parse();
1687   ASSERT_TRUE(r.IsSuccess()) << r.Error();
1688   EXPECT_TRUE(cp.PipelineDataForTesting()->GetEnableDepthTest());
1689 }
1690 
TEST_F(CommandParserTest,DepthTestDisable)1691 TEST_F(CommandParserTest, DepthTestDisable) {
1692   std::string data = "depthTestEnable false";
1693 
1694   Pipeline pipeline(PipelineType::kGraphics);
1695   Script script;
1696   CommandParser cp(&script, &pipeline, 1, data);
1697   Result r = cp.Parse();
1698   ASSERT_TRUE(r.IsSuccess()) << r.Error();
1699   EXPECT_FALSE(cp.PipelineDataForTesting()->GetEnableDepthTest());
1700 }
1701 
TEST_F(CommandParserTest,DepthWriteEnable)1702 TEST_F(CommandParserTest, DepthWriteEnable) {
1703   std::string data = "depthWriteEnable true";
1704 
1705   Pipeline pipeline(PipelineType::kGraphics);
1706   Script script;
1707   CommandParser cp(&script, &pipeline, 1, data);
1708   Result r = cp.Parse();
1709   ASSERT_TRUE(r.IsSuccess()) << r.Error();
1710   EXPECT_TRUE(cp.PipelineDataForTesting()->GetEnableDepthWrite());
1711 }
1712 
TEST_F(CommandParserTest,DepthWriteDisable)1713 TEST_F(CommandParserTest, DepthWriteDisable) {
1714   std::string data = "depthWriteEnable false";
1715 
1716   Pipeline pipeline(PipelineType::kGraphics);
1717   Script script;
1718   CommandParser cp(&script, &pipeline, 1, data);
1719   Result r = cp.Parse();
1720   ASSERT_TRUE(r.IsSuccess()) << r.Error();
1721   EXPECT_FALSE(cp.PipelineDataForTesting()->GetEnableDepthWrite());
1722 }
1723 
TEST_F(CommandParserTest,DepthBoundsTestEnable)1724 TEST_F(CommandParserTest, DepthBoundsTestEnable) {
1725   std::string data = "depthBoundsTestEnable true";
1726 
1727   Pipeline pipeline(PipelineType::kGraphics);
1728   Script script;
1729   CommandParser cp(&script, &pipeline, 1, data);
1730   Result r = cp.Parse();
1731   ASSERT_TRUE(r.IsSuccess()) << r.Error();
1732   EXPECT_TRUE(cp.PipelineDataForTesting()->GetEnableDepthBoundsTest());
1733 }
1734 
TEST_F(CommandParserTest,DepthBoundsTestDisable)1735 TEST_F(CommandParserTest, DepthBoundsTestDisable) {
1736   std::string data = "depthBoundsTestEnable false";
1737 
1738   Pipeline pipeline(PipelineType::kGraphics);
1739   Script script;
1740   CommandParser cp(&script, &pipeline, 1, data);
1741   Result r = cp.Parse();
1742   ASSERT_TRUE(r.IsSuccess()) << r.Error();
1743   EXPECT_FALSE(cp.PipelineDataForTesting()->GetEnableDepthBoundsTest());
1744 }
1745 
TEST_F(CommandParserTest,StencilTestEnable)1746 TEST_F(CommandParserTest, StencilTestEnable) {
1747   std::string data = "stencilTestEnable true";
1748 
1749   Pipeline pipeline(PipelineType::kGraphics);
1750   Script script;
1751   CommandParser cp(&script, &pipeline, 1, data);
1752   Result r = cp.Parse();
1753   ASSERT_TRUE(r.IsSuccess()) << r.Error();
1754   EXPECT_TRUE(cp.PipelineDataForTesting()->GetEnableStencilTest());
1755 }
1756 
TEST_F(CommandParserTest,StencilTestDisable)1757 TEST_F(CommandParserTest, StencilTestDisable) {
1758   std::string data = "stencilTestEnable false";
1759 
1760   Pipeline pipeline(PipelineType::kGraphics);
1761   Script script;
1762   CommandParser cp(&script, &pipeline, 1, data);
1763   Result r = cp.Parse();
1764   ASSERT_TRUE(r.IsSuccess()) << r.Error();
1765   EXPECT_FALSE(cp.PipelineDataForTesting()->GetEnableStencilTest());
1766 }
1767 
1768 struct BooleanTest {
1769   const char* name;
1770 };
1771 using CommandParserBooleanTests = testing::TestWithParam<BooleanTest>;
1772 
TEST_P(CommandParserBooleanTests,MissingParam)1773 TEST_P(CommandParserBooleanTests, MissingParam) {
1774   const auto& test_data = GetParam();
1775 
1776   std::string data = std::string(test_data.name);
1777 
1778   Pipeline pipeline(PipelineType::kGraphics);
1779   Script script;
1780   CommandParser cp(&script, &pipeline, 1, data);
1781   Result r = cp.Parse();
1782   ASSERT_FALSE(r.IsSuccess());
1783   EXPECT_EQ(std::string("1: Missing value for ") + test_data.name + " command",
1784             r.Error());
1785 }
1786 
TEST_P(CommandParserBooleanTests,IllegalParam)1787 TEST_P(CommandParserBooleanTests, IllegalParam) {
1788   const auto& test_data = GetParam();
1789 
1790   std::string data = std::string(test_data.name) + " 123";
1791 
1792   Pipeline pipeline(PipelineType::kGraphics);
1793   Script script;
1794   CommandParser cp(&script, &pipeline, 1, data);
1795   Result r = cp.Parse();
1796   ASSERT_FALSE(r.IsSuccess());
1797   EXPECT_EQ(
1798       std::string("1: Invalid value for ") + test_data.name + " command: 123",
1799       r.Error());
1800 }
1801 
TEST_P(CommandParserBooleanTests,ExtraParam)1802 TEST_P(CommandParserBooleanTests, ExtraParam) {
1803   const auto& test_data = GetParam();
1804 
1805   std::string data = std::string(test_data.name) + " true EXTRA";
1806 
1807   Pipeline pipeline(PipelineType::kGraphics);
1808   Script script;
1809   CommandParser cp(&script, &pipeline, 1, data);
1810   Result r = cp.Parse();
1811   ASSERT_FALSE(r.IsSuccess());
1812   EXPECT_EQ(std::string("1: Extra parameter for ") + test_data.name +
1813                 " command: EXTRA",
1814             r.Error());
1815 }
1816 
1817 INSTANTIATE_TEST_SUITE_P(
1818     BooleanTests,
1819     CommandParserBooleanTests,
1820     testing::Values(BooleanTest{"primitiveRestartEnable"},
1821                     BooleanTest{"depthClampEnable"},
1822                     BooleanTest{"rasterizerDiscardEnable"},
1823                     BooleanTest{"depthBiasEnable"},
1824                     BooleanTest{"logicOpEnable"},
1825                     BooleanTest{"blendEnable"},
1826                     BooleanTest{"depthTestEnable"},
1827                     BooleanTest{"depthWriteEnable"},
1828                     BooleanTest{"depthBoundsTestEnable"},
1829                     BooleanTest{
1830                         "stencilTestEnable"}));  // NOLINT(whitespace/parens)
1831 
1832 struct PolygonModeTestData {
1833   const char* name;
1834   PolygonMode value;
1835 };
1836 using CommandDataPipelinePolygonModeParser =
1837     testing::TestWithParam<PolygonModeTestData>;
1838 
TEST_P(CommandDataPipelinePolygonModeParser,PolygonMode)1839 TEST_P(CommandDataPipelinePolygonModeParser, PolygonMode) {
1840   const auto& test_data = GetParam();
1841 
1842   std::string data = "polygonMode " + std::string(test_data.name);
1843 
1844   Pipeline pipeline(PipelineType::kGraphics);
1845   Script script;
1846   CommandParser cp(&script, &pipeline, 1, data);
1847   Result r = cp.Parse();
1848   ASSERT_TRUE(r.IsSuccess()) << r.Error();
1849   EXPECT_EQ(test_data.value, cp.PipelineDataForTesting()->GetPolygonMode());
1850 }
1851 
1852 INSTANTIATE_TEST_SUITE_P(
1853     PolygonModeTests,
1854     CommandDataPipelinePolygonModeParser,
1855     testing::Values(
1856         PolygonModeTestData{"VK_POLYGON_MODE_FILL", PolygonMode::kFill},
1857         PolygonModeTestData{"VK_POLYGON_MODE_LINE", PolygonMode::kLine},
1858         PolygonModeTestData{
1859             "VK_POLYGON_MODE_POINT",
1860             PolygonMode::kPoint}));  // NOLINT(whitespace/parens)
1861 
1862 struct CullModeTestData {
1863   const char* name;
1864   CullMode value;
1865 };
1866 using CommandDataPipelineCullModeParser =
1867     testing::TestWithParam<CullModeTestData>;
1868 
TEST_P(CommandDataPipelineCullModeParser,CullMode)1869 TEST_P(CommandDataPipelineCullModeParser, CullMode) {
1870   const auto& test_data = GetParam();
1871 
1872   std::string data = "cullMode " + std::string(test_data.name);
1873 
1874   Pipeline pipeline(PipelineType::kGraphics);
1875   Script script;
1876   CommandParser cp(&script, &pipeline, 1, data);
1877   Result r = cp.Parse();
1878   ASSERT_TRUE(r.IsSuccess()) << r.Error();
1879   EXPECT_EQ(test_data.value, cp.PipelineDataForTesting()->GetCullMode());
1880 }
1881 
1882 INSTANTIATE_TEST_SUITE_P(
1883     CullModeTests,
1884     CommandDataPipelineCullModeParser,
1885     testing::Values(
1886         CullModeTestData{"VK_CULL_MODE_NONE", CullMode::kNone},
1887         CullModeTestData{"VK_CULL_MODE_FRONT_BIT", CullMode::kFront},
1888         CullModeTestData{"VK_CULL_MODE_BACK_BIT", CullMode::kBack},
1889         CullModeTestData{"VK_CULL_MODE_BACK_BIT | VK_CULL_MODE_FRONT_BIT",
1890                          CullMode::kFrontAndBack},
1891         CullModeTestData{"VK_CULL_MODE_FRONT_BIT | VK_CULL_MODE_BACK_BIT",
1892                          CullMode::kFrontAndBack},
1893         CullModeTestData{
1894             "VK_CULL_MODE_FRONT_AND_BACK",
1895             CullMode::kFrontAndBack}));  // NOLINT(whitespace/parens)
1896 
1897 struct FrontFaceTestData {
1898   const char* name;
1899   FrontFace value;
1900 };
1901 using CommandDataPipelineFrontFaceParser =
1902     testing::TestWithParam<FrontFaceTestData>;
1903 
TEST_P(CommandDataPipelineFrontFaceParser,FrontFace)1904 TEST_P(CommandDataPipelineFrontFaceParser, FrontFace) {
1905   const auto& test_data = GetParam();
1906 
1907   std::string data = "frontFace " + std::string(test_data.name);
1908 
1909   Pipeline pipeline(PipelineType::kGraphics);
1910   Script script;
1911   CommandParser cp(&script, &pipeline, 1, data);
1912   Result r = cp.Parse();
1913   ASSERT_TRUE(r.IsSuccess()) << r.Error();
1914   EXPECT_EQ(test_data.value, cp.PipelineDataForTesting()->GetFrontFace());
1915 }
1916 
1917 INSTANTIATE_TEST_SUITE_P(
1918     FrontFaceTests,
1919     CommandDataPipelineFrontFaceParser,
1920     testing::Values(FrontFaceTestData{"VK_FRONT_FACE_COUNTER_CLOCKWISE",
1921                                       FrontFace::kCounterClockwise},
1922                     FrontFaceTestData{
1923                         "VK_FRONT_FACE_CLOCKWISE",
1924                         FrontFace::kClockwise}));  // NOLINT(whitespace/parens)
1925 
1926 struct LogicOpTestData {
1927   const char* name;
1928   LogicOp value;
1929 };
1930 using CommandDataPipelineLogicOpParser =
1931     testing::TestWithParam<LogicOpTestData>;
1932 
TEST_P(CommandDataPipelineLogicOpParser,LogicOp)1933 TEST_P(CommandDataPipelineLogicOpParser, LogicOp) {
1934   const auto& test_data = GetParam();
1935 
1936   std::string data = "logicOp " + std::string(test_data.name);
1937 
1938   Pipeline pipeline(PipelineType::kGraphics);
1939   Script script;
1940   CommandParser cp(&script, &pipeline, 1, data);
1941   Result r = cp.Parse();
1942   ASSERT_TRUE(r.IsSuccess()) << r.Error();
1943   EXPECT_EQ(test_data.value, cp.PipelineDataForTesting()->GetLogicOp());
1944 }
1945 
1946 INSTANTIATE_TEST_SUITE_P(
1947     LogicOpTests,
1948     CommandDataPipelineLogicOpParser,
1949     testing::Values(
1950         LogicOpTestData{"VK_LOGIC_OP_CLEAR", LogicOp::kClear},
1951         LogicOpTestData{"VK_LOGIC_OP_AND", LogicOp::kAnd},
1952         LogicOpTestData{"VK_LOGIC_OP_AND_REVERSE", LogicOp::kAndReverse},
1953         LogicOpTestData{"VK_LOGIC_OP_COPY", LogicOp::kCopy},
1954         LogicOpTestData{"VK_LOGIC_OP_AND_INVERTED", LogicOp::kAndInverted},
1955         LogicOpTestData{"VK_LOGIC_OP_NO_OP", LogicOp::kNoOp},
1956         LogicOpTestData{"VK_LOGIC_OP_XOR", LogicOp::kXor},
1957         LogicOpTestData{"VK_LOGIC_OP_OR", LogicOp::kOr},
1958         LogicOpTestData{"VK_LOGIC_OP_NOR", LogicOp::kNor},
1959         LogicOpTestData{"VK_LOGIC_OP_EQUIVALENT", LogicOp::kEquivalent},
1960         LogicOpTestData{"VK_LOGIC_OP_INVERT", LogicOp::kInvert},
1961         LogicOpTestData{"VK_LOGIC_OP_OR_REVERSE", LogicOp::kOrReverse},
1962         LogicOpTestData{"VK_LOGIC_OP_COPY_INVERTED", LogicOp::kCopyInverted},
1963         LogicOpTestData{"VK_LOGIC_OP_OR_INVERTED", LogicOp::kOrInverted},
1964         LogicOpTestData{"VK_LOGIC_OP_NAND", LogicOp::kNand},
1965         LogicOpTestData{"VK_LOGIC_OP_SET",
1966                         LogicOp::kSet}));  // NOLINT(whitespace/parens)
1967 
TEST_F(CommandParserTest,DepthBiasConstantFactor)1968 TEST_F(CommandParserTest, DepthBiasConstantFactor) {
1969   std::string data = "depthBiasConstantFactor 3.4";
1970 
1971   Pipeline pipeline(PipelineType::kGraphics);
1972   Script script;
1973   CommandParser cp(&script, &pipeline, 1, data);
1974   Result r = cp.Parse();
1975   ASSERT_TRUE(r.IsSuccess()) << r.Error();
1976   EXPECT_FLOAT_EQ(3.4f,
1977                   cp.PipelineDataForTesting()->GetDepthBiasConstantFactor());
1978 }
1979 
TEST_F(CommandParserTest,DepthBiasClamp)1980 TEST_F(CommandParserTest, DepthBiasClamp) {
1981   std::string data = "depthBiasClamp 3.4";
1982 
1983   Pipeline pipeline(PipelineType::kGraphics);
1984   Script script;
1985   CommandParser cp(&script, &pipeline, 1, data);
1986   Result r = cp.Parse();
1987   ASSERT_TRUE(r.IsSuccess()) << r.Error();
1988   EXPECT_FLOAT_EQ(3.4f, cp.PipelineDataForTesting()->GetDepthBiasClamp());
1989 }
1990 
TEST_F(CommandParserTest,DepthBiasSlopeFactor)1991 TEST_F(CommandParserTest, DepthBiasSlopeFactor) {
1992   std::string data = "depthBiasSlopeFactor 3.4";
1993 
1994   Pipeline pipeline(PipelineType::kGraphics);
1995   Script script;
1996   CommandParser cp(&script, &pipeline, 1, data);
1997   Result r = cp.Parse();
1998   ASSERT_TRUE(r.IsSuccess()) << r.Error();
1999   EXPECT_FLOAT_EQ(3.4f, cp.PipelineDataForTesting()->GetDepthBiasSlopeFactor());
2000 }
2001 
TEST_F(CommandParserTest,LineWidth)2002 TEST_F(CommandParserTest, LineWidth) {
2003   std::string data = "lineWidth 3.4";
2004 
2005   Pipeline pipeline(PipelineType::kGraphics);
2006   Script script;
2007   CommandParser cp(&script, &pipeline, 1, data);
2008   Result r = cp.Parse();
2009   ASSERT_TRUE(r.IsSuccess()) << r.Error();
2010   EXPECT_FLOAT_EQ(3.4f, cp.PipelineDataForTesting()->GetLineWidth());
2011 }
2012 
TEST_F(CommandParserTest,MinDepthBounds)2013 TEST_F(CommandParserTest, MinDepthBounds) {
2014   std::string data = "minDepthBounds 3.4";
2015 
2016   Pipeline pipeline(PipelineType::kGraphics);
2017   Script script;
2018   CommandParser cp(&script, &pipeline, 1, data);
2019   Result r = cp.Parse();
2020   ASSERT_TRUE(r.IsSuccess()) << r.Error();
2021   EXPECT_FLOAT_EQ(3.4f, cp.PipelineDataForTesting()->GetMinDepthBounds());
2022 }
2023 
TEST_F(CommandParserTest,MaxDepthBounds)2024 TEST_F(CommandParserTest, MaxDepthBounds) {
2025   std::string data = "maxDepthBounds 3.4";
2026 
2027   Pipeline pipeline(PipelineType::kGraphics);
2028   Script script;
2029   CommandParser cp(&script, &pipeline, 1, data);
2030   Result r = cp.Parse();
2031   ASSERT_TRUE(r.IsSuccess()) << r.Error();
2032   EXPECT_FLOAT_EQ(3.4f, cp.PipelineDataForTesting()->GetMaxDepthBounds());
2033 }
2034 
2035 struct FloatTest {
2036   const char* name;
2037 };
2038 using CommandParserFloatTests = testing::TestWithParam<FloatTest>;
2039 
TEST_P(CommandParserFloatTests,MissingParam)2040 TEST_P(CommandParserFloatTests, MissingParam) {
2041   const auto& test_data = GetParam();
2042 
2043   std::string data = std::string(test_data.name);
2044 
2045   Pipeline pipeline(PipelineType::kGraphics);
2046   Script script;
2047   CommandParser cp(&script, &pipeline, 1, data);
2048   Result r = cp.Parse();
2049   ASSERT_FALSE(r.IsSuccess());
2050   EXPECT_EQ(std::string("1: Missing value for ") + test_data.name + " command",
2051             r.Error());
2052 }
2053 
TEST_P(CommandParserFloatTests,IllegalParam)2054 TEST_P(CommandParserFloatTests, IllegalParam) {
2055   const auto& test_data = GetParam();
2056 
2057   std::string data = std::string(test_data.name) + " INVALID";
2058 
2059   Pipeline pipeline(PipelineType::kGraphics);
2060   Script script;
2061   CommandParser cp(&script, &pipeline, 1, data);
2062   Result r = cp.Parse();
2063   ASSERT_FALSE(r.IsSuccess());
2064   EXPECT_EQ("1: Invalid conversion to double", r.Error());
2065 }
2066 
TEST_P(CommandParserFloatTests,ExtraParam)2067 TEST_P(CommandParserFloatTests, ExtraParam) {
2068   const auto& test_data = GetParam();
2069 
2070   std::string data = std::string(test_data.name) + " 3.2 EXTRA";
2071 
2072   Pipeline pipeline(PipelineType::kGraphics);
2073   Script script;
2074   CommandParser cp(&script, &pipeline, 1, data);
2075   Result r = cp.Parse();
2076   ASSERT_FALSE(r.IsSuccess());
2077   EXPECT_EQ(std::string("1: Extra parameter for ") + test_data.name +
2078                 " command: EXTRA",
2079             r.Error());
2080 }
2081 
2082 INSTANTIATE_TEST_SUITE_P(
2083     FloatTests,
2084     CommandParserFloatTests,
2085     testing::Values(FloatTest{"depthBiasConstantFactor"},
2086                     FloatTest{"lineWidth"},
2087                     FloatTest{"depthBiasClamp"},
2088                     FloatTest{"depthBiasSlopeFactor"},
2089                     FloatTest{"minDepthBounds"},
2090                     FloatTest{"maxDepthBounds"}));  // NOLINT(whitespace/parens)
2091 
TEST_F(CommandParserTest,SrcColorBlendFactor)2092 TEST_F(CommandParserTest, SrcColorBlendFactor) {
2093   std::string data = "srcColorBlendFactor VK_BLEND_FACTOR_DST_COLOR";
2094 
2095   Pipeline pipeline(PipelineType::kGraphics);
2096   Script script;
2097   CommandParser cp(&script, &pipeline, 1, data);
2098   Result r = cp.Parse();
2099   ASSERT_TRUE(r.IsSuccess()) << r.Error();
2100   EXPECT_EQ(BlendFactor::kDstColor,
2101             cp.PipelineDataForTesting()->GetSrcColorBlendFactor());
2102 }
2103 
TEST_F(CommandParserTest,DstColorBlendFactor)2104 TEST_F(CommandParserTest, DstColorBlendFactor) {
2105   std::string data = "dstColorBlendFactor VK_BLEND_FACTOR_DST_COLOR";
2106 
2107   Pipeline pipeline(PipelineType::kGraphics);
2108   Script script;
2109   CommandParser cp(&script, &pipeline, 1, data);
2110   Result r = cp.Parse();
2111   ASSERT_TRUE(r.IsSuccess()) << r.Error();
2112   EXPECT_EQ(BlendFactor::kDstColor,
2113             cp.PipelineDataForTesting()->GetDstColorBlendFactor());
2114 }
2115 
TEST_F(CommandParserTest,SrcAlphaBlendFactor)2116 TEST_F(CommandParserTest, SrcAlphaBlendFactor) {
2117   std::string data = "srcAlphaBlendFactor VK_BLEND_FACTOR_DST_COLOR";
2118 
2119   Pipeline pipeline(PipelineType::kGraphics);
2120   Script script;
2121   CommandParser cp(&script, &pipeline, 1, data);
2122   Result r = cp.Parse();
2123   ASSERT_TRUE(r.IsSuccess()) << r.Error();
2124   EXPECT_EQ(BlendFactor::kDstColor,
2125             cp.PipelineDataForTesting()->GetSrcAlphaBlendFactor());
2126 }
2127 
TEST_F(CommandParserTest,DstAlphaBlendFactor)2128 TEST_F(CommandParserTest, DstAlphaBlendFactor) {
2129   std::string data = "dstAlphaBlendFactor VK_BLEND_FACTOR_DST_COLOR";
2130 
2131   Pipeline pipeline(PipelineType::kGraphics);
2132   Script script;
2133   CommandParser cp(&script, &pipeline, 1, data);
2134   Result r = cp.Parse();
2135   ASSERT_TRUE(r.IsSuccess()) << r.Error();
2136   EXPECT_EQ(BlendFactor::kDstColor,
2137             cp.PipelineDataForTesting()->GetDstAlphaBlendFactor());
2138 }
2139 
2140 struct BlendFactorData {
2141   const char* name;
2142   BlendFactor type;
2143 };
2144 using CommandParserBlendFactorParsing = testing::TestWithParam<BlendFactorData>;
2145 
TEST_P(CommandParserBlendFactorParsing,Parse)2146 TEST_P(CommandParserBlendFactorParsing, Parse) {
2147   const auto& test_data = GetParam();
2148 
2149   Pipeline pipeline(PipelineType::kGraphics);
2150   Script script;
2151   CommandParser cp(&script, &pipeline, 1, "unused");
2152   BlendFactor factor = BlendFactor::kZero;
2153   Result r = cp.ParseBlendFactorNameForTesting(test_data.name, &factor);
2154   ASSERT_TRUE(r.IsSuccess()) << r.Error();
2155   EXPECT_EQ(test_data.type, factor);
2156 }
2157 
2158 INSTANTIATE_TEST_SUITE_P(
2159     BlendFactorParsingTests,
2160     CommandParserBlendFactorParsing,
2161     testing::Values(
2162         BlendFactorData{"VK_BLEND_FACTOR_ZERO", BlendFactor::kZero},
2163         BlendFactorData{"VK_BLEND_FACTOR_ONE", BlendFactor::kOne},
2164         BlendFactorData{"VK_BLEND_FACTOR_SRC_COLOR", BlendFactor::kSrcColor},
2165         BlendFactorData{"VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR",
2166                         BlendFactor::kOneMinusSrcColor},
2167         BlendFactorData{"VK_BLEND_FACTOR_DST_COLOR", BlendFactor::kDstColor},
2168         BlendFactorData{"VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR",
2169                         BlendFactor::kOneMinusDstColor},
2170         BlendFactorData{"VK_BLEND_FACTOR_SRC_ALPHA", BlendFactor::kSrcAlpha},
2171         BlendFactorData{"VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA",
2172                         BlendFactor::kOneMinusSrcAlpha},
2173         BlendFactorData{"VK_BLEND_FACTOR_DST_ALPHA", BlendFactor::kDstAlpha},
2174         BlendFactorData{"VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA",
2175                         BlendFactor::kOneMinusDstAlpha},
2176         BlendFactorData{"VK_BLEND_FACTOR_CONSTANT_COLOR",
2177                         BlendFactor::kConstantColor},
2178         BlendFactorData{"VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR",
2179                         BlendFactor::kOneMinusConstantColor},
2180         BlendFactorData{"VK_BLEND_FACTOR_CONSTANT_ALPHA",
2181                         BlendFactor::kConstantAlpha},
2182         BlendFactorData{"VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA",
2183                         BlendFactor::kOneMinusConstantAlpha},
2184         BlendFactorData{"VK_BLEND_FACTOR_SRC_ALPHA_SATURATE",
2185                         BlendFactor::kSrcAlphaSaturate},
2186         BlendFactorData{"VK_BLEND_FACTOR_SRC1_COLOR", BlendFactor::kSrc1Color},
2187         BlendFactorData{"VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR",
2188                         BlendFactor::kOneMinusSrc1Color},
2189         BlendFactorData{"VK_BLEND_FACTOR_SRC1_ALPHA", BlendFactor::kSrc1Alpha},
2190         BlendFactorData{
2191             "VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA",
2192             BlendFactor::kOneMinusSrc1Alpha}));  // NOLINT(whitespace/parens)
2193 
TEST_F(CommandParserTest,BlendFactorParsingInvalid)2194 TEST_F(CommandParserTest, BlendFactorParsingInvalid) {
2195   Pipeline pipeline(PipelineType::kGraphics);
2196   Script script;
2197   CommandParser cp(&script, &pipeline, 1, "unused");
2198   BlendFactor factor = BlendFactor::kZero;
2199   Result r = cp.ParseBlendFactorNameForTesting("INVALID", &factor);
2200   ASSERT_FALSE(r.IsSuccess());
2201   EXPECT_EQ("Unknown BlendFactor provided: INVALID", r.Error());
2202 }
2203 
2204 struct BlendFactorTest {
2205   const char* name;
2206 };
2207 using CommandParserBlendFactorTests = testing::TestWithParam<BlendFactorTest>;
2208 
TEST_P(CommandParserBlendFactorTests,MissingParam)2209 TEST_P(CommandParserBlendFactorTests, MissingParam) {
2210   const auto& test_data = GetParam();
2211 
2212   std::string data = std::string(test_data.name);
2213 
2214   Pipeline pipeline(PipelineType::kGraphics);
2215   Script script;
2216   CommandParser cp(&script, &pipeline, 1, data);
2217   Result r = cp.Parse();
2218   ASSERT_FALSE(r.IsSuccess());
2219   EXPECT_EQ(
2220       std::string("1: Missing parameter for ") + test_data.name + " command",
2221       r.Error());
2222 }
2223 
TEST_P(CommandParserBlendFactorTests,IllegalParam)2224 TEST_P(CommandParserBlendFactorTests, IllegalParam) {
2225   const auto& test_data = GetParam();
2226 
2227   std::string data = std::string(test_data.name) + " 1.23";
2228 
2229   Pipeline pipeline(PipelineType::kGraphics);
2230   Script script;
2231   CommandParser cp(&script, &pipeline, 1, data);
2232   Result r = cp.Parse();
2233   ASSERT_FALSE(r.IsSuccess());
2234   EXPECT_EQ(std::string("1: Invalid parameter for ") + test_data.name +
2235                 " command: 1.23",
2236             r.Error());
2237 }
2238 
TEST_P(CommandParserBlendFactorTests,ExtraParam)2239 TEST_P(CommandParserBlendFactorTests, ExtraParam) {
2240   const auto& test_data = GetParam();
2241 
2242   std::string data = std::string(test_data.name) + " VK_BLEND_FACTOR_ONE EXTRA";
2243 
2244   Pipeline pipeline(PipelineType::kGraphics);
2245   Script script;
2246   CommandParser cp(&script, &pipeline, 1, data);
2247   Result r = cp.Parse();
2248   ASSERT_FALSE(r.IsSuccess());
2249   EXPECT_EQ(std::string("1: Extra parameter for ") + test_data.name +
2250                 " command: EXTRA",
2251             r.Error());
2252 }
2253 
2254 INSTANTIATE_TEST_SUITE_P(
2255     BlendFactorTests,
2256     CommandParserBlendFactorTests,
2257     testing::Values(BlendFactorTest{"srcColorBlendFactor"},
2258                     BlendFactorTest{"dstColorBlendFactor"},
2259                     BlendFactorTest{"srcAlphaBlendFactor"},
2260                     BlendFactorTest{
2261                         "dstAlphaBlendFactor"}));  // NOLINT(whitespace/parens)
2262 
TEST_F(CommandParserTest,ColorBlendOp)2263 TEST_F(CommandParserTest, ColorBlendOp) {
2264   std::string data = "colorBlendOp VK_BLEND_OP_XOR_EXT";
2265 
2266   Pipeline pipeline(PipelineType::kGraphics);
2267   Script script;
2268   CommandParser cp(&script, &pipeline, 1, data);
2269   Result r = cp.Parse();
2270   ASSERT_TRUE(r.IsSuccess()) << r.Error();
2271   EXPECT_EQ(BlendOp::kXor, cp.PipelineDataForTesting()->GetColorBlendOp());
2272 }
2273 
TEST_F(CommandParserTest,AlphaBlendOp)2274 TEST_F(CommandParserTest, AlphaBlendOp) {
2275   std::string data = "alphaBlendOp VK_BLEND_OP_XOR_EXT";
2276 
2277   Pipeline pipeline(PipelineType::kGraphics);
2278   Script script;
2279   CommandParser cp(&script, &pipeline, 1, data);
2280   Result r = cp.Parse();
2281   ASSERT_TRUE(r.IsSuccess()) << r.Error();
2282   EXPECT_EQ(BlendOp::kXor, cp.PipelineDataForTesting()->GetAlphaBlendOp());
2283 }
2284 
2285 struct BlendOpData {
2286   const char* name;
2287   BlendOp type;
2288 };
2289 using CommandParserBlendOpParsing = testing::TestWithParam<BlendOpData>;
2290 
TEST_P(CommandParserBlendOpParsing,Parse)2291 TEST_P(CommandParserBlendOpParsing, Parse) {
2292   const auto& test_data = GetParam();
2293 
2294   Pipeline pipeline(PipelineType::kGraphics);
2295   Script script;
2296   CommandParser cp(&script, &pipeline, 1, "unused");
2297   BlendOp op = BlendOp::kAdd;
2298   Result r = cp.ParseBlendOpNameForTesting(test_data.name, &op);
2299   ASSERT_TRUE(r.IsSuccess()) << r.Error();
2300   EXPECT_EQ(test_data.type, op);
2301 }
2302 
2303 INSTANTIATE_TEST_SUITE_P(
2304     BlendOpParsingTests1,
2305     CommandParserBlendOpParsing,
2306     testing::Values(
2307         BlendOpData{"VK_BLEND_OP_ADD", BlendOp::kAdd},
2308         BlendOpData{"VK_BLEND_OP_SUBTRACT", BlendOp::kSubtract},
2309         BlendOpData{"VK_BLEND_OP_REVERSE_SUBTRACT", BlendOp::kReverseSubtract},
2310         BlendOpData{"VK_BLEND_OP_MIN", BlendOp::kMin},
2311         BlendOpData{"VK_BLEND_OP_MAX", BlendOp::kMax},
2312         BlendOpData{"VK_BLEND_OP_ZERO_EXT", BlendOp::kZero},
2313         BlendOpData{"VK_BLEND_OP_SRC_EXT", BlendOp::kSrc},
2314         BlendOpData{"VK_BLEND_OP_DST_EXT", BlendOp::kDst},
2315         BlendOpData{"VK_BLEND_OP_SRC_OVER_EXT", BlendOp::kSrcOver},
2316         BlendOpData{"VK_BLEND_OP_DST_OVER_EXT", BlendOp::kDstOver},
2317         BlendOpData{"VK_BLEND_OP_SRC_IN_EXT", BlendOp::kSrcIn},
2318         BlendOpData{"VK_BLEND_OP_DST_IN_EXT", BlendOp::kDstIn},
2319         BlendOpData{"VK_BLEND_OP_SRC_OUT_EXT", BlendOp::kSrcOut},
2320         BlendOpData{"VK_BLEND_OP_DST_OUT_EXT", BlendOp::kDstOut},
2321         BlendOpData{"VK_BLEND_OP_SRC_ATOP_EXT", BlendOp::kSrcAtop},
2322         BlendOpData{"VK_BLEND_OP_DST_ATOP_EXT", BlendOp::kDstAtop},
2323         BlendOpData{"VK_BLEND_OP_XOR_EXT", BlendOp::kXor},
2324         BlendOpData{"VK_BLEND_OP_MULTIPLY_EXT", BlendOp::kMultiply},
2325         BlendOpData{"VK_BLEND_OP_SCREEN_EXT", BlendOp::kScreen},
2326         BlendOpData{"VK_BLEND_OP_OVERLAY_EXT", BlendOp::kOverlay},
2327         BlendOpData{"VK_BLEND_OP_DARKEN_EXT", BlendOp::kDarken},
2328         BlendOpData{"VK_BLEND_OP_LIGHTEN_EXT", BlendOp::kLighten},
2329         BlendOpData{"VK_BLEND_OP_COLORDODGE_EXT", BlendOp::kColorDodge},
2330         BlendOpData{"VK_BLEND_OP_COLORBURN_EXT", BlendOp::kColorBurn},
2331         BlendOpData{"VK_BLEND_OP_HARDLIGHT_EXT", BlendOp::kHardLight},
2332         BlendOpData{"VK_BLEND_OP_SOFTLIGHT_EXT", BlendOp::kSoftLight},
2333         BlendOpData{"VK_BLEND_OP_DIFFERENCE_EXT", BlendOp::kDifference},
2334         BlendOpData{"VK_BLEND_OP_EXCLUSION_EXT", BlendOp::kExclusion},
2335         BlendOpData{"VK_BLEND_OP_INVERT_EXT",
2336                     BlendOp::kInvert}));  // NOLINT(whitespace/parens)
2337 
2338 INSTANTIATE_TEST_SUITE_P(
2339     BlendOpParsingTests2,
2340     CommandParserBlendOpParsing,
2341     testing::Values(
2342         BlendOpData{"VK_BLEND_OP_INVERT_RGB_EXT", BlendOp::kInvertRGB},
2343         BlendOpData{"VK_BLEND_OP_LINEARDODGE_EXT", BlendOp::kLinearDodge},
2344         BlendOpData{"VK_BLEND_OP_LINEARBURN_EXT", BlendOp::kLinearBurn},
2345         BlendOpData{"VK_BLEND_OP_VIVIDLIGHT_EXT", BlendOp::kVividLight},
2346         BlendOpData{"VK_BLEND_OP_LINEARLIGHT_EXT", BlendOp::kLinearLight},
2347         BlendOpData{"VK_BLEND_OP_PINLIGHT_EXT", BlendOp::kPinLight},
2348         BlendOpData{"VK_BLEND_OP_HARDMIX_EXT", BlendOp::kHardMix},
2349         BlendOpData{"VK_BLEND_OP_HSL_HUE_EXT", BlendOp::kHslHue},
2350         BlendOpData{"VK_BLEND_OP_HSL_SATURATION_EXT", BlendOp::kHslSaturation},
2351         BlendOpData{"VK_BLEND_OP_HSL_COLOR_EXT", BlendOp::kHslColor},
2352         BlendOpData{"VK_BLEND_OP_HSL_LUMINOSITY_EXT", BlendOp::kHslLuminosity},
2353         BlendOpData{"VK_BLEND_OP_PLUS_EXT", BlendOp::kPlus},
2354         BlendOpData{"VK_BLEND_OP_PLUS_CLAMPED_EXT", BlendOp::kPlusClamped},
2355         BlendOpData{"VK_BLEND_OP_PLUS_CLAMPED_ALPHA_EXT",
2356                     BlendOp::kPlusClampedAlpha},
2357         BlendOpData{"VK_BLEND_OP_PLUS_DARKER_EXT", BlendOp::kPlusDarker},
2358         BlendOpData{"VK_BLEND_OP_MINUS_EXT", BlendOp::kMinus},
2359         BlendOpData{"VK_BLEND_OP_MINUS_CLAMPED_EXT", BlendOp::kMinusClamped},
2360         BlendOpData{"VK_BLEND_OP_CONTRAST_EXT", BlendOp::kContrast},
2361         BlendOpData{"VK_BLEND_OP_INVERT_OVG_EXT", BlendOp::kInvertOvg},
2362         BlendOpData{"VK_BLEND_OP_RED_EXT", BlendOp::kRed},
2363         BlendOpData{"VK_BLEND_OP_GREEN_EXT", BlendOp::kGreen},
2364         BlendOpData{"VK_BLEND_OP_BLUE_EXT",
2365                     BlendOp::kBlue}));  // NOLINT(whitespace/parens)
2366 
TEST_F(CommandParserTest,BlendOpParsingInvalid)2367 TEST_F(CommandParserTest, BlendOpParsingInvalid) {
2368   Pipeline pipeline(PipelineType::kGraphics);
2369   Script script;
2370   CommandParser cp(&script, &pipeline, 1, "unused");
2371   BlendOp op = BlendOp::kAdd;
2372   Result r = cp.ParseBlendOpNameForTesting("INVALID", &op);
2373   ASSERT_FALSE(r.IsSuccess());
2374   EXPECT_EQ("Unknown BlendOp provided: INVALID", r.Error());
2375 }
2376 
2377 struct BlendOpTest {
2378   const char* name;
2379 };
2380 using CommandParserBlendOpTests = testing::TestWithParam<BlendOpTest>;
2381 
TEST_P(CommandParserBlendOpTests,MissingParam)2382 TEST_P(CommandParserBlendOpTests, MissingParam) {
2383   const auto& test_data = GetParam();
2384 
2385   std::string data = std::string(test_data.name);
2386 
2387   Pipeline pipeline(PipelineType::kGraphics);
2388   Script script;
2389   CommandParser cp(&script, &pipeline, 1, data);
2390   Result r = cp.Parse();
2391   ASSERT_FALSE(r.IsSuccess());
2392   EXPECT_EQ(
2393       std::string("1: Missing parameter for ") + test_data.name + " command",
2394       r.Error());
2395 }
2396 
TEST_P(CommandParserBlendOpTests,IllegalParam)2397 TEST_P(CommandParserBlendOpTests, IllegalParam) {
2398   const auto& test_data = GetParam();
2399 
2400   std::string data = std::string(test_data.name) + " 1.23";
2401 
2402   Pipeline pipeline(PipelineType::kGraphics);
2403   Script script;
2404   CommandParser cp(&script, &pipeline, 1, data);
2405   Result r = cp.Parse();
2406   ASSERT_FALSE(r.IsSuccess());
2407   EXPECT_EQ(std::string("1: Invalid parameter for ") + test_data.name +
2408                 " command: 1.23",
2409             r.Error());
2410 }
2411 
TEST_P(CommandParserBlendOpTests,ExtraParam)2412 TEST_P(CommandParserBlendOpTests, ExtraParam) {
2413   const auto& test_data = GetParam();
2414 
2415   std::string data = std::string(test_data.name) + " VK_BLEND_OP_MAX EXTRA";
2416 
2417   Pipeline pipeline(PipelineType::kGraphics);
2418   Script script;
2419   CommandParser cp(&script, &pipeline, 1, data);
2420   Result r = cp.Parse();
2421   ASSERT_FALSE(r.IsSuccess());
2422   EXPECT_EQ(std::string("1: Extra parameter for ") + test_data.name +
2423                 " command: EXTRA",
2424             r.Error());
2425 }
2426 
2427 INSTANTIATE_TEST_SUITE_P(
2428     BlendOpTests,
2429     CommandParserBlendOpTests,
2430     testing::Values(BlendOpTest{"colorBlendOp"},
2431                     BlendOpTest{"alphaBlendOp"}));  // NOLINT(whitespace/parens)
2432 
TEST_F(CommandParserTest,DepthCompareOp)2433 TEST_F(CommandParserTest, DepthCompareOp) {
2434   std::string data = "depthCompareOp VK_COMPARE_OP_EQUAL";
2435 
2436   Pipeline pipeline(PipelineType::kGraphics);
2437   Script script;
2438   CommandParser cp(&script, &pipeline, 1, data);
2439   Result r = cp.Parse();
2440   ASSERT_TRUE(r.IsSuccess()) << r.Error();
2441   EXPECT_EQ(CompareOp::kEqual,
2442             cp.PipelineDataForTesting()->GetDepthCompareOp());
2443 }
2444 
TEST_F(CommandParserTest,FrontCompareOp)2445 TEST_F(CommandParserTest, FrontCompareOp) {
2446   std::string data = "front.compareOp VK_COMPARE_OP_EQUAL";
2447 
2448   Pipeline pipeline(PipelineType::kGraphics);
2449   Script script;
2450   CommandParser cp(&script, &pipeline, 1, data);
2451   Result r = cp.Parse();
2452   ASSERT_TRUE(r.IsSuccess()) << r.Error();
2453   EXPECT_EQ(CompareOp::kEqual,
2454             cp.PipelineDataForTesting()->GetFrontCompareOp());
2455 }
2456 
TEST_F(CommandParserTest,BackCompareOp)2457 TEST_F(CommandParserTest, BackCompareOp) {
2458   std::string data = "back.compareOp VK_COMPARE_OP_EQUAL";
2459 
2460   Pipeline pipeline(PipelineType::kGraphics);
2461   Script script;
2462   CommandParser cp(&script, &pipeline, 1, data);
2463   Result r = cp.Parse();
2464   ASSERT_TRUE(r.IsSuccess()) << r.Error();
2465   EXPECT_EQ(CompareOp::kEqual, cp.PipelineDataForTesting()->GetBackCompareOp());
2466 }
2467 
2468 struct CompareOpData {
2469   const char* name;
2470   CompareOp type;
2471 };
2472 using CommandParserCompareOpParsing = testing::TestWithParam<CompareOpData>;
2473 
TEST_P(CommandParserCompareOpParsing,Parse)2474 TEST_P(CommandParserCompareOpParsing, Parse) {
2475   const auto& test_data = GetParam();
2476 
2477   Pipeline pipeline(PipelineType::kGraphics);
2478   Script script;
2479   CommandParser cp(&script, &pipeline, 1, "unused");
2480   CompareOp op = CompareOp::kNever;
2481   Result r = cp.ParseCompareOpNameForTesting(test_data.name, &op);
2482   ASSERT_TRUE(r.IsSuccess()) << r.Error();
2483   EXPECT_EQ(test_data.type, op);
2484 }
2485 
2486 INSTANTIATE_TEST_SUITE_P(
2487     CompareOpParsingTests,
2488     CommandParserCompareOpParsing,
2489     testing::Values(
2490         CompareOpData{"VK_COMPARE_OP_NEVER", CompareOp::kNever},
2491         CompareOpData{"VK_COMPARE_OP_LESS", CompareOp::kLess},
2492         CompareOpData{"VK_COMPARE_OP_EQUAL", CompareOp::kEqual},
2493         CompareOpData{"VK_COMPARE_OP_LESS_OR_EQUAL", CompareOp::kLessOrEqual},
2494         CompareOpData{"VK_COMPARE_OP_GREATER", CompareOp::kGreater},
2495         CompareOpData{"VK_COMPARE_OP_NOT_EQUAL", CompareOp::kNotEqual},
2496         CompareOpData{"VK_COMPARE_OP_GREATER_OR_EQUAL",
2497                       CompareOp::kGreaterOrEqual},
2498         CompareOpData{"VK_COMPARE_OP_ALWAYS",
2499                       CompareOp::kAlways}));  // NOLINT(whitespace/parens)
2500 
TEST_F(CommandParserTest,CompareOpParsingInvalid)2501 TEST_F(CommandParserTest, CompareOpParsingInvalid) {
2502   Pipeline pipeline(PipelineType::kGraphics);
2503   Script script;
2504   CommandParser cp(&script, &pipeline, 1, "unused");
2505   CompareOp op = CompareOp::kNever;
2506   Result r = cp.ParseCompareOpNameForTesting("INVALID", &op);
2507   ASSERT_FALSE(r.IsSuccess());
2508   EXPECT_EQ("Unknown CompareOp provided: INVALID", r.Error());
2509 }
2510 
2511 struct CompareOpTest {
2512   const char* name;
2513 };
2514 using CommandParserCompareOpTests = testing::TestWithParam<CompareOpTest>;
2515 
TEST_P(CommandParserCompareOpTests,MissingParam)2516 TEST_P(CommandParserCompareOpTests, MissingParam) {
2517   const auto& test_data = GetParam();
2518 
2519   std::string data = std::string(test_data.name);
2520 
2521   Pipeline pipeline(PipelineType::kGraphics);
2522   Script script;
2523   CommandParser cp(&script, &pipeline, 1, data);
2524   Result r = cp.Parse();
2525   ASSERT_FALSE(r.IsSuccess());
2526   EXPECT_EQ(
2527       std::string("1: Missing parameter for ") + test_data.name + " command",
2528       r.Error());
2529 }
2530 
TEST_P(CommandParserCompareOpTests,IllegalParam)2531 TEST_P(CommandParserCompareOpTests, IllegalParam) {
2532   const auto& test_data = GetParam();
2533 
2534   std::string data = std::string(test_data.name) + " 1.23";
2535 
2536   Pipeline pipeline(PipelineType::kGraphics);
2537   Script script;
2538   CommandParser cp(&script, &pipeline, 1, data);
2539   Result r = cp.Parse();
2540   ASSERT_FALSE(r.IsSuccess());
2541   EXPECT_EQ(std::string("1: Invalid parameter for ") + test_data.name +
2542                 " command: 1.23",
2543             r.Error());
2544 }
2545 
TEST_P(CommandParserCompareOpTests,ExtraParam)2546 TEST_P(CommandParserCompareOpTests, ExtraParam) {
2547   const auto& test_data = GetParam();
2548 
2549   std::string data =
2550       std::string(test_data.name) + " VK_COMPARE_OP_ALWAYS EXTRA";
2551 
2552   Pipeline pipeline(PipelineType::kGraphics);
2553   Script script;
2554   CommandParser cp(&script, &pipeline, 1, data);
2555   Result r = cp.Parse();
2556   ASSERT_FALSE(r.IsSuccess());
2557   EXPECT_EQ(std::string("1: Extra parameter for ") + test_data.name +
2558                 " command: EXTRA",
2559             r.Error());
2560 }
2561 
2562 INSTANTIATE_TEST_SUITE_P(
2563     CompareOpTests,
2564     CommandParserCompareOpTests,
2565     testing::Values(CompareOpTest{"depthCompareOp"},
2566                     CompareOpTest{"front.compareOp"},
2567                     CompareOpTest{
2568                         "back.compareOp"}));  // NOLINT(whitespace/parens)
2569 
TEST_F(CommandParserTest,FrontFailOp)2570 TEST_F(CommandParserTest, FrontFailOp) {
2571   std::string data = "front.failOp VK_STENCIL_OP_REPLACE";
2572 
2573   Pipeline pipeline(PipelineType::kGraphics);
2574   Script script;
2575   CommandParser cp(&script, &pipeline, 1, data);
2576   Result r = cp.Parse();
2577   ASSERT_TRUE(r.IsSuccess()) << r.Error();
2578   EXPECT_EQ(StencilOp::kReplace, cp.PipelineDataForTesting()->GetFrontFailOp());
2579 }
2580 
TEST_F(CommandParserTest,FrontPassOp)2581 TEST_F(CommandParserTest, FrontPassOp) {
2582   std::string data = "front.passOp VK_STENCIL_OP_REPLACE";
2583 
2584   Pipeline pipeline(PipelineType::kGraphics);
2585   Script script;
2586   CommandParser cp(&script, &pipeline, 1, data);
2587   Result r = cp.Parse();
2588   ASSERT_TRUE(r.IsSuccess()) << r.Error();
2589   EXPECT_EQ(StencilOp::kReplace, cp.PipelineDataForTesting()->GetFrontPassOp());
2590 }
2591 
TEST_F(CommandParserTest,FrontDepthFailOp)2592 TEST_F(CommandParserTest, FrontDepthFailOp) {
2593   std::string data = "front.depthFailOp VK_STENCIL_OP_REPLACE";
2594 
2595   Pipeline pipeline(PipelineType::kGraphics);
2596   Script script;
2597   CommandParser cp(&script, &pipeline, 1, data);
2598   Result r = cp.Parse();
2599   ASSERT_TRUE(r.IsSuccess()) << r.Error();
2600   EXPECT_EQ(StencilOp::kReplace,
2601             cp.PipelineDataForTesting()->GetFrontDepthFailOp());
2602 }
2603 
TEST_F(CommandParserTest,BackFailOp)2604 TEST_F(CommandParserTest, BackFailOp) {
2605   std::string data = "back.failOp VK_STENCIL_OP_REPLACE";
2606 
2607   Pipeline pipeline(PipelineType::kGraphics);
2608   Script script;
2609   CommandParser cp(&script, &pipeline, 1, data);
2610   Result r = cp.Parse();
2611   ASSERT_TRUE(r.IsSuccess()) << r.Error();
2612   EXPECT_EQ(StencilOp::kReplace, cp.PipelineDataForTesting()->GetBackFailOp());
2613 }
2614 
TEST_F(CommandParserTest,BackPassOp)2615 TEST_F(CommandParserTest, BackPassOp) {
2616   std::string data = "back.passOp VK_STENCIL_OP_REPLACE";
2617 
2618   Pipeline pipeline(PipelineType::kGraphics);
2619   Script script;
2620   CommandParser cp(&script, &pipeline, 1, data);
2621   Result r = cp.Parse();
2622   ASSERT_TRUE(r.IsSuccess()) << r.Error();
2623   EXPECT_EQ(StencilOp::kReplace, cp.PipelineDataForTesting()->GetBackPassOp());
2624 }
2625 
TEST_F(CommandParserTest,BackDepthFailOp)2626 TEST_F(CommandParserTest, BackDepthFailOp) {
2627   std::string data = "back.depthFailOp VK_STENCIL_OP_REPLACE";
2628 
2629   Pipeline pipeline(PipelineType::kGraphics);
2630   Script script;
2631   CommandParser cp(&script, &pipeline, 1, data);
2632   Result r = cp.Parse();
2633   ASSERT_TRUE(r.IsSuccess()) << r.Error();
2634   EXPECT_EQ(StencilOp::kReplace,
2635             cp.PipelineDataForTesting()->GetBackDepthFailOp());
2636 }
2637 
2638 struct StencilOpData {
2639   const char* name;
2640   StencilOp type;
2641 };
2642 using CommandParserStencilOpParsing = testing::TestWithParam<StencilOpData>;
2643 
TEST_P(CommandParserStencilOpParsing,Parse)2644 TEST_P(CommandParserStencilOpParsing, Parse) {
2645   const auto& test_data = GetParam();
2646 
2647   Pipeline pipeline(PipelineType::kGraphics);
2648   Script script;
2649   CommandParser cp(&script, &pipeline, 1, "unused");
2650   StencilOp op = StencilOp::kKeep;
2651   Result r = cp.ParseStencilOpNameForTesting(test_data.name, &op);
2652   ASSERT_TRUE(r.IsSuccess()) << r.Error();
2653   EXPECT_EQ(test_data.type, op);
2654 }
2655 
2656 INSTANTIATE_TEST_SUITE_P(
2657     CompareOpParsingTests,
2658     CommandParserStencilOpParsing,
2659     testing::Values(
2660         StencilOpData{"VK_STENCIL_OP_KEEP", StencilOp::kKeep},
2661         StencilOpData{"VK_STENCIL_OP_ZERO", StencilOp::kZero},
2662         StencilOpData{"VK_STENCIL_OP_REPLACE", StencilOp::kReplace},
2663         StencilOpData{"VK_STENCIL_OP_INCREMENT_AND_CLAMP",
2664                       StencilOp::kIncrementAndClamp},
2665         StencilOpData{"VK_STENCIL_OP_DECREMENT_AND_CLAMP",
2666                       StencilOp::kDecrementAndClamp},
2667         StencilOpData{"VK_STENCIL_OP_INVERT", StencilOp::kInvert},
2668         StencilOpData{"VK_STENCIL_OP_INCREMENT_AND_WRAP",
2669                       StencilOp::kIncrementAndWrap},
2670         StencilOpData{
2671             "VK_STENCIL_OP_DECREMENT_AND_WRAP",
2672             StencilOp::kDecrementAndWrap}));  // NOLINT(whitespace/parens)
2673 
TEST_F(CommandParserTest,StencilOpParsingInvalid)2674 TEST_F(CommandParserTest, StencilOpParsingInvalid) {
2675   Pipeline pipeline(PipelineType::kGraphics);
2676   Script script;
2677   CommandParser cp(&script, &pipeline, 1, "unused");
2678   StencilOp op = StencilOp::kKeep;
2679   Result r = cp.ParseStencilOpNameForTesting("INVALID", &op);
2680   ASSERT_FALSE(r.IsSuccess());
2681   EXPECT_EQ("Unknown StencilOp provided: INVALID", r.Error());
2682 }
2683 
2684 struct StencilOpTest {
2685   const char* name;
2686 };
2687 using CommandParserStencilOpTests = testing::TestWithParam<StencilOpTest>;
2688 
TEST_P(CommandParserStencilOpTests,MissingParam)2689 TEST_P(CommandParserStencilOpTests, MissingParam) {
2690   const auto& test_data = GetParam();
2691 
2692   std::string data = std::string(test_data.name);
2693 
2694   Pipeline pipeline(PipelineType::kGraphics);
2695   Script script;
2696   CommandParser cp(&script, &pipeline, 1, data);
2697   Result r = cp.Parse();
2698   ASSERT_FALSE(r.IsSuccess());
2699   EXPECT_EQ(
2700       std::string("1: Missing parameter for ") + test_data.name + " command",
2701       r.Error());
2702 }
2703 
TEST_P(CommandParserStencilOpTests,IllegalParam)2704 TEST_P(CommandParserStencilOpTests, IllegalParam) {
2705   const auto& test_data = GetParam();
2706 
2707   std::string data = std::string(test_data.name) + " 1.23";
2708 
2709   Pipeline pipeline(PipelineType::kGraphics);
2710   Script script;
2711   CommandParser cp(&script, &pipeline, 1, data);
2712   Result r = cp.Parse();
2713   ASSERT_FALSE(r.IsSuccess());
2714   EXPECT_EQ(std::string("1: Invalid parameter for ") + test_data.name +
2715                 " command: 1.23",
2716             r.Error());
2717 }
2718 
TEST_P(CommandParserStencilOpTests,ExtraParam)2719 TEST_P(CommandParserStencilOpTests, ExtraParam) {
2720   const auto& test_data = GetParam();
2721 
2722   std::string data =
2723       std::string(test_data.name) + " VK_STENCIL_OP_REPLACE EXTRA";
2724 
2725   Pipeline pipeline(PipelineType::kGraphics);
2726   Script script;
2727   CommandParser cp(&script, &pipeline, 1, data);
2728   Result r = cp.Parse();
2729   ASSERT_FALSE(r.IsSuccess());
2730   EXPECT_EQ(std::string("1: Extra parameter for ") + test_data.name +
2731                 " command: EXTRA",
2732             r.Error());
2733 }
2734 
2735 INSTANTIATE_TEST_SUITE_P(
2736     StencilOpTests,
2737     CommandParserStencilOpTests,
2738     testing::Values(StencilOpTest{"front.passOp"},
2739                     StencilOpTest{"front.failOp"},
2740                     StencilOpTest{"front.depthFailOp"},
2741                     StencilOpTest{"back.passOp"},
2742                     StencilOpTest{"back.failOp"},
2743                     StencilOpTest{
2744                         "back.depthFailOp"}));  // NOLINT(whitespace/parens)
2745 
TEST_F(CommandParserTest,FrontCompareMask)2746 TEST_F(CommandParserTest, FrontCompareMask) {
2747   std::string data = "front.compareMask 123";
2748 
2749   Pipeline pipeline(PipelineType::kGraphics);
2750   Script script;
2751   CommandParser cp(&script, &pipeline, 1, data);
2752   Result r = cp.Parse();
2753   ASSERT_FALSE(r.IsSuccess());
2754   EXPECT_EQ("1: front.compareMask not implemented", r.Error());
2755 }
2756 
TEST_F(CommandParserTest,FrontWriteMask)2757 TEST_F(CommandParserTest, FrontWriteMask) {
2758   std::string data = "front.writeMask 123";
2759 
2760   Pipeline pipeline(PipelineType::kGraphics);
2761   Script script;
2762   CommandParser cp(&script, &pipeline, 1, data);
2763   Result r = cp.Parse();
2764   ASSERT_FALSE(r.IsSuccess());
2765   EXPECT_EQ("1: front.writeMask not implemented", r.Error());
2766 }
2767 
TEST_F(CommandParserTest,BackCompareMask)2768 TEST_F(CommandParserTest, BackCompareMask) {
2769   std::string data = "back.compareMask 123";
2770 
2771   Pipeline pipeline(PipelineType::kGraphics);
2772   Script script;
2773   CommandParser cp(&script, &pipeline, 1, data);
2774   Result r = cp.Parse();
2775   ASSERT_FALSE(r.IsSuccess());
2776   EXPECT_EQ("1: back.compareMask not implemented", r.Error());
2777 }
2778 
TEST_F(CommandParserTest,BackWriteMask)2779 TEST_F(CommandParserTest, BackWriteMask) {
2780   std::string data = "back.writeMask 123";
2781 
2782   Pipeline pipeline(PipelineType::kGraphics);
2783   Script script;
2784   CommandParser cp(&script, &pipeline, 1, data);
2785   Result r = cp.Parse();
2786   ASSERT_FALSE(r.IsSuccess());
2787   EXPECT_EQ("1: back.writeMask not implemented", r.Error());
2788 }
2789 
TEST_F(CommandParserTest,FrontReference)2790 TEST_F(CommandParserTest, FrontReference) {
2791   std::string data = "front.reference 10";
2792 
2793   Pipeline pipeline(PipelineType::kGraphics);
2794   Script script;
2795   CommandParser cp(&script, &pipeline, 1, data);
2796   Result r = cp.Parse();
2797   ASSERT_TRUE(r.IsSuccess()) << r.Error();
2798   EXPECT_EQ(10U, cp.PipelineDataForTesting()->GetFrontReference());
2799 }
2800 
TEST_F(CommandParserTest,BackReference)2801 TEST_F(CommandParserTest, BackReference) {
2802   std::string data = "back.reference 10";
2803 
2804   Pipeline pipeline(PipelineType::kGraphics);
2805   Script script;
2806   CommandParser cp(&script, &pipeline, 1, data);
2807   Result r = cp.Parse();
2808   ASSERT_TRUE(r.IsSuccess()) << r.Error();
2809   EXPECT_EQ(10U, cp.PipelineDataForTesting()->GetBackReference());
2810 }
2811 
2812 struct ReferenceData {
2813   const char* name;
2814 };
2815 
2816 using CommandParserReferenceTests = testing::TestWithParam<ReferenceData>;
2817 
TEST_P(CommandParserReferenceTests,FrontReferenceMissingValue)2818 TEST_P(CommandParserReferenceTests, FrontReferenceMissingValue) {
2819   const auto& test_data = GetParam();
2820   std::string data = std::string(test_data.name);
2821 
2822   Pipeline pipeline(PipelineType::kGraphics);
2823   Script script;
2824   CommandParser cp(&script, &pipeline, 1, data);
2825   Result r = cp.Parse();
2826   ASSERT_FALSE(r.IsSuccess());
2827   EXPECT_EQ(
2828       std::string("1: Missing parameter for ") + test_data.name + " command",
2829       r.Error());
2830 }
2831 
TEST_P(CommandParserReferenceTests,FrontReferenceExtraParameters)2832 TEST_P(CommandParserReferenceTests, FrontReferenceExtraParameters) {
2833   const auto& test_data = GetParam();
2834   std::string data = std::string(test_data.name) + " 10 EXTRA";
2835 
2836   Pipeline pipeline(PipelineType::kGraphics);
2837   Script script;
2838   CommandParser cp(&script, &pipeline, 1, data);
2839   Result r = cp.Parse();
2840   ASSERT_FALSE(r.IsSuccess());
2841   EXPECT_EQ(std::string("1: Extra parameter for ") + test_data.name +
2842                 " command: EXTRA",
2843             r.Error());
2844 }
2845 
TEST_P(CommandParserReferenceTests,FrontReferenceInvalidParameters)2846 TEST_P(CommandParserReferenceTests, FrontReferenceInvalidParameters) {
2847   const auto& test_data = GetParam();
2848   std::string data = std::string(test_data.name) + " INVALID";
2849 
2850   Pipeline pipeline(PipelineType::kGraphics);
2851   Script script;
2852   CommandParser cp(&script, &pipeline, 1, data);
2853   Result r = cp.Parse();
2854   ASSERT_FALSE(r.IsSuccess());
2855   EXPECT_EQ(std::string("1: Invalid parameter for ") + test_data.name +
2856                 " command: INVALID",
2857             r.Error());
2858 }
2859 
2860 INSTANTIATE_TEST_SUITE_P(
2861     ReferenceTest,
2862     CommandParserReferenceTests,
2863     testing::Values(ReferenceData{"front.reference"},
2864                     ReferenceData{
2865                         "back.reference"}));  // NOLINT(whitespace/parens)
2866 
2867 struct ColorMaskData {
2868   const char* input;
2869   uint8_t result;
2870 };
2871 using CommandParserColorMaskTests = testing::TestWithParam<ColorMaskData>;
2872 
TEST_P(CommandParserColorMaskTests,ColorWriteMask)2873 TEST_P(CommandParserColorMaskTests, ColorWriteMask) {
2874   const auto& test_data = GetParam();
2875   std::string data = "colorWriteMask " + std::string(test_data.input);
2876 
2877   Pipeline pipeline(PipelineType::kGraphics);
2878   Script script;
2879   CommandParser cp(&script, &pipeline, 1, data);
2880   Result r = cp.Parse();
2881   ASSERT_TRUE(r.IsSuccess()) << r.Error();
2882   EXPECT_EQ(test_data.result, cp.PipelineDataForTesting()->GetColorWriteMask());
2883 }
2884 
2885 INSTANTIATE_TEST_SUITE_P(
2886     ColorMaskTests,
2887     CommandParserColorMaskTests,
2888     testing::Values(
2889         ColorMaskData{"VK_COLOR_COMPONENT_R_BIT", kColorMaskR},
2890         ColorMaskData{"VK_COLOR_COMPONENT_G_BIT", kColorMaskG},
2891         ColorMaskData{"VK_COLOR_COMPONENT_B_BIT", kColorMaskB},
2892         ColorMaskData{"VK_COLOR_COMPONENT_A_BIT", kColorMaskA},
2893         ColorMaskData{"VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | "
2894                       "VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT",
2895                       kColorMaskR | kColorMaskG | kColorMaskB | kColorMaskA},
2896         ColorMaskData{"VK_COLOR_COMPONENT_A_BIT | VK_COLOR_COMPONENT_B_BIT | "
2897                       "VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT",
2898                       kColorMaskR | kColorMaskG | kColorMaskB |
2899                           kColorMaskA}));  // NOLINT(whitespace/parens)
2900 
TEST_F(CommandParserTest,ColorWriteMaskInvalid)2901 TEST_F(CommandParserTest, ColorWriteMaskInvalid) {
2902   std::string data = "colorWriteMask INVALID";
2903 
2904   Pipeline pipeline(PipelineType::kGraphics);
2905   Script script;
2906   CommandParser cp(&script, &pipeline, 1, data);
2907   Result r = cp.Parse();
2908   ASSERT_FALSE(r.IsSuccess());
2909   EXPECT_EQ("1: Unknown parameter for colorWriteMask command: INVALID",
2910             r.Error());
2911 }
2912 
TEST_F(CommandParserTest,ColorWriteMaskInvalidAfterValid)2913 TEST_F(CommandParserTest, ColorWriteMaskInvalidAfterValid) {
2914   std::string data = "colorWriteMask VK_COLOR_COMPONENT_G_BIT | INVALID";
2915 
2916   Pipeline pipeline(PipelineType::kGraphics);
2917   Script script;
2918   CommandParser cp(&script, &pipeline, 1, data);
2919   Result r = cp.Parse();
2920   ASSERT_FALSE(r.IsSuccess());
2921   EXPECT_EQ("1: Unknown parameter for colorWriteMask command: INVALID",
2922             r.Error());
2923 }
2924 
TEST_F(CommandParserTest,ColorWriteMaskMissingParam)2925 TEST_F(CommandParserTest, ColorWriteMaskMissingParam) {
2926   std::string data = "colorWriteMask";
2927 
2928   Pipeline pipeline(PipelineType::kGraphics);
2929   Script script;
2930   CommandParser cp(&script, &pipeline, 1, data);
2931   Result r = cp.Parse();
2932   ASSERT_FALSE(r.IsSuccess());
2933   EXPECT_EQ("1: Missing parameter for colorWriteMask command", r.Error());
2934 }
2935 
TEST_F(CommandParserTest,ColorWriteMaskExtraParam)2936 TEST_F(CommandParserTest, ColorWriteMaskExtraParam) {
2937   std::string data =
2938       "colorWriteMask VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_B_BIT "
2939       "EXTRA";
2940 
2941   Pipeline pipeline(PipelineType::kGraphics);
2942   Script script;
2943   CommandParser cp(&script, &pipeline, 1, data);
2944   Result r = cp.Parse();
2945   ASSERT_FALSE(r.IsSuccess());
2946   EXPECT_EQ("1: Unknown parameter for colorWriteMask command: EXTRA",
2947             r.Error());
2948 }
2949 
TEST_F(CommandParserTest,SSBO)2950 TEST_F(CommandParserTest, SSBO) {
2951   std::string data = "ssbo 5 40";
2952 
2953   Pipeline pipeline(PipelineType::kGraphics);
2954   Script script;
2955   CommandParser cp(&script, &pipeline, 1, data);
2956   Result r = cp.Parse();
2957   ASSERT_TRUE(r.IsSuccess()) << r.Error();
2958 
2959   auto& cmds = cp.Commands();
2960   ASSERT_EQ(1U, cmds.size());
2961   ASSERT_TRUE(cmds[0]->IsBuffer());
2962 
2963   auto* cmd = cmds[0]->AsBuffer();
2964   EXPECT_TRUE(cmd->IsSSBO());
2965   EXPECT_EQ(static_cast<uint32_t>(0), cmd->GetDescriptorSet());
2966   EXPECT_EQ(5U, cmd->GetBinding());
2967   EXPECT_EQ(40U, cmd->GetBuffer()->ElementCount());
2968 }
2969 
TEST_F(CommandParserTest,SSBOWithDescriptorSet)2970 TEST_F(CommandParserTest, SSBOWithDescriptorSet) {
2971   std::string data = "ssbo 9:5 40";
2972 
2973   Pipeline pipeline(PipelineType::kGraphics);
2974   Script script;
2975   CommandParser cp(&script, &pipeline, 1, data);
2976   Result r = cp.Parse();
2977   ASSERT_TRUE(r.IsSuccess()) << r.Error();
2978 
2979   auto& cmds = cp.Commands();
2980   ASSERT_EQ(1U, cmds.size());
2981   ASSERT_TRUE(cmds[0]->IsBuffer());
2982 
2983   auto* cmd = cmds[0]->AsBuffer();
2984   EXPECT_TRUE(cmd->IsSSBO());
2985   EXPECT_EQ(9U, cmd->GetDescriptorSet());
2986   EXPECT_EQ(5U, cmd->GetBinding());
2987   EXPECT_EQ(40U, cmd->GetBuffer()->ElementCount());
2988 }
2989 
TEST_F(CommandParserTest,SSBOExtraParameter)2990 TEST_F(CommandParserTest, SSBOExtraParameter) {
2991   std::string data = "ssbo 5 40 EXTRA";
2992 
2993   Pipeline pipeline(PipelineType::kGraphics);
2994   Script script;
2995   CommandParser cp(&script, &pipeline, 1, data);
2996   Result r = cp.Parse();
2997   ASSERT_FALSE(r.IsSuccess());
2998   EXPECT_EQ("1: Extra parameter for ssbo command: EXTRA", r.Error());
2999 }
3000 
TEST_F(CommandParserTest,SSBOInvalidFloatBinding)3001 TEST_F(CommandParserTest, SSBOInvalidFloatBinding) {
3002   std::string data = "ssbo 5.0 40";
3003 
3004   Pipeline pipeline(PipelineType::kGraphics);
3005   Script script;
3006   CommandParser cp(&script, &pipeline, 1, data);
3007   Result r = cp.Parse();
3008   ASSERT_FALSE(r.IsSuccess());
3009   EXPECT_EQ("1: Invalid binding value for ssbo command", r.Error());
3010 }
3011 
TEST_F(CommandParserTest,SSBOInvalidBinding)3012 TEST_F(CommandParserTest, SSBOInvalidBinding) {
3013   std::string data = "ssbo abc 40";
3014 
3015   Pipeline pipeline(PipelineType::kGraphics);
3016   Script script;
3017   CommandParser cp(&script, &pipeline, 1, data);
3018   Result r = cp.Parse();
3019   ASSERT_FALSE(r.IsSuccess());
3020   EXPECT_EQ("1: Invalid binding value for ssbo command", r.Error());
3021 }
3022 
TEST_F(CommandParserTest,SSBOInvalidFloatSize)3023 TEST_F(CommandParserTest, SSBOInvalidFloatSize) {
3024   std::string data = "ssbo 5 40.0";
3025 
3026   Pipeline pipeline(PipelineType::kGraphics);
3027   Script script;
3028   CommandParser cp(&script, &pipeline, 1, data);
3029   Result r = cp.Parse();
3030   ASSERT_FALSE(r.IsSuccess());
3031   EXPECT_EQ("1: Invalid size value for ssbo command: 40.0", r.Error());
3032 }
3033 
TEST_F(CommandParserTest,SSBOInvalidSize)3034 TEST_F(CommandParserTest, SSBOInvalidSize) {
3035   std::string data = "ssbo 5 abc";
3036 
3037   Pipeline pipeline(PipelineType::kGraphics);
3038   Script script;
3039   CommandParser cp(&script, &pipeline, 1, data);
3040   Result r = cp.Parse();
3041   ASSERT_FALSE(r.IsSuccess());
3042   EXPECT_EQ("1: Invalid value for ssbo command: abc", r.Error());
3043 }
3044 
TEST_F(CommandParserTest,SSBOMissingSize)3045 TEST_F(CommandParserTest, SSBOMissingSize) {
3046   std::string data = "ssbo 5";
3047 
3048   Pipeline pipeline(PipelineType::kGraphics);
3049   Script script;
3050   CommandParser cp(&script, &pipeline, 1, data);
3051   Result r = cp.Parse();
3052   ASSERT_FALSE(r.IsSuccess());
3053   EXPECT_EQ("1: Missing size value for ssbo command: ", r.Error());
3054 }
3055 
TEST_F(CommandParserTest,SSBOMissingBinding)3056 TEST_F(CommandParserTest, SSBOMissingBinding) {
3057   std::string data = "ssbo";
3058 
3059   Pipeline pipeline(PipelineType::kGraphics);
3060   Script script;
3061   CommandParser cp(&script, &pipeline, 1, data);
3062   Result r = cp.Parse();
3063   ASSERT_FALSE(r.IsSuccess());
3064   EXPECT_EQ("1: Missing binding and size values for ssbo command", r.Error());
3065 }
3066 
TEST_F(CommandParserTest,SSBOSubdataWithFloat)3067 TEST_F(CommandParserTest, SSBOSubdataWithFloat) {
3068   std::string data = "ssbo 6 subdata vec3 16 2.3 4.2 1.2";
3069 
3070   Pipeline pipeline(PipelineType::kGraphics);
3071   Script script;
3072 
3073   CommandParser cp(&script, &pipeline, 1, data);
3074   Result r = cp.Parse();
3075   ASSERT_TRUE(r.IsSuccess()) << r.Error();
3076 
3077   auto& cmds = cp.Commands();
3078   ASSERT_EQ(1U, cmds.size());
3079   ASSERT_TRUE(cmds[0]->IsBuffer());
3080 
3081   auto* cmd = cmds[0]->AsBuffer();
3082   EXPECT_TRUE(cmd->IsSSBO());
3083   EXPECT_EQ(static_cast<uint32_t>(0), cmd->GetDescriptorSet());
3084   EXPECT_EQ(6U, cmd->GetBinding());
3085   EXPECT_EQ(16U, cmd->GetOffset());
3086   ASSERT_TRUE(cmd->IsSubdata());
3087 
3088   auto* fmt = cmd->GetBuffer()->GetFormat();
3089   ASSERT_TRUE(fmt->GetType()->IsNumber());
3090 
3091   auto n = fmt->GetType()->AsNumber();
3092   EXPECT_TRUE(type::Type::IsFloat32(n->GetFormatMode(), n->NumBits()));
3093   EXPECT_EQ(1U, fmt->GetType()->ColumnCount());
3094   EXPECT_EQ(3U, fmt->GetType()->RowCount());
3095 
3096   const auto& values = cmd->GetValues();
3097   std::vector<float> results = {2.3f, 4.2f, 1.2f};
3098   ASSERT_EQ(results.size(), values.size());
3099   for (size_t i = 0; i < results.size(); ++i) {
3100     EXPECT_FLOAT_EQ(results[i], values[i].AsFloat());
3101   }
3102 }
3103 
TEST_F(CommandParserTest,SSBOSubdataWithNegativeOffset)3104 TEST_F(CommandParserTest, SSBOSubdataWithNegativeOffset) {
3105   std::string data = "ssbo 6 subdata vec3 -2 -4 -5 -6";
3106 
3107   Pipeline pipeline(PipelineType::kGraphics);
3108   Script script;
3109   CommandParser cp(&script, &pipeline, 1, data);
3110   Result r = cp.Parse();
3111   ASSERT_FALSE(r.IsSuccess());
3112   EXPECT_EQ("1: offset for SSBO must be positive, got: -2", r.Error());
3113 }
3114 
TEST_F(CommandParserTest,SSBOSubdataWithDescriptorSet)3115 TEST_F(CommandParserTest, SSBOSubdataWithDescriptorSet) {
3116   std::string data = "ssbo 5:6 subdata vec3 16 2.3 4.2 1.2";
3117 
3118   Pipeline pipeline(PipelineType::kGraphics);
3119   Script script;
3120   CommandParser cp(&script, &pipeline, 1, data);
3121   Result r = cp.Parse();
3122   ASSERT_TRUE(r.IsSuccess()) << r.Error();
3123 
3124   auto& cmds = cp.Commands();
3125   ASSERT_EQ(1U, cmds.size());
3126   ASSERT_TRUE(cmds[0]->IsBuffer());
3127 
3128   auto* cmd = cmds[0]->AsBuffer();
3129   EXPECT_TRUE(cmd->IsSSBO());
3130   ASSERT_TRUE(cmd->IsSubdata());
3131   EXPECT_EQ(5U, cmd->GetDescriptorSet());
3132   EXPECT_EQ(6U, cmd->GetBinding());
3133   EXPECT_EQ(16U, cmd->GetOffset());
3134 
3135   auto* fmt = cmd->GetBuffer()->GetFormat();
3136   ASSERT_TRUE(fmt->GetType()->IsNumber());
3137 
3138   auto n = fmt->GetType()->AsNumber();
3139   EXPECT_TRUE(type::Type::IsFloat32(n->GetFormatMode(), n->NumBits()));
3140   EXPECT_EQ(1U, fmt->GetType()->ColumnCount());
3141   EXPECT_EQ(3U, fmt->GetType()->RowCount());
3142 
3143   const auto& values = cmd->GetValues();
3144   std::vector<float> results = {2.3f, 4.2f, 1.2f};
3145   ASSERT_EQ(results.size(), values.size());
3146   for (size_t i = 0; i < results.size(); ++i) {
3147     EXPECT_FLOAT_EQ(results[i], values[i].AsFloat());
3148   }
3149 }
3150 
TEST_F(CommandParserTest,SSBOSubdataWithInts)3151 TEST_F(CommandParserTest, SSBOSubdataWithInts) {
3152   std::string data = "ssbo 6 subdata i16vec3 8 2 4 1";
3153 
3154   Pipeline pipeline(PipelineType::kGraphics);
3155   Script script;
3156   CommandParser cp(&script, &pipeline, 1, data);
3157   Result r = cp.Parse();
3158   ASSERT_TRUE(r.IsSuccess()) << r.Error();
3159 
3160   auto& cmds = cp.Commands();
3161   ASSERT_EQ(1U, cmds.size());
3162   ASSERT_TRUE(cmds[0]->IsBuffer());
3163 
3164   auto* cmd = cmds[0]->AsBuffer();
3165   EXPECT_TRUE(cmd->IsSSBO());
3166   ASSERT_TRUE(cmd->IsSubdata());
3167   EXPECT_EQ(static_cast<uint32_t>(0), cmd->GetDescriptorSet());
3168   EXPECT_EQ(6U, cmd->GetBinding());
3169   EXPECT_EQ(8U, cmd->GetOffset());
3170 
3171   auto* fmt = cmd->GetBuffer()->GetFormat();
3172   ASSERT_TRUE(fmt->GetType()->IsNumber());
3173 
3174   auto n = fmt->GetType()->AsNumber();
3175   EXPECT_TRUE(type::Type::IsInt16(n->GetFormatMode(), n->NumBits()));
3176   EXPECT_EQ(1U, fmt->GetType()->ColumnCount());
3177   EXPECT_EQ(3U, fmt->GetType()->RowCount());
3178 
3179   const auto& values = cmd->GetValues();
3180   std::vector<int16_t> results = {2, 4, 1};
3181   ASSERT_EQ(results.size(), values.size());
3182   for (size_t i = 0; i < results.size(); ++i) {
3183     EXPECT_FLOAT_EQ(results[i], values[i].AsInt16());
3184   }
3185 }
3186 
TEST_F(CommandParserTest,SSBOSubdataWithMultipleVectors)3187 TEST_F(CommandParserTest, SSBOSubdataWithMultipleVectors) {
3188   std::string data = "ssbo 6 subdata i16vec3 8 2 4 1 3 6 8";
3189 
3190   Pipeline pipeline(PipelineType::kGraphics);
3191   Script script;
3192   CommandParser cp(&script, &pipeline, 1, data);
3193   Result r = cp.Parse();
3194   ASSERT_TRUE(r.IsSuccess()) << r.Error();
3195 
3196   auto& cmds = cp.Commands();
3197   ASSERT_EQ(1U, cmds.size());
3198   ASSERT_TRUE(cmds[0]->IsBuffer());
3199 
3200   auto* cmd = cmds[0]->AsBuffer();
3201   EXPECT_TRUE(cmd->IsSSBO());
3202   ASSERT_TRUE(cmd->IsSubdata());
3203   EXPECT_EQ(static_cast<uint32_t>(0), cmd->GetDescriptorSet());
3204   EXPECT_EQ(6U, cmd->GetBinding());
3205   EXPECT_EQ(8U, cmd->GetOffset());
3206 
3207   auto* fmt = cmd->GetBuffer()->GetFormat();
3208   ASSERT_TRUE(fmt->GetType()->IsNumber());
3209 
3210   auto n = fmt->GetType()->AsNumber();
3211   EXPECT_TRUE(type::Type::IsInt16(n->GetFormatMode(), n->NumBits()));
3212   EXPECT_EQ(1U, fmt->GetType()->ColumnCount());
3213   EXPECT_EQ(3U, fmt->GetType()->RowCount());
3214 
3215   const auto& values = cmd->GetValues();
3216   std::vector<int16_t> results = {2, 4, 1, 3, 6, 8};
3217   ASSERT_EQ(results.size(), values.size());
3218   for (size_t i = 0; i < results.size(); ++i) {
3219     EXPECT_FLOAT_EQ(results[i], values[i].AsInt16());
3220   }
3221 }
3222 
TEST_F(CommandParserTest,SSBOSubdataMissingBinding)3223 TEST_F(CommandParserTest, SSBOSubdataMissingBinding) {
3224   std::string data = "ssbo subdata i16vec3 0 2 3 2";
3225 
3226   Pipeline pipeline(PipelineType::kGraphics);
3227   Script script;
3228   CommandParser cp(&script, &pipeline, 1, data);
3229   Result r = cp.Parse();
3230   ASSERT_FALSE(r.IsSuccess());
3231   EXPECT_EQ("1: Invalid binding value for ssbo command", r.Error());
3232 }
3233 
TEST_F(CommandParserTest,SSBOSubdataWithInvalidBinding)3234 TEST_F(CommandParserTest, SSBOSubdataWithInvalidBinding) {
3235   std::string data = "ssbo INVALID subdata i16vec3 2 2 3 4";
3236 
3237   Pipeline pipeline(PipelineType::kGraphics);
3238   Script script;
3239   CommandParser cp(&script, &pipeline, 1, data);
3240   Result r = cp.Parse();
3241   ASSERT_FALSE(r.IsSuccess());
3242   EXPECT_EQ("1: Invalid binding value for ssbo command", r.Error());
3243 }
3244 
TEST_F(CommandParserTest,SSBOSubdataMissingSubdataCommand)3245 TEST_F(CommandParserTest, SSBOSubdataMissingSubdataCommand) {
3246   std::string data = "ssbo 6 INVALID i16vec3 2 2";
3247 
3248   Pipeline pipeline(PipelineType::kGraphics);
3249   Script script;
3250   CommandParser cp(&script, &pipeline, 1, data);
3251   Result r = cp.Parse();
3252   ASSERT_FALSE(r.IsSuccess());
3253   EXPECT_EQ("1: Invalid value for ssbo command: INVALID", r.Error());
3254 }
3255 
TEST_F(CommandParserTest,SSBOSubdataWithBadType)3256 TEST_F(CommandParserTest, SSBOSubdataWithBadType) {
3257   std::string data = "ssbo 0 subdata INVALID 2 2 3 4";
3258 
3259   Pipeline pipeline(PipelineType::kGraphics);
3260   Script script;
3261   CommandParser cp(&script, &pipeline, 1, data);
3262   Result r = cp.Parse();
3263   ASSERT_FALSE(r.IsSuccess());
3264   EXPECT_EQ("1: Invalid type provided: INVALID", r.Error());
3265 }
3266 
TEST_F(CommandParserTest,SSBOSubdataWithInvalidFloatOffset)3267 TEST_F(CommandParserTest, SSBOSubdataWithInvalidFloatOffset) {
3268   std::string data = "ssbo 0 subdata vec2 2.0 3 2 4";
3269 
3270   Pipeline pipeline(PipelineType::kGraphics);
3271   Script script;
3272   CommandParser cp(&script, &pipeline, 1, data);
3273   Result r = cp.Parse();
3274   ASSERT_FALSE(r.IsSuccess());
3275   EXPECT_EQ("1: Invalid offset for ssbo command: 2.0", r.Error());
3276 }
3277 
TEST_F(CommandParserTest,SSBOSubdataWithInvalidStringOffset)3278 TEST_F(CommandParserTest, SSBOSubdataWithInvalidStringOffset) {
3279   std::string data = "ssbo 0 subdata vec2 asdf 3 2 4";
3280 
3281   Pipeline pipeline(PipelineType::kGraphics);
3282   Script script;
3283   CommandParser cp(&script, &pipeline, 1, data);
3284   Result r = cp.Parse();
3285   ASSERT_FALSE(r.IsSuccess());
3286   EXPECT_EQ("1: Invalid offset for ssbo command: asdf", r.Error());
3287 }
3288 
TEST_F(CommandParserTest,SSBOSubdataWithMissingData)3289 TEST_F(CommandParserTest, SSBOSubdataWithMissingData) {
3290   std::string data = "ssbo 6 subdata i16vec3 0 2";
3291 
3292   Pipeline pipeline(PipelineType::kGraphics);
3293   Script script;
3294   CommandParser cp(&script, &pipeline, 1, data);
3295   Result r = cp.Parse();
3296   ASSERT_FALSE(r.IsSuccess());
3297   EXPECT_EQ("1: Incorrect number of values provided to ssbo command",
3298             r.Error());
3299 }
3300 
TEST_F(CommandParserTest,SSBOSubdataWithMissingAllData)3301 TEST_F(CommandParserTest, SSBOSubdataWithMissingAllData) {
3302   std::string data = "ssbo 6 subdata i16vec3 8";
3303 
3304   Pipeline pipeline(PipelineType::kGraphics);
3305   Script script;
3306   CommandParser cp(&script, &pipeline, 1, data);
3307   Result r = cp.Parse();
3308   ASSERT_FALSE(r.IsSuccess());
3309   EXPECT_EQ("1: Incorrect number of values provided to ssbo command",
3310             r.Error());
3311 }
3312 
TEST_F(CommandParserTest,SSBOSubdataWithNonDataTypeSizedOffset)3313 TEST_F(CommandParserTest, SSBOSubdataWithNonDataTypeSizedOffset) {
3314   std::string data = "ssbo 6 subdata i16vec3 2";
3315 
3316   Pipeline pipeline(PipelineType::kGraphics);
3317   Script script;
3318   CommandParser cp(&script, &pipeline, 1, data);
3319   Result r = cp.Parse();
3320   ASSERT_FALSE(r.IsSuccess());
3321   EXPECT_EQ("1: offset for SSBO must be a multiple of the data size expected 8",
3322             r.Error());
3323 }
3324 
TEST_F(CommandParserTest,Uniform)3325 TEST_F(CommandParserTest, Uniform) {
3326   std::string data = "uniform vec3 32 2.1 3.2 4.3";
3327 
3328   Pipeline pipeline(PipelineType::kGraphics);
3329   Script script;
3330   CommandParser cp(&script, &pipeline, 1, data);
3331   Result r = cp.Parse();
3332   ASSERT_TRUE(r.IsSuccess()) << r.Error();
3333 
3334   auto& cmds = cp.Commands();
3335   ASSERT_EQ(1U, cmds.size());
3336   ASSERT_TRUE(cmds[0]->IsBuffer());
3337 
3338   auto* cmd = cmds[0]->AsBuffer();
3339   EXPECT_TRUE(cmd->IsPushConstant());
3340   EXPECT_EQ(32U, cmd->GetOffset());
3341 
3342   auto* fmt = cmd->GetBuffer()->GetFormat();
3343   ASSERT_TRUE(fmt->GetType()->IsNumber());
3344 
3345   auto n = fmt->GetType()->AsNumber();
3346   EXPECT_TRUE(type::Type::IsFloat32(n->GetFormatMode(), n->NumBits()));
3347   EXPECT_EQ(1U, fmt->GetType()->ColumnCount());
3348   EXPECT_EQ(3U, fmt->GetType()->RowCount());
3349 
3350   const auto* buf = cmd->GetBuffer();
3351   const auto* values = buf->GetValues<float>();
3352   std::vector<float> results = {2.1f, 3.2f, 4.3f, 0.f};
3353   for (size_t i = 0; i < results.size(); ++i) {
3354     EXPECT_FLOAT_EQ(results[i], values[i]);
3355   }
3356 }
3357 
TEST_F(CommandParserTest,UniformOffsetMustBePositive)3358 TEST_F(CommandParserTest, UniformOffsetMustBePositive) {
3359   std::string data = "uniform vec3 -2 2.1 3.2 4.3";
3360 
3361   Pipeline pipeline(PipelineType::kGraphics);
3362   Script script;
3363   CommandParser cp(&script, &pipeline, 1, data);
3364   Result r = cp.Parse();
3365   ASSERT_FALSE(r.IsSuccess());
3366   EXPECT_EQ("1: offset for uniform must be positive, got: -2", r.Error());
3367 }
3368 
TEST_F(CommandParserTest,UniformWithContinuation)3369 TEST_F(CommandParserTest, UniformWithContinuation) {
3370   std::string data = "uniform vec3 16 2.1 3.2 4.3 \\\n5.4 6.7 8.9";
3371 
3372   Pipeline pipeline(PipelineType::kGraphics);
3373   Script script;
3374   CommandParser cp(&script, &pipeline, 1, data);
3375   Result r = cp.Parse();
3376   ASSERT_TRUE(r.IsSuccess()) << r.Error();
3377 
3378   auto& cmds = cp.Commands();
3379   ASSERT_EQ(1U, cmds.size());
3380   ASSERT_TRUE(cmds[0]->IsBuffer());
3381 
3382   auto* cmd = cmds[0]->AsBuffer();
3383   EXPECT_TRUE(cmd->IsPushConstant());
3384   EXPECT_EQ(16U, cmd->GetOffset());
3385 
3386   auto* fmt = cmd->GetBuffer()->GetFormat();
3387   ASSERT_TRUE(fmt->GetType()->IsNumber());
3388 
3389   auto n = fmt->GetType()->AsNumber();
3390   EXPECT_TRUE(type::Type::IsFloat32(n->GetFormatMode(), n->NumBits()));
3391   EXPECT_EQ(1U, fmt->GetType()->ColumnCount());
3392   EXPECT_EQ(3U, fmt->GetType()->RowCount());
3393 
3394   const auto* buf = cmd->GetBuffer();
3395   const auto* values = buf->GetValues<float>();
3396   std::vector<float> results = {2.1f, 3.2f, 4.3f, 0.f, 5.4f, 6.7f, 8.9f, 0.f};
3397   for (size_t i = 0; i < results.size(); ++i) {
3398     EXPECT_FLOAT_EQ(results[i], values[i]);
3399   }
3400 }
3401 
TEST_F(CommandParserTest,UniformInvalidType)3402 TEST_F(CommandParserTest, UniformInvalidType) {
3403   std::string data = "uniform INVALID 0 2.1 3.2 4.3";
3404 
3405   Pipeline pipeline(PipelineType::kGraphics);
3406   Script script;
3407   CommandParser cp(&script, &pipeline, 1, data);
3408   Result r = cp.Parse();
3409   ASSERT_FALSE(r.IsSuccess());
3410   EXPECT_EQ("1: Invalid type provided: INVALID", r.Error());
3411 }
3412 
TEST_F(CommandParserTest,UniformInvalidFloatOffset)3413 TEST_F(CommandParserTest, UniformInvalidFloatOffset) {
3414   std::string data = "uniform vec3 5.5 2.1 3.2 4.3";
3415 
3416   Pipeline pipeline(PipelineType::kGraphics);
3417   Script script;
3418   CommandParser cp(&script, &pipeline, 1, data);
3419   Result r = cp.Parse();
3420   ASSERT_FALSE(r.IsSuccess());
3421   EXPECT_EQ("1: Invalid offset value for uniform command: 5.5", r.Error());
3422 }
3423 
TEST_F(CommandParserTest,UniformInvalidStringOffset)3424 TEST_F(CommandParserTest, UniformInvalidStringOffset) {
3425   std::string data = "uniform vec3 INVALID 2.1 3.2 4.3";
3426 
3427   Pipeline pipeline(PipelineType::kGraphics);
3428   Script script;
3429   CommandParser cp(&script, &pipeline, 1, data);
3430   Result r = cp.Parse();
3431   ASSERT_FALSE(r.IsSuccess());
3432   EXPECT_EQ("1: Invalid offset value for uniform command: INVALID", r.Error());
3433 }
3434 
TEST_F(CommandParserTest,UniformMissingValues)3435 TEST_F(CommandParserTest, UniformMissingValues) {
3436   std::string data = "uniform vec3 0 2.1 3.2 4.3 5.5";
3437 
3438   Pipeline pipeline(PipelineType::kGraphics);
3439   Script script;
3440   CommandParser cp(&script, &pipeline, 1, data);
3441   Result r = cp.Parse();
3442   ASSERT_FALSE(r.IsSuccess());
3443   EXPECT_EQ("1: Incorrect number of values provided to uniform command",
3444             r.Error());
3445 }
3446 
TEST_F(CommandParserTest,UniformUBO)3447 TEST_F(CommandParserTest, UniformUBO) {
3448   std::string data = "uniform ubo 2 vec3 0 2.1 3.2 4.3";
3449 
3450   Pipeline pipeline(PipelineType::kGraphics);
3451   Script script;
3452   CommandParser cp(&script, &pipeline, 1, data);
3453   Result r = cp.Parse();
3454   ASSERT_TRUE(r.IsSuccess()) << r.Error();
3455 
3456   auto& cmds = cp.Commands();
3457   ASSERT_EQ(1U, cmds.size());
3458   ASSERT_TRUE(cmds[0]->IsBuffer());
3459 
3460   auto* cmd = cmds[0]->AsBuffer();
3461   EXPECT_TRUE(cmd->IsUniform());
3462   EXPECT_EQ(static_cast<uint32_t>(0), cmd->GetDescriptorSet());
3463   EXPECT_EQ(2U, cmd->GetBinding());
3464   EXPECT_EQ(static_cast<uint32_t>(0), cmd->GetOffset());
3465 
3466   auto* fmt = cmd->GetBuffer()->GetFormat();
3467   ASSERT_TRUE(fmt->GetType()->IsNumber());
3468 
3469   auto n = fmt->GetType()->AsNumber();
3470   EXPECT_TRUE(type::Type::IsFloat32(n->GetFormatMode(), n->NumBits()));
3471   EXPECT_EQ(1U, fmt->GetType()->ColumnCount());
3472   EXPECT_EQ(3U, fmt->GetType()->RowCount());
3473 
3474   const auto& values = cmd->GetValues();
3475   std::vector<float> results = {2.1f, 3.2f, 4.3f};
3476   ASSERT_EQ(results.size(), values.size());
3477   for (size_t i = 0; i < results.size(); ++i) {
3478     EXPECT_FLOAT_EQ(results[i], values[i].AsFloat());
3479   }
3480 }
3481 
TEST_F(CommandParserTest,UniformUBODisallowUpdatingInMiddleOfElement)3482 TEST_F(CommandParserTest, UniformUBODisallowUpdatingInMiddleOfElement) {
3483   std::string data = "uniform ubo 2 vec3 4 2.1 3.2 4.3";
3484 
3485   Pipeline pipeline(PipelineType::kGraphics);
3486   Script script;
3487   CommandParser cp(&script, &pipeline, 1, data);
3488   Result r = cp.Parse();
3489   ASSERT_FALSE(r.IsSuccess());
3490 
3491   EXPECT_EQ("1: offset for uniform must be multiple of data size", r.Error());
3492 }
3493 
TEST_F(CommandParserTest,UniformUBOOffsetMustBePositive)3494 TEST_F(CommandParserTest, UniformUBOOffsetMustBePositive) {
3495   std::string data = "uniform ubo 2 vec3 -1 2.1 3.2 4.3";
3496 
3497   Pipeline pipeline(PipelineType::kGraphics);
3498   Script script;
3499   CommandParser cp(&script, &pipeline, 1, data);
3500   Result r = cp.Parse();
3501   ASSERT_FALSE(r.IsSuccess());
3502   EXPECT_EQ("1: offset for uniform must be positive, got: -1", r.Error());
3503 }
3504 
TEST_F(CommandParserTest,UniformUBOWithDescriptorSet)3505 TEST_F(CommandParserTest, UniformUBOWithDescriptorSet) {
3506   std::string data = "uniform ubo 3:2 vec3 16 2.1 3.2 4.3";
3507 
3508   Pipeline pipeline(PipelineType::kGraphics);
3509   Script script;
3510   CommandParser cp(&script, &pipeline, 1, data);
3511   Result r = cp.Parse();
3512   ASSERT_TRUE(r.IsSuccess()) << r.Error();
3513 
3514   auto& cmds = cp.Commands();
3515   ASSERT_EQ(1U, cmds.size());
3516   ASSERT_TRUE(cmds[0]->IsBuffer());
3517 
3518   auto* cmd = cmds[0]->AsBuffer();
3519   EXPECT_TRUE(cmd->IsUniform());
3520   EXPECT_EQ(3U, cmd->GetDescriptorSet());
3521   EXPECT_EQ(2U, cmd->GetBinding());
3522   EXPECT_EQ(16U, cmd->GetOffset());
3523 
3524   auto* fmt = cmd->GetBuffer()->GetFormat();
3525   ASSERT_TRUE(fmt->GetType()->IsNumber());
3526 
3527   auto n = fmt->GetType()->AsNumber();
3528   EXPECT_TRUE(type::Type::IsFloat32(n->GetFormatMode(), n->NumBits()));
3529   EXPECT_EQ(1U, fmt->GetType()->ColumnCount());
3530   EXPECT_EQ(3U, fmt->GetType()->RowCount());
3531 
3532   const auto& values = cmd->GetValues();
3533   std::vector<float> results = {2.1f, 3.2f, 4.3f};
3534   ASSERT_EQ(results.size(), values.size());
3535   for (size_t i = 0; i < results.size(); ++i) {
3536     EXPECT_FLOAT_EQ(results[i], values[i].AsFloat());
3537   }
3538 }
3539 
TEST_F(CommandParserTest,UniformUBOInvalidFloatBinding)3540 TEST_F(CommandParserTest, UniformUBOInvalidFloatBinding) {
3541   std::string data = "uniform ubo 0.0 vec3 0 2.1 3.2 4.3";
3542 
3543   Pipeline pipeline(PipelineType::kGraphics);
3544   Script script;
3545   CommandParser cp(&script, &pipeline, 1, data);
3546   Result r = cp.Parse();
3547   ASSERT_FALSE(r.IsSuccess());
3548   EXPECT_EQ("1: Invalid binding value for uniform ubo command: 0.0", r.Error());
3549 }
3550 
TEST_F(CommandParserTest,UniformUBOInvalidStringBinding)3551 TEST_F(CommandParserTest, UniformUBOInvalidStringBinding) {
3552   std::string data = "uniform ubo INVALID vec3 0 2.1 3.2 4.3";
3553 
3554   Pipeline pipeline(PipelineType::kGraphics);
3555   Script script;
3556   CommandParser cp(&script, &pipeline, 1, data);
3557   Result r = cp.Parse();
3558   ASSERT_FALSE(r.IsSuccess());
3559   EXPECT_EQ("1: Invalid binding value for uniform ubo command: INVALID",
3560             r.Error());
3561 }
3562 
TEST_F(CommandParserTest,UniformUBOInvalidType)3563 TEST_F(CommandParserTest, UniformUBOInvalidType) {
3564   std::string data = "uniform ubo 0 INVALID 0 2.1 3.2 4.3";
3565 
3566   Pipeline pipeline(PipelineType::kGraphics);
3567   Script script;
3568   CommandParser cp(&script, &pipeline, 1, data);
3569   Result r = cp.Parse();
3570   ASSERT_FALSE(r.IsSuccess());
3571   EXPECT_EQ("1: Invalid type provided: INVALID", r.Error());
3572 }
3573 
TEST_F(CommandParserTest,UniformUBOInvalidFloatOffset)3574 TEST_F(CommandParserTest, UniformUBOInvalidFloatOffset) {
3575   std::string data = "uniform ubo 0 vec3 5.5 2.1 3.2 4.3";
3576 
3577   Pipeline pipeline(PipelineType::kGraphics);
3578   Script script;
3579   CommandParser cp(&script, &pipeline, 1, data);
3580   Result r = cp.Parse();
3581   ASSERT_FALSE(r.IsSuccess());
3582   EXPECT_EQ("1: Invalid offset value for uniform command: 5.5", r.Error());
3583 }
3584 
TEST_F(CommandParserTest,UniformUBOInvalidStringOffset)3585 TEST_F(CommandParserTest, UniformUBOInvalidStringOffset) {
3586   std::string data = "uniform ubo 0 vec3 INVALID 2.1 3.2 4.3";
3587 
3588   Pipeline pipeline(PipelineType::kGraphics);
3589   Script script;
3590   CommandParser cp(&script, &pipeline, 1, data);
3591   Result r = cp.Parse();
3592   ASSERT_FALSE(r.IsSuccess());
3593   EXPECT_EQ("1: Invalid offset value for uniform command: INVALID", r.Error());
3594 }
3595 
TEST_F(CommandParserTest,UniformUBOMissingValues)3596 TEST_F(CommandParserTest, UniformUBOMissingValues) {
3597   std::string data = "uniform ubo 0 vec3 0 2.1 3.2 4.3 5.5";
3598 
3599   Pipeline pipeline(PipelineType::kGraphics);
3600   Script script;
3601   CommandParser cp(&script, &pipeline, 1, data);
3602   Result r = cp.Parse();
3603   ASSERT_FALSE(r.IsSuccess());
3604   EXPECT_EQ("1: Incorrect number of values provided to uniform command",
3605             r.Error());
3606 }
3607 
TEST_F(CommandParserTest,ToleranceSingleFloatValue)3608 TEST_F(CommandParserTest, ToleranceSingleFloatValue) {
3609   std::string data = "tolerance 0.5";
3610 
3611   Pipeline pipeline(PipelineType::kGraphics);
3612   Script script;
3613   CommandParser cp(&script, &pipeline, 1, data);
3614   Result r = cp.Parse();
3615   ASSERT_TRUE(r.IsSuccess()) << r.Error();
3616 
3617   auto& tolerances = cp.TolerancesForTesting();
3618   ASSERT_EQ(1U, tolerances.size());
3619   EXPECT_FALSE(tolerances[0].is_percent);
3620   EXPECT_DOUBLE_EQ(0.5, tolerances[0].value);
3621 }
3622 
TEST_F(CommandParserTest,ToleranceSingleFloatPercent)3623 TEST_F(CommandParserTest, ToleranceSingleFloatPercent) {
3624   std::string data = "tolerance 0.5%";
3625 
3626   Pipeline pipeline(PipelineType::kGraphics);
3627   Script script;
3628   CommandParser cp(&script, &pipeline, 1, data);
3629   Result r = cp.Parse();
3630   ASSERT_TRUE(r.IsSuccess()) << r.Error();
3631 
3632   auto& tolerances = cp.TolerancesForTesting();
3633   ASSERT_EQ(1U, tolerances.size());
3634   EXPECT_TRUE(tolerances[0].is_percent);
3635   EXPECT_DOUBLE_EQ(0.5, tolerances[0].value);
3636 }
3637 
TEST_F(CommandParserTest,ToleranceSingleIntValue)3638 TEST_F(CommandParserTest, ToleranceSingleIntValue) {
3639   std::string data = "tolerance 5";
3640 
3641   Pipeline pipeline(PipelineType::kGraphics);
3642   Script script;
3643   CommandParser cp(&script, &pipeline, 1, data);
3644   Result r = cp.Parse();
3645   ASSERT_TRUE(r.IsSuccess()) << r.Error();
3646 
3647   auto& tolerances = cp.TolerancesForTesting();
3648   ASSERT_EQ(1U, tolerances.size());
3649   EXPECT_FALSE(tolerances[0].is_percent);
3650   EXPECT_DOUBLE_EQ(5.0, tolerances[0].value);
3651 }
3652 
TEST_F(CommandParserTest,ToleranceSingleIntPercent)3653 TEST_F(CommandParserTest, ToleranceSingleIntPercent) {
3654   std::string data = "tolerance 5%";
3655 
3656   Pipeline pipeline(PipelineType::kGraphics);
3657   Script script;
3658   CommandParser cp(&script, &pipeline, 1, data);
3659   Result r = cp.Parse();
3660   ASSERT_TRUE(r.IsSuccess()) << r.Error();
3661 
3662   auto& tolerances = cp.TolerancesForTesting();
3663   ASSERT_EQ(1U, tolerances.size());
3664   EXPECT_TRUE(tolerances[0].is_percent);
3665   EXPECT_DOUBLE_EQ(5.0, tolerances[0].value);
3666 }
3667 
TEST_F(CommandParserTest,ToleranceMultiFloatValue)3668 TEST_F(CommandParserTest, ToleranceMultiFloatValue) {
3669   std::string data = "tolerance 0.5 2.4 3.9 99.7";
3670 
3671   Pipeline pipeline(PipelineType::kGraphics);
3672   Script script;
3673   CommandParser cp(&script, &pipeline, 1, data);
3674   Result r = cp.Parse();
3675   ASSERT_TRUE(r.IsSuccess()) << r.Error();
3676 
3677   auto& tolerances = cp.TolerancesForTesting();
3678   std::vector<double> results = {0.5, 2.4, 3.9, 99.7};
3679   ASSERT_EQ(results.size(), tolerances.size());
3680   for (size_t i = 0; i < results.size(); ++i) {
3681     EXPECT_FALSE(tolerances[0].is_percent);
3682     EXPECT_DOUBLE_EQ(results[i], tolerances[i].value);
3683   }
3684 }
3685 
TEST_F(CommandParserTest,ToleranceMultiFloatValueWithPercent)3686 TEST_F(CommandParserTest, ToleranceMultiFloatValueWithPercent) {
3687   std::string data = "tolerance 0.5% 2.4 3.9% 99.7";
3688 
3689   Pipeline pipeline(PipelineType::kGraphics);
3690   Script script;
3691   CommandParser cp(&script, &pipeline, 1, data);
3692   Result r = cp.Parse();
3693   ASSERT_TRUE(r.IsSuccess()) << r.Error();
3694 
3695   auto& tolerances = cp.TolerancesForTesting();
3696   std::vector<double> results = {0.5, 2.4, 3.9, 99.7};
3697   ASSERT_EQ(results.size(), tolerances.size());
3698   for (size_t i = 0; i < results.size(); ++i) {
3699     if (i % 2 == 0)
3700       EXPECT_TRUE(tolerances[i].is_percent);
3701     else
3702       EXPECT_FALSE(tolerances[i].is_percent);
3703 
3704     EXPECT_DOUBLE_EQ(results[i], tolerances[i].value);
3705   }
3706 }
3707 
TEST_F(CommandParserTest,ToleranceMultiIntValue)3708 TEST_F(CommandParserTest, ToleranceMultiIntValue) {
3709   std::string data = "tolerance 5 4 3 99";
3710 
3711   Pipeline pipeline(PipelineType::kGraphics);
3712   Script script;
3713   CommandParser cp(&script, &pipeline, 1, data);
3714   Result r = cp.Parse();
3715   ASSERT_TRUE(r.IsSuccess()) << r.Error();
3716 
3717   auto& tolerances = cp.TolerancesForTesting();
3718   std::vector<double> results = {5.0, 4.0, 3.0, 99.0};
3719   ASSERT_EQ(results.size(), tolerances.size());
3720   for (size_t i = 0; i < results.size(); ++i) {
3721     EXPECT_FALSE(tolerances[0].is_percent);
3722     EXPECT_DOUBLE_EQ(results[i], tolerances[i].value);
3723   }
3724 }
3725 
TEST_F(CommandParserTest,ToleranceMultiIntValueWithPercent)3726 TEST_F(CommandParserTest, ToleranceMultiIntValueWithPercent) {
3727   std::string data = "tolerance 5% 4 3% 99";
3728 
3729   Pipeline pipeline(PipelineType::kGraphics);
3730   Script script;
3731   CommandParser cp(&script, &pipeline, 1, data);
3732   Result r = cp.Parse();
3733   ASSERT_TRUE(r.IsSuccess()) << r.Error();
3734 
3735   auto& tolerances = cp.TolerancesForTesting();
3736   std::vector<double> results = {5.0, 4.0, 3.0, 99.0};
3737   ASSERT_EQ(results.size(), tolerances.size());
3738   for (size_t i = 0; i < results.size(); ++i) {
3739     if (i % 2 == 0)
3740       EXPECT_TRUE(tolerances[i].is_percent);
3741     else
3742       EXPECT_FALSE(tolerances[i].is_percent);
3743 
3744     EXPECT_DOUBLE_EQ(results[i], tolerances[i].value);
3745   }
3746 }
3747 
TEST_F(CommandParserTest,ToleranceInvalidValue1)3748 TEST_F(CommandParserTest, ToleranceInvalidValue1) {
3749   std::string data = "tolerance INVALID";
3750 
3751   Pipeline pipeline(PipelineType::kGraphics);
3752   Script script;
3753   CommandParser cp(&script, &pipeline, 1, data);
3754   Result r = cp.Parse();
3755   ASSERT_FALSE(r.IsSuccess());
3756   EXPECT_EQ("1: Invalid value for tolerance command: INVALID", r.Error());
3757 }
3758 
TEST_F(CommandParserTest,ToleranceInvalidJustPercent)3759 TEST_F(CommandParserTest, ToleranceInvalidJustPercent) {
3760   std::string data = "tolerance %";
3761 
3762   Pipeline pipeline(PipelineType::kGraphics);
3763   Script script;
3764   CommandParser cp(&script, &pipeline, 1, data);
3765   Result r = cp.Parse();
3766   ASSERT_FALSE(r.IsSuccess());
3767   EXPECT_EQ("1: Invalid value for tolerance command: %", r.Error());
3768 }
3769 
TEST_F(CommandParserTest,ToleranceInvalidValue2)3770 TEST_F(CommandParserTest, ToleranceInvalidValue2) {
3771   std::string data = "tolerance 1 INVALID 3 4";
3772 
3773   Pipeline pipeline(PipelineType::kGraphics);
3774   Script script;
3775   CommandParser cp(&script, &pipeline, 1, data);
3776   Result r = cp.Parse();
3777   ASSERT_FALSE(r.IsSuccess());
3778   EXPECT_EQ("1: Invalid value for tolerance command: INVALID", r.Error());
3779 }
3780 
TEST_F(CommandParserTest,ToleranceInvalidValue3)3781 TEST_F(CommandParserTest, ToleranceInvalidValue3) {
3782   std::string data = "tolerance 1 2 INVALID 4";
3783 
3784   Pipeline pipeline(PipelineType::kGraphics);
3785   Script script;
3786   CommandParser cp(&script, &pipeline, 1, data);
3787   Result r = cp.Parse();
3788   ASSERT_FALSE(r.IsSuccess());
3789   EXPECT_EQ("1: Invalid value for tolerance command: INVALID", r.Error());
3790 }
3791 
TEST_F(CommandParserTest,ToleranceInvalidValue4)3792 TEST_F(CommandParserTest, ToleranceInvalidValue4) {
3793   std::string data = "tolerance 1 2 3 INVALID";
3794 
3795   Pipeline pipeline(PipelineType::kGraphics);
3796   Script script;
3797   CommandParser cp(&script, &pipeline, 1, data);
3798   Result r = cp.Parse();
3799   ASSERT_FALSE(r.IsSuccess());
3800   EXPECT_EQ("1: Invalid value for tolerance command: INVALID", r.Error());
3801 }
3802 
TEST_F(CommandParserTest,ToleranceMissingValues)3803 TEST_F(CommandParserTest, ToleranceMissingValues) {
3804   std::string data = "tolerance";
3805 
3806   Pipeline pipeline(PipelineType::kGraphics);
3807   Script script;
3808   CommandParser cp(&script, &pipeline, 1, data);
3809   Result r = cp.Parse();
3810   ASSERT_FALSE(r.IsSuccess());
3811   EXPECT_EQ("1: Missing value for tolerance command", r.Error());
3812 }
3813 
TEST_F(CommandParserTest,ToleranceTooManyValues)3814 TEST_F(CommandParserTest, ToleranceTooManyValues) {
3815   std::string data = "tolerance 1 2 3 4 5";
3816 
3817   Pipeline pipeline(PipelineType::kGraphics);
3818   Script script;
3819   CommandParser cp(&script, &pipeline, 1, data);
3820   Result r = cp.Parse();
3821   ASSERT_FALSE(r.IsSuccess());
3822   EXPECT_EQ("1: Extra parameter for tolerance command: 5", r.Error());
3823 }
3824 
TEST_F(CommandParserTest,ToleranceInvalidWithNumber)3825 TEST_F(CommandParserTest, ToleranceInvalidWithNumber) {
3826   std::string data = "tolerance 1INVALID";
3827 
3828   Pipeline pipeline(PipelineType::kGraphics);
3829   Script script;
3830   CommandParser cp(&script, &pipeline, 1, data);
3831   Result r = cp.Parse();
3832   ASSERT_FALSE(r.IsSuccess());
3833   EXPECT_EQ("1: Invalid value for tolerance command: INVALID", r.Error());
3834 }
3835 
TEST_F(CommandParserTest,ToleranceInvalidWithMissingValue)3836 TEST_F(CommandParserTest, ToleranceInvalidWithMissingValue) {
3837   std::string data = "tolerance 1, , 3, 4";
3838 
3839   Pipeline pipeline(PipelineType::kGraphics);
3840   Script script;
3841   CommandParser cp(&script, &pipeline, 1, data);
3842   Result r = cp.Parse();
3843   ASSERT_FALSE(r.IsSuccess());
3844   EXPECT_EQ("1: Invalid number of tolerance parameters provided", r.Error());
3845 }
3846 
TEST_F(CommandParserTest,ToleranceWithCommas)3847 TEST_F(CommandParserTest, ToleranceWithCommas) {
3848   std::string data = "tolerance 1,2, 3 ,4";
3849 
3850   Pipeline pipeline(PipelineType::kGraphics);
3851   Script script;
3852   CommandParser cp(&script, &pipeline, 1, data);
3853   Result r = cp.Parse();
3854   ASSERT_TRUE(r.IsSuccess()) << r.Error();
3855 
3856   auto& tolerances = cp.TolerancesForTesting();
3857   std::vector<double> results = {1.0, 2.0, 3.0, 4.0};
3858   ASSERT_EQ(results.size(), tolerances.size());
3859   for (size_t i = 0; i < results.size(); ++i) {
3860     EXPECT_FALSE(tolerances[0].is_percent);
3861     EXPECT_DOUBLE_EQ(results[i], tolerances[i].value);
3862   }
3863 }
3864 
TEST_F(CommandParserTest,ProbeSSBOWithTolerance)3865 TEST_F(CommandParserTest, ProbeSSBOWithTolerance) {
3866   std::string data = R"(
3867 ssbo 3:6 3
3868 tolerance 2 3 4 5
3869 probe ssbo vec3 3:6 2 >= 2.3 4.2 1.2)";
3870 
3871   Pipeline pipeline(PipelineType::kGraphics);
3872   Script script;
3873   CommandParser cp(&script, &pipeline, 1, data);
3874   Result r = cp.Parse();
3875   ASSERT_TRUE(r.IsSuccess()) << r.Error();
3876 
3877   auto& cmds = cp.Commands();
3878   ASSERT_EQ(2U, cmds.size());
3879   ASSERT_TRUE(cmds[1]->IsProbeSSBO());
3880 
3881   auto* cmd = cmds[1]->AsProbeSSBO();
3882   ASSERT_TRUE(cmd->HasTolerances());
3883 
3884   auto& tolerances = cmd->GetTolerances();
3885   std::vector<double> vals = {2, 3, 4, 5};
3886   ASSERT_EQ(vals.size(), tolerances.size());
3887   for (size_t i = 0; i < vals.size(); ++i) {
3888     EXPECT_FALSE(tolerances[i].is_percent);
3889     EXPECT_DOUBLE_EQ(vals[i], tolerances[i].value);
3890   }
3891 }
3892 
TEST_F(CommandParserTest,ProbeWithTolerance)3893 TEST_F(CommandParserTest, ProbeWithTolerance) {
3894   std::string data = R"(
3895 tolerance 2% 3% 4% 5%
3896 probe all rgba 0.2 0.3 0.4 0.5)";
3897 
3898   Pipeline pipeline(PipelineType::kGraphics);
3899   auto color_buf = pipeline.GenerateDefaultColorAttachmentBuffer();
3900   pipeline.AddColorAttachment(color_buf.get(), 0, 0);
3901 
3902   Script script;
3903   CommandParser cp(&script, &pipeline, 1, data);
3904   Result r = cp.Parse();
3905   ASSERT_TRUE(r.IsSuccess()) << r.Error();
3906 
3907   auto& cmds = cp.Commands();
3908   ASSERT_EQ(1U, cmds.size());
3909   ASSERT_TRUE(cmds[0]->IsProbe());
3910 
3911   auto* cmd = cmds[0]->AsProbe();
3912   ASSERT_TRUE(cmd->HasTolerances());
3913 
3914   auto& tolerances = cmd->GetTolerances();
3915   std::vector<double> vals = {2, 3, 4, 5};
3916   ASSERT_EQ(vals.size(), tolerances.size());
3917   for (size_t i = 0; i < vals.size(); ++i) {
3918     EXPECT_TRUE(tolerances[i].is_percent);
3919     EXPECT_DOUBLE_EQ(vals[i], tolerances[i].value);
3920   }
3921 }
3922 
TEST_F(CommandParserTest,ProbeSSBOWithDescriptorSet)3923 TEST_F(CommandParserTest, ProbeSSBOWithDescriptorSet) {
3924   std::string data = R"(
3925 ssbo 3:6 2
3926 probe ssbo vec3 3:6 2 >= 2.3 4.2 1.2)";
3927 
3928   Pipeline pipeline(PipelineType::kGraphics);
3929   Script script;
3930   CommandParser cp(&script, &pipeline, 1, data);
3931   Result r = cp.Parse();
3932   ASSERT_TRUE(r.IsSuccess()) << r.Error();
3933 
3934   auto& cmds = cp.Commands();
3935   ASSERT_EQ(2U, cmds.size());
3936   ASSERT_TRUE(cmds[1]->IsProbeSSBO());
3937 
3938   auto* cmd = cmds[1]->AsProbeSSBO();
3939   EXPECT_EQ(3U, cmd->GetDescriptorSet());
3940   EXPECT_EQ(6U, cmd->GetBinding());
3941   EXPECT_EQ(2U, cmd->GetOffset());
3942   EXPECT_EQ(ProbeSSBOCommand::Comparator::kGreaterOrEqual,
3943             cmd->GetComparator());
3944 
3945   auto* fmt = cmd->GetFormat();
3946   ASSERT_TRUE(fmt->GetType()->IsNumber());
3947 
3948   auto n = fmt->GetType()->AsNumber();
3949   EXPECT_TRUE(type::Type::IsFloat32(n->GetFormatMode(), n->NumBits()));
3950   EXPECT_EQ(1U, fmt->GetType()->ColumnCount());
3951   EXPECT_EQ(3U, fmt->GetType()->RowCount());
3952 
3953   const auto& values = cmd->GetValues();
3954   std::vector<float> results = {2.3f, 4.2f, 1.2f};
3955   ASSERT_EQ(results.size(), values.size());
3956   for (size_t i = 0; i < results.size(); ++i) {
3957     EXPECT_FLOAT_EQ(results[i], values[i].AsFloat());
3958   }
3959 }
3960 
TEST_F(CommandParserTest,ProbeSSBOWithFloats)3961 TEST_F(CommandParserTest, ProbeSSBOWithFloats) {
3962   std::string data = R"(
3963 ssbo 6 2
3964 probe ssbo vec3 6 2 >= 2.3 4.2 1.2)";
3965 
3966   Pipeline pipeline(PipelineType::kGraphics);
3967   Script script;
3968   CommandParser cp(&script, &pipeline, 1, data);
3969   Result r = cp.Parse();
3970   ASSERT_TRUE(r.IsSuccess()) << r.Error();
3971 
3972   auto& cmds = cp.Commands();
3973   ASSERT_EQ(2U, cmds.size());
3974   ASSERT_TRUE(cmds[1]->IsProbeSSBO());
3975 
3976   auto* cmd = cmds[1]->AsProbeSSBO();
3977   EXPECT_EQ(static_cast<uint32_t>(0), cmd->GetDescriptorSet());
3978   EXPECT_EQ(6U, cmd->GetBinding());
3979   EXPECT_EQ(2U, cmd->GetOffset());
3980   EXPECT_EQ(ProbeSSBOCommand::Comparator::kGreaterOrEqual,
3981             cmd->GetComparator());
3982 
3983   auto* fmt = cmd->GetFormat();
3984   ASSERT_TRUE(fmt->GetType()->IsNumber());
3985 
3986   auto n = fmt->GetType()->AsNumber();
3987   EXPECT_TRUE(type::Type::IsFloat32(n->GetFormatMode(), n->NumBits()));
3988   EXPECT_EQ(1U, fmt->GetType()->ColumnCount());
3989   EXPECT_EQ(3U, fmt->GetType()->RowCount());
3990 
3991   const auto& values = cmd->GetValues();
3992   std::vector<float> results = {2.3f, 4.2f, 1.2f};
3993   ASSERT_EQ(results.size(), values.size());
3994   for (size_t i = 0; i < results.size(); ++i) {
3995     EXPECT_FLOAT_EQ(results[i], values[i].AsFloat());
3996   }
3997 }
3998 
TEST_F(CommandParserTest,MultiProbeSSBOWithFloats)3999 TEST_F(CommandParserTest, MultiProbeSSBOWithFloats) {
4000   std::string data = R"(
4001 ssbo 6 2
4002 probe ssbo vec3 6 2 >= 2.3 4.2 1.2
4003 probe ssbo vec3 6 2 >= 2.3 4.2 1.2)";
4004 
4005   Pipeline pipeline(PipelineType::kGraphics);
4006   Script script;
4007   CommandParser cp(&script, &pipeline, 1, data);
4008   Result r = cp.Parse();
4009   ASSERT_TRUE(r.IsSuccess()) << r.Error();
4010 
4011   auto& cmds = cp.Commands();
4012   ASSERT_EQ(3U, cmds.size());
4013   ASSERT_TRUE(cmds[1]->IsProbeSSBO());
4014 
4015   auto* cmd = cmds[1]->AsProbeSSBO();
4016   EXPECT_EQ(6U, cmd->GetBinding());
4017   EXPECT_EQ(2U, cmd->GetOffset());
4018   EXPECT_EQ(ProbeSSBOCommand::Comparator::kGreaterOrEqual,
4019             cmd->GetComparator());
4020 
4021   auto* fmt = cmd->GetFormat();
4022   ASSERT_TRUE(fmt->GetType()->IsNumber());
4023 
4024   auto n = fmt->GetType()->AsNumber();
4025   EXPECT_TRUE(type::Type::IsFloat32(n->GetFormatMode(), n->NumBits()));
4026   EXPECT_EQ(1U, fmt->GetType()->ColumnCount());
4027   EXPECT_EQ(3U, fmt->GetType()->RowCount());
4028 
4029   const auto& values = cmd->GetValues();
4030   std::vector<float> results = {2.3f, 4.2f, 1.2f};
4031   ASSERT_EQ(results.size(), values.size());
4032   for (size_t i = 0; i < results.size(); ++i) {
4033     EXPECT_FLOAT_EQ(results[i], values[i].AsFloat());
4034   }
4035 }
4036 
TEST_F(CommandParserTest,ProbeSSBOWithInts)4037 TEST_F(CommandParserTest, ProbeSSBOWithInts) {
4038   std::string data = R"(
4039 ssbo 6 2
4040 probe ssbo i16vec3 6 2 <= 2 4 1)";
4041 
4042   Pipeline pipeline(PipelineType::kGraphics);
4043   Script script;
4044   CommandParser cp(&script, &pipeline, 1, data);
4045   Result r = cp.Parse();
4046   ASSERT_TRUE(r.IsSuccess()) << r.Error();
4047 
4048   auto& cmds = cp.Commands();
4049   ASSERT_EQ(2U, cmds.size());
4050   ASSERT_TRUE(cmds[1]->IsProbeSSBO());
4051 
4052   auto* cmd = cmds[1]->AsProbeSSBO();
4053   EXPECT_EQ(static_cast<uint32_t>(0), cmd->GetDescriptorSet());
4054   EXPECT_EQ(6U, cmd->GetBinding());
4055   EXPECT_EQ(2U, cmd->GetOffset());
4056   EXPECT_EQ(ProbeSSBOCommand::Comparator::kLessOrEqual, cmd->GetComparator());
4057 
4058   auto* fmt = cmd->GetFormat();
4059   ASSERT_TRUE(fmt->GetType()->IsNumber());
4060 
4061   auto n = fmt->GetType()->AsNumber();
4062   EXPECT_TRUE(type::Type::IsInt16(n->GetFormatMode(), n->NumBits()));
4063   EXPECT_EQ(1U, fmt->GetType()->ColumnCount());
4064   EXPECT_EQ(3U, fmt->GetType()->RowCount());
4065 
4066   const auto& values = cmd->GetValues();
4067   std::vector<int16_t> results = {2, 4, 1};
4068   ASSERT_EQ(results.size(), values.size());
4069   for (size_t i = 0; i < results.size(); ++i) {
4070     EXPECT_FLOAT_EQ(results[i], values[i].AsInt16());
4071   }
4072 }
4073 
TEST_F(CommandParserTest,ProbeSSBOWithMultipleVectors)4074 TEST_F(CommandParserTest, ProbeSSBOWithMultipleVectors) {
4075   std::string data = R"(
4076 ssbo 6 2
4077 probe ssbo i16vec3 6 2 == 2 4 1 3 6 8)";
4078 
4079   Pipeline pipeline(PipelineType::kGraphics);
4080   Script script;
4081   CommandParser cp(&script, &pipeline, 1, data);
4082   Result r = cp.Parse();
4083   ASSERT_TRUE(r.IsSuccess()) << r.Error();
4084 
4085   auto& cmds = cp.Commands();
4086   ASSERT_EQ(2U, cmds.size());
4087   ASSERT_TRUE(cmds[1]->IsProbeSSBO());
4088 
4089   auto* cmd = cmds[1]->AsProbeSSBO();
4090   EXPECT_EQ(static_cast<uint32_t>(0), cmd->GetDescriptorSet());
4091   EXPECT_EQ(6U, cmd->GetBinding());
4092   EXPECT_EQ(2U, cmd->GetOffset());
4093   EXPECT_EQ(ProbeSSBOCommand::Comparator::kEqual, cmd->GetComparator());
4094 
4095   auto* fmt = cmd->GetFormat();
4096   ASSERT_TRUE(fmt->GetType()->IsNumber());
4097 
4098   auto n = fmt->GetType()->AsNumber();
4099   EXPECT_TRUE(type::Type::IsInt16(n->GetFormatMode(), n->NumBits()));
4100   EXPECT_EQ(1U, fmt->GetType()->ColumnCount());
4101   EXPECT_EQ(3U, fmt->GetType()->RowCount());
4102 
4103   const auto& values = cmd->GetValues();
4104   std::vector<int16_t> results = {2, 4, 1, 3, 6, 8};
4105   ASSERT_EQ(results.size(), values.size());
4106   for (size_t i = 0; i < results.size(); ++i) {
4107     EXPECT_FLOAT_EQ(results[i], values[i].AsInt16());
4108   }
4109 }
4110 
TEST_F(CommandParserTest,ProbeSSBOMissingBinding)4111 TEST_F(CommandParserTest, ProbeSSBOMissingBinding) {
4112   std::string data = "probe ssbo i16vec3 2 == 2 3 2";
4113 
4114   Pipeline pipeline(PipelineType::kGraphics);
4115   Script script;
4116   CommandParser cp(&script, &pipeline, 1, data);
4117   Result r = cp.Parse();
4118   ASSERT_FALSE(r.IsSuccess());
4119   EXPECT_EQ("1: Invalid value for probe ssbo command: ==", r.Error());
4120 }
4121 
TEST_F(CommandParserTest,ProbeSSBOWithInvalidBinding)4122 TEST_F(CommandParserTest, ProbeSSBOWithInvalidBinding) {
4123   std::string data = "probe ssbo i16vec3 INVALID 2 == 2 3 4";
4124 
4125   Pipeline pipeline(PipelineType::kGraphics);
4126   Script script;
4127   CommandParser cp(&script, &pipeline, 1, data);
4128   Result r = cp.Parse();
4129   ASSERT_FALSE(r.IsSuccess());
4130   EXPECT_EQ("1: Invalid binding value for probe ssbo command: INVALID",
4131             r.Error());
4132 }
4133 
TEST_F(CommandParserTest,ProbeSSBOWithBadType)4134 TEST_F(CommandParserTest, ProbeSSBOWithBadType) {
4135   std::string data = "probe ssbo INVALID 0 2 == 2 3 4";
4136 
4137   Pipeline pipeline(PipelineType::kGraphics);
4138   Script script;
4139   CommandParser cp(&script, &pipeline, 1, data);
4140   Result r = cp.Parse();
4141   ASSERT_FALSE(r.IsSuccess());
4142   EXPECT_EQ("1: Invalid type provided: INVALID", r.Error());
4143 }
4144 
TEST_F(CommandParserTest,ProbeSSBOWithInvalidFloatOffset)4145 TEST_F(CommandParserTest, ProbeSSBOWithInvalidFloatOffset) {
4146   std::string data = R"(
4147 ssbo 0 2
4148 probe ssbo vec2 0 2.0 == 3 2 4)";
4149 
4150   Pipeline pipeline(PipelineType::kGraphics);
4151   Script script;
4152   CommandParser cp(&script, &pipeline, 1, data);
4153   Result r = cp.Parse();
4154   ASSERT_FALSE(r.IsSuccess());
4155   EXPECT_EQ("3: Invalid offset for probe ssbo command: 2.0", r.Error());
4156 }
4157 
TEST_F(CommandParserTest,ProbeSSBOWithInvalidStringOffset)4158 TEST_F(CommandParserTest, ProbeSSBOWithInvalidStringOffset) {
4159   std::string data = "probe ssbo vec2 0 INVALID == 3 2 4";
4160 
4161   Pipeline pipeline(PipelineType::kGraphics);
4162   Script script;
4163   CommandParser cp(&script, &pipeline, 1, data);
4164   Result r = cp.Parse();
4165   ASSERT_FALSE(r.IsSuccess());
4166   EXPECT_EQ("1: Invalid value for probe ssbo command: INVALID", r.Error());
4167 }
4168 
TEST_F(CommandParserTest,ProbeSSBOWithInvalidComparator)4169 TEST_F(CommandParserTest, ProbeSSBOWithInvalidComparator) {
4170   std::string data = R"(
4171 ssbo 6 2
4172 probe ssbo vec2 6 2 INVALID 3 2 4)";
4173 
4174   Pipeline pipeline(PipelineType::kGraphics);
4175   Script script;
4176   CommandParser cp(&script, &pipeline, 1, data);
4177   Result r = cp.Parse();
4178   ASSERT_FALSE(r.IsSuccess());
4179   EXPECT_EQ("3: Invalid comparator: INVALID", r.Error());
4180 }
4181 
TEST_F(CommandParserTest,ProbeSSBOWithMissingData)4182 TEST_F(CommandParserTest, ProbeSSBOWithMissingData) {
4183   std::string data = R"(
4184 ssbo 6 2
4185 probe ssbo i16vec3 6 2 == 2)";
4186 
4187   Pipeline pipeline(PipelineType::kGraphics);
4188   Script script;
4189   CommandParser cp(&script, &pipeline, 1, data);
4190   Result r = cp.Parse();
4191   ASSERT_FALSE(r.IsSuccess());
4192   EXPECT_EQ("3: Incorrect number of values provided to probe ssbo command",
4193             r.Error());
4194 }
4195 
TEST_F(CommandParserTest,ProbeSSBOWithMissingAllData)4196 TEST_F(CommandParserTest, ProbeSSBOWithMissingAllData) {
4197   std::string data = R"(
4198 ssbo 6 2
4199 probe ssbo i16vec3 6 2 ==)";
4200 
4201   Pipeline pipeline(PipelineType::kGraphics);
4202   Script script;
4203   CommandParser cp(&script, &pipeline, 1, data);
4204   Result r = cp.Parse();
4205   ASSERT_FALSE(r.IsSuccess());
4206   EXPECT_EQ("3: Incorrect number of values provided to probe ssbo command",
4207             r.Error());
4208 }
4209 
4210 struct ComparatorTest {
4211   const char* name;
4212   ProbeSSBOCommand::Comparator op;
4213 };
4214 using CommandParserComparatorTests = testing::TestWithParam<ComparatorTest>;
4215 
TEST_P(CommandParserComparatorTests,Comparator)4216 TEST_P(CommandParserComparatorTests, Comparator) {
4217   const auto& test_data = GetParam();
4218 
4219   Pipeline pipeline(PipelineType::kGraphics);
4220   Script script;
4221   CommandParser cp(&script, &pipeline, 1, "unused");
4222   ProbeSSBOCommand::Comparator result;
4223   Result r = cp.ParseComparatorForTesting(test_data.name, &result);
4224   ASSERT_TRUE(r.IsSuccess()) << r.Error();
4225   EXPECT_EQ(test_data.op, result);
4226 }
4227 
4228 INSTANTIATE_TEST_SUITE_P(
4229     ComparatorTests,
4230     CommandParserComparatorTests,
4231     testing::Values(
4232         ComparatorTest{"==", ProbeSSBOCommand::Comparator::kEqual},
4233         ComparatorTest{"!=", ProbeSSBOCommand::Comparator::kNotEqual},
4234         ComparatorTest{"~=", ProbeSSBOCommand::Comparator::kFuzzyEqual},
4235         ComparatorTest{"<", ProbeSSBOCommand::Comparator::kLess},
4236         ComparatorTest{"<=", ProbeSSBOCommand::Comparator::kLessOrEqual},
4237         ComparatorTest{">", ProbeSSBOCommand::Comparator::kGreater},
4238         ComparatorTest{">=",
4239                        ProbeSSBOCommand::Comparator::
4240                            kGreaterOrEqual}));  // NOLINT(whitespace/parens)
4241 
TEST_F(CommandParserTest,ComparatorInvalid)4242 TEST_F(CommandParserTest, ComparatorInvalid) {
4243   Pipeline pipeline(PipelineType::kGraphics);
4244   Script script;
4245   CommandParser cp(&script, &pipeline, 1, "unused");
4246   ProbeSSBOCommand::Comparator result;
4247   Result r = cp.ParseComparatorForTesting("INVALID", &result);
4248   ASSERT_FALSE(r.IsSuccess());
4249   EXPECT_EQ("Invalid comparator: INVALID", r.Error());
4250 }
4251 
4252 }  // namespace vkscript
4253 }  // namespace amber
4254