Flutter Engine
The Flutter Engine
SkSLDebugTracePlayerTest.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2021 Google LLC
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
14#include "src/sksl/SkSLString.h"
15#include "src/sksl/SkSLUtil.h"
19#include "src/sksl/ir/SkSLProgram.h" // IWYU pragma: keep
22#include "tests/Test.h"
23
24#include <cstddef>
25#include <memory>
26#include <string>
27#include <unordered_map>
28#include <unordered_set>
29#include <utility>
30#include <vector>
31
33
35 std::string src) {
36 auto debugTrace = sk_make_sp<SkSL::DebugTracePriv>();
37
40 settings.fOptimize = false;
41
42 std::unique_ptr<SkSL::Program> program =
43 compiler.convertProgram(SkSL::ProgramKind::kRuntimeShader, std::move(src), settings);
44 REPORTER_ASSERT(r, program);
45
46 if (program) {
47 const SkSL::FunctionDeclaration* main = program->getFunction("main");
49
50 if (main) {
51 // Compile our program.
52 SkArenaAlloc alloc(/*firstHeapAllocation=*/1000);
53 SkRasterPipeline pipeline(&alloc);
54 std::unique_ptr<SkSL::RP::Program> rasterProg = SkSL::MakeRasterPipelineProgram(
55 *program, *main->definition(), debugTrace.get(), /*writeTraceOps=*/true);
56 REPORTER_ASSERT(r, rasterProg);
57
58 if (rasterProg) {
59 // Append the SkSL program to the raster pipeline, and run it at xy=(0.5, 0.5).
60 static constexpr float kCoordinates[4] = {0.5f, 0.5f, 0.0f, 1.0f};
61 pipeline.appendConstantColor(&alloc, kCoordinates);
62 rasterProg->appendStages(&pipeline,
63 &alloc,
64 /*callbacks=*/nullptr,
65 /*uniforms=*/{});
66 pipeline.run(0, 0, 1, 1);
67 }
68 }
69 }
70
71 return debugTrace;
72}
73
74static std::string make_stack_string(const SkSL::DebugTracePriv& trace,
75 const SkSL::SkSLDebugTracePlayer& player) {
76 std::vector<int> callStack = player.getCallStack();
77 std::string text;
78 const char* separator = "";
79 for (int frame : callStack) {
80 text += separator;
81 separator = " -> ";
82
83 if (frame >= 0 && (size_t)frame < trace.fFuncInfo.size()) {
84 text += trace.fFuncInfo[frame].name;
85 } else {
86 text += "???";
87 }
88 }
89
90 return text;
91}
92
93static std::string make_vars_string(
94 const SkSL::DebugTracePriv& trace,
95 const std::vector<SkSL::SkSLDebugTracePlayer::VariableData>& vars) {
96 std::string text;
97 auto separator = SkSL::String::Separator();
99 text += separator();
100
101 if (var.fSlotIndex < 0 || (size_t)var.fSlotIndex >= trace.fSlotInfo.size()) {
102 text += "???";
103 continue;
104 }
105
106 const SkSL::SlotDebugInfo& slot = trace.fSlotInfo[var.fSlotIndex];
107 text += var.fDirty ? "##" : "";
108 text += slot.name;
109 text += trace.getSlotComponentSuffix(var.fSlotIndex);
110 text += " = ";
111 text += trace.slotValueToString(var.fSlotIndex, var.fValue);
112 }
113
114 return text;
115}
116
117static std::string make_local_vars_string(const SkSL::DebugTracePriv& trace,
118 const SkSL::SkSLDebugTracePlayer& player) {
119 int frame = player.getStackDepth() - 1;
120 return make_vars_string(trace, player.getLocalVariables(frame));
121}
122
123static std::string make_global_vars_string(const SkSL::DebugTracePriv& trace,
124 const SkSL::SkSLDebugTracePlayer& player) {
125 return make_vars_string(trace, player.getGlobalVariables());
126}
127
128DEF_TEST(SkSLTracePlayerCanResetToNull, r) {
130 player.reset(nullptr);
131
132 // We should be in a reasonable state.
133 REPORTER_ASSERT(r, player.cursor() == 0);
134 REPORTER_ASSERT(r, player.getCurrentLine() == -1);
136 REPORTER_ASSERT(r, player.getCallStack().empty());
137 REPORTER_ASSERT(r, player.getGlobalVariables().empty());
138 REPORTER_ASSERT(r, player.getLineNumbersReached().empty());
139}
140
141DEF_TEST(SkSLTracePlayerHelloWorld, r) {
143R"( // Line 1
144half4 main(float2 xy) { // Line 2
145 return half4(2 + 2); // Line 3
146} // Line 4
147)");
149 player.reset(trace);
150
151 // We have not started tracing yet.
152 REPORTER_ASSERT(r, player.cursor() == 0);
153 REPORTER_ASSERT(r, player.getCurrentLine() == -1);
155 REPORTER_ASSERT(r, player.getCallStack().empty());
156 REPORTER_ASSERT(r, player.getGlobalVariables().empty());
157 REPORTER_ASSERT(r, player.getLineNumbersReached() == LineNumberMap({{3, 1}}));
158
159 player.step();
160
161 // We should now be inside main.
162 REPORTER_ASSERT(r, player.cursor() > 0);
164 REPORTER_ASSERT(r, player.getCurrentLine() == 3);
165 REPORTER_ASSERT(r, make_stack_string(*trace, player) == "half4 main(float2 xy)");
166 REPORTER_ASSERT(r, player.getGlobalVariables().empty());
167 REPORTER_ASSERT(r, player.getLocalVariables(0).size() == 2); // xy
168
169 player.step();
170
171 // We have now completed the trace.
172 REPORTER_ASSERT(r, player.cursor() > 0);
174 REPORTER_ASSERT(r, player.getCurrentLine() == -1);
175 REPORTER_ASSERT(r, player.getCallStack().empty());
177 make_global_vars_string(*trace, player) ==
178 "##[main].result.x = 4, ##[main].result.y = 4, ##[main].result.z = "
179 "4, ##[main].result.w = 4");
180}
181
182DEF_TEST(SkSLTracePlayerReset, r) {
184R"( // Line 1
185half4 main(float2 xy) { // Line 2
186 return half4(2 + 2); // Line 3
187} // Line 4
188)");
190 player.reset(trace);
191
192 // We have not started tracing yet.
193 REPORTER_ASSERT(r, player.cursor() == 0);
194 REPORTER_ASSERT(r, player.getCurrentLine() == -1);
196 REPORTER_ASSERT(r, player.getCallStack().empty());
197 REPORTER_ASSERT(r, player.getGlobalVariables().empty());
198
199 player.step();
200
201 // We should now be inside main.
202 REPORTER_ASSERT(r, player.cursor() > 0);
203 REPORTER_ASSERT(r, player.getCurrentLine() == 3);
204 REPORTER_ASSERT(r, make_stack_string(*trace, player) == "half4 main(float2 xy)");
205 REPORTER_ASSERT(r, player.getGlobalVariables().empty());
206 REPORTER_ASSERT(r, player.getLocalVariables(0).size() == 2); // xy
207
208 player.reset(trace);
209
210 // We should be back to square one.
211 REPORTER_ASSERT(r, player.cursor() == 0);
212 REPORTER_ASSERT(r, player.getCurrentLine() == -1);
214 REPORTER_ASSERT(r, player.getCallStack().empty());
215 REPORTER_ASSERT(r, player.getGlobalVariables().empty());
216}
217
218DEF_TEST(SkSLTracePlayerFunctions, r) {
220R"( // Line 1
221int fnB() { // Line 2
222 return 2 + 2; // Line 3
223} // Line 4
224int fnA() { // Line 5
225 return fnB(); // Line 6
226} // Line 7
227half4 main(float2 xy) { // Line 8
228 return half4(fnA()); // Line 9
229} // Line 10
230)");
232 player.reset(trace);
233
234 // We have not started tracing yet.
235 REPORTER_ASSERT(r, player.cursor() == 0);
236 REPORTER_ASSERT(r, player.getCurrentLine() == -1);
238 REPORTER_ASSERT(r, player.getCallStack().empty());
239 REPORTER_ASSERT(r, player.getGlobalVariables().empty());
240 REPORTER_ASSERT(r, player.getLineNumbersReached() == LineNumberMap({{3, 1}, {6, 1}, {9, 1}}));
241
242 player.step();
243
244 // We should now be inside main.
246 REPORTER_ASSERT(r, player.getCurrentLine() == 9);
247 REPORTER_ASSERT(r, make_stack_string(*trace, player) == "half4 main(float2 xy)");
248 REPORTER_ASSERT(r, player.getGlobalVariables().empty());
249 REPORTER_ASSERT(r, player.getLocalVariables(0).size() == 2); // xy
250
251 player.stepOver();
252
253 // We should now have completed execution.
255 REPORTER_ASSERT(r, player.getCurrentLine() == -1);
256 REPORTER_ASSERT(r, player.getCallStack().empty());
258 make_global_vars_string(*trace, player) ==
259 "##[main].result.x = 4, ##[main].result.y = 4, ##[main].result.z = "
260 "4, ##[main].result.w = 4");
261
262 // Watch the stack grow and shrink as single-step.
263 player.reset(trace);
264 player.step();
265
266 REPORTER_ASSERT(r, make_stack_string(*trace, player) == "half4 main(float2 xy)");
268 REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "##xy.x = 0.5, ##xy.y = 0.5");
269 REPORTER_ASSERT(r, make_global_vars_string(*trace, player) == "");
270 player.step();
271
272 REPORTER_ASSERT(r, make_stack_string(*trace, player) == "half4 main(float2 xy) -> int fnA()");
275 REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "");
276 REPORTER_ASSERT(r, make_global_vars_string(*trace, player) == "");
277 player.step();
278
280 r,
281 make_stack_string(*trace, player) == "half4 main(float2 xy) -> int fnA() -> int fnB()");
282 REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "");
283 REPORTER_ASSERT(r, make_global_vars_string(*trace, player) == "");
287 player.step();
288
289 REPORTER_ASSERT(r, make_stack_string(*trace, player) == "half4 main(float2 xy) -> int fnA()");
290 REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "##[fnB].result = 4");
291 REPORTER_ASSERT(r, make_global_vars_string(*trace, player) == "");
292 player.step();
293
294 REPORTER_ASSERT(r, make_stack_string(*trace, player) == "half4 main(float2 xy)");
296 r,
297 make_local_vars_string(*trace, player) == "##[fnA].result = 4, xy.x = 0.5, xy.y = 0.5");
298 REPORTER_ASSERT(r, make_global_vars_string(*trace, player) == "");
299
300 player.step();
303 make_global_vars_string(*trace, player) ==
304 "##[main].result.x = 4, ##[main].result.y = 4, ##[main].result.z = "
305 "4, ##[main].result.w = 4");
306}
307
308DEF_TEST(SkSLTracePlayerVariables, r) {
310R"( // Line 1
311float func() { // Line 2
312 float x = 4, y = 5, z = 6; // Line 3
313 return z; // Line 4
314} // Line 5
315half4 main(float2 xy) { // Line 6
316 int a = 123; // Line 7
317 bool b = true; // Line 8
318 func(); // Line 9
319 float4 c = float4(0, 0.5, 1, -1); // Line 10
320 float3x3 d = float3x3(2); // Line 11
321 return half4(a); // Line 12
322} // Line 13
323)");
325 player.reset(trace);
326
328 r,
329 player.getLineNumbersReached() ==
331 {{3, 1}, {4, 1}, {7, 1}, {8, 1}, {9, 1}, {10, 1}, {11, 1}, {12, 1}}));
332 player.step();
333
334 REPORTER_ASSERT(r, player.getCurrentLine() == 7);
335 REPORTER_ASSERT(r, make_stack_string(*trace, player) == "half4 main(float2 xy)");
336 REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "##xy.x = 0.5, ##xy.y = 0.5");
337 player.step();
338
339 REPORTER_ASSERT(r, player.getCurrentLine() == 8);
340 REPORTER_ASSERT(r, make_stack_string(*trace, player) == "half4 main(float2 xy)");
342 make_local_vars_string(*trace, player) == "##a = 123, xy.x = 0.5, xy.y = 0.5");
343 player.step();
344
345 REPORTER_ASSERT(r, player.getCurrentLine() == 9);
346 REPORTER_ASSERT(r, make_stack_string(*trace, player) == "half4 main(float2 xy)");
348 make_local_vars_string(*trace, player) ==
349 "##b = true, a = 123, xy.x = 0.5, xy.y = 0.5");
350 player.step();
351
352 REPORTER_ASSERT(r, player.getCurrentLine() == 3);
354 make_stack_string(*trace, player) == "half4 main(float2 xy) -> float func()");
355 REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "");
356 player.step();
357
358 REPORTER_ASSERT(r, player.getCurrentLine() == 4);
360 make_stack_string(*trace, player) == "half4 main(float2 xy) -> float func()");
361 REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "##z = 6, ##y = 5, ##x = 4");
362 player.step();
363
364 REPORTER_ASSERT(r, player.getCurrentLine() == 9);
365 REPORTER_ASSERT(r, make_stack_string(*trace, player) == "half4 main(float2 xy)");
367 make_local_vars_string(*trace, player) ==
368 "##[func].result = 6, b = true, a = 123, xy.x = 0.5, xy.y = 0.5");
369 player.step();
370
371 REPORTER_ASSERT(r, player.getCurrentLine() == 10);
372 REPORTER_ASSERT(r, make_stack_string(*trace, player) == "half4 main(float2 xy)");
374 r,
375 make_local_vars_string(*trace, player) == "b = true, a = 123, xy.x = 0.5, xy.y = 0.5");
376 player.step();
377
378 REPORTER_ASSERT(r, player.getCurrentLine() == 11);
379 REPORTER_ASSERT(r, make_stack_string(*trace, player) == "half4 main(float2 xy)");
381 make_local_vars_string(*trace, player) ==
382 "##c.x = 0, ##c.y = 0.5, ##c.z = 1, ##c.w = -1, b = true, a = 123, "
383 "xy.x = 0.5, xy.y = 0.5");
384 player.step();
385
386 REPORTER_ASSERT(r, player.getCurrentLine() == 12);
387 REPORTER_ASSERT(r, make_stack_string(*trace, player) == "half4 main(float2 xy)");
389 make_local_vars_string(*trace, player) ==
390 "##d[0][0] = 2, ##d[0][1] = 0, ##d[0][2] = 0, "
391 "##d[1][0] = 0, ##d[1][1] = 2, ##d[1][2] = 0, "
392 "##d[2][0] = 0, ##d[2][1] = 0, ##d[2][2] = 2, "
393 "c.x = 0, c.y = 0.5, c.z = 1, c.w = -1, b = true, a = 123, "
394 "xy.x = 0.5, xy.y = 0.5");
395
396 player.step();
398 REPORTER_ASSERT(r, make_stack_string(*trace, player) == "");
400 make_global_vars_string(*trace, player) ==
401 "##[main].result.x = 123, ##[main].result.y = 123, "
402 "##[main].result.z = 123, ##[main].result.w = 123");
403}
404
405DEF_TEST(SkSLTracePlayerVariableGroups, r) {
407R"( // Line 1
408struct S { int x, y, z; }; // Line 2
409half4 main(float2 xy) { // Line 3
410 S s; // Line 4
411 int arr[3]; // Line 5
412 s.y = 1; // Line 6
413 arr[1] = 2; // Line 7
414 s.x = 3; // Line 8
415 arr[2] = 4; // Line 9
416 return half4(0); // Line 10
417} // Line 11
418)");
420 player.reset(trace);
421 player.step();
422
423 REPORTER_ASSERT(r, player.getCurrentLine() == 4);
424 REPORTER_ASSERT(r, make_stack_string(*trace, player) == "half4 main(float2 xy)");
425 REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "##xy.x = 0.5, ##xy.y = 0.5");
426 player.step();
428 REPORTER_ASSERT(r, player.getCurrentLine() == 5);
430 make_local_vars_string(*trace, player) ==
431 "##s.x = 0, ##s.y = 0, ##s.z = 0, xy.x = 0.5, xy.y = 0.5");
432 player.step();
433
434 REPORTER_ASSERT(r, player.getCurrentLine() == 6);
436 make_local_vars_string(*trace, player) ==
437 "##arr[0] = 0, ##arr[1] = 0, ##arr[2] = 0, s.x = 0, s.y = 0, s.z = "
438 "0, xy.x = 0.5, xy.y = 0.5");
439 player.step();
440
441 REPORTER_ASSERT(r, player.getCurrentLine() == 7);
443 make_local_vars_string(*trace, player) ==
444 "s.x = 0, ##s.y = 1, s.z = 0, arr[0] = 0, arr[1] = 0, arr[2] = 0, "
445 "xy.x = 0.5, xy.y = 0.5");
446 player.step();
447
448 REPORTER_ASSERT(r, player.getCurrentLine() == 8);
450 make_local_vars_string(*trace, player) ==
451 "arr[0] = 0, ##arr[1] = 2, arr[2] = 0, s.x = 0, s.y = 1, s.z = 0, "
452 "xy.x = 0.5, xy.y = 0.5");
453 player.step();
454
455 REPORTER_ASSERT(r, player.getCurrentLine() == 9);
457 make_local_vars_string(*trace, player) ==
458 "##s.x = 3, s.y = 1, s.z = 0, arr[0] = 0, arr[1] = 2, arr[2] = 0, "
459 "xy.x = 0.5, xy.y = 0.5");
460 player.step();
461
462 REPORTER_ASSERT(r, player.getCurrentLine() == 10);
464 make_local_vars_string(*trace, player) ==
465 "arr[0] = 0, arr[1] = 2, ##arr[2] = 4, s.x = 3, s.y = 1, s.z = 0, "
466 "xy.x = 0.5, xy.y = 0.5");
467}
468
469DEF_TEST(SkSLTracePlayerIfStatement, r) {
471R"( // Line 1
472half4 main(float2 xy) { // Line 2
473 int val; // Line 3
474 if (true) { // Line 4
475 int temp = 1; // Line 5
476 val = temp; // Line 6
477 } else { // Line 7
478 val = 2; // Line 8
479 } // Line 9
480 if (false) { // Line 10
481 int temp = 3; // Line 11
482 val = temp; // Line 12
483 } else { // Line 13
484 val = 4; // Line 14
485 } // Line 15
486 return half4(val); // Line 16
487} // Line 17
488)");
490 player.reset(trace);
491
493 r,
494 player.getLineNumbersReached() ==
495 LineNumberMap({{3, 1}, {4, 1}, {5, 1}, {6, 1}, {10, 1}, {14, 1}, {16, 1}}));
496 player.step();
497
498 REPORTER_ASSERT(r, player.getCurrentLine() == 3);
499 REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "##xy.x = 0.5, ##xy.y = 0.5");
500 player.step();
501
502 REPORTER_ASSERT(r, player.getCurrentLine() == 4);
504 make_local_vars_string(*trace, player) == "##val = 0, xy.x = 0.5, xy.y = 0.5");
505 player.step();
506
507 REPORTER_ASSERT(r, player.getCurrentLine() == 5);
508 REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "val = 0, xy.x = 0.5, xy.y = 0.5");
509 player.step();
510
511 REPORTER_ASSERT(r, player.getCurrentLine() == 6);
513 make_local_vars_string(*trace, player) ==
514 "##temp = 1, val = 0, xy.x = 0.5, xy.y = 0.5");
515 player.step();
516
517 // We skip over the false-branch.
518 REPORTER_ASSERT(r, player.getCurrentLine() == 10);
520 make_local_vars_string(*trace, player) == "##val = 1, xy.x = 0.5, xy.y = 0.5");
521 player.step();
522
523 // We skip over the true-branch.
524 REPORTER_ASSERT(r, player.getCurrentLine() == 14);
525 REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "val = 1, xy.x = 0.5, xy.y = 0.5");
526 player.step();
527
528 REPORTER_ASSERT(r, player.getCurrentLine() == 16);
530 make_local_vars_string(*trace, player) == "##val = 4, xy.x = 0.5, xy.y = 0.5");
531 player.step();
532
535 make_global_vars_string(*trace, player) ==
536 "##[main].result.x = 4, ##[main].result.y = 4, ##[main].result.z = "
537 "4, ##[main].result.w = 4");
538}
539
540DEF_TEST(SkSLTracePlayerForLoop, r) {
542R"( // Line 1
543half4 main(float2 xy) { // Line 2
544 int val = 0; // Line 3
545 for (int x = 1; x < 3; ++x) { // Line 4
546 val = x; // Line 5
547 } // Line 6
548 return half4(val); // Line 7
549} // Line 8
550)");
552 player.reset(trace);
553
555 r, player.getLineNumbersReached() == LineNumberMap({{3, 1}, {4, 3}, {5, 2}, {7, 1}}));
556 player.step();
557
558 REPORTER_ASSERT(r, player.getCurrentLine() == 3);
560 r, player.getLineNumbersReached() == LineNumberMap({{3, 0}, {4, 3}, {5, 2}, {7, 1}}));
561 REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "##xy.x = 0.5, ##xy.y = 0.5");
562 player.step();
563
564 REPORTER_ASSERT(r, player.getCurrentLine() == 4);
566 r, player.getLineNumbersReached() == LineNumberMap({{3, 0}, {4, 2}, {5, 2}, {7, 1}}));
568 make_local_vars_string(*trace, player) == "##val = 0, xy.x = 0.5, xy.y = 0.5");
569 player.step();
570
571 REPORTER_ASSERT(r, player.getCurrentLine() == 5);
573 r, player.getLineNumbersReached() == LineNumberMap({{3, 0}, {4, 2}, {5, 1}, {7, 1}}));
575 r,
576 make_local_vars_string(*trace, player) == "##x = 1, val = 0, xy.x = 0.5, xy.y = 0.5");
577 player.step();
578
579 REPORTER_ASSERT(r, player.getCurrentLine() == 4);
581 r, player.getLineNumbersReached() == LineNumberMap({{3, 0}, {4, 1}, {5, 1}, {7, 1}}));
583 r,
584 make_local_vars_string(*trace, player) == "##val = 1, x = 1, xy.x = 0.5, xy.y = 0.5");
585 player.step();
586
587 REPORTER_ASSERT(r, player.getCurrentLine() == 5);
589 r, player.getLineNumbersReached() == LineNumberMap({{3, 0}, {4, 1}, {5, 0}, {7, 1}}));
591 r,
592 make_local_vars_string(*trace, player) == "##x = 2, val = 1, xy.x = 0.5, xy.y = 0.5");
593 player.step();
594
597 r, player.getLineNumbersReached() == LineNumberMap({{3, 0}, {4, 0}, {5, 0}, {7, 1}}));
599 r,
600 make_local_vars_string(*trace, player) == "##val = 2, x = 2, xy.x = 0.5, xy.y = 0.5");
601 player.step();
602
603 REPORTER_ASSERT(r, player.getCurrentLine() == 7);
605 r, player.getLineNumbersReached() == LineNumberMap({{3, 0}, {4, 0}, {5, 0}, {7, 0}}));
606 REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "val = 2, xy.x = 0.5, xy.y = 0.5");
607 player.step();
608
611 make_global_vars_string(*trace, player) ==
612 "##[main].result.x = 2, ##[main].result.y = 2, ##[main].result.z = "
613 "2, ##[main].result.w = 2");
614}
615
616DEF_TEST(SkSLTracePlayerStepOut, r) {
618R"( // Line 1
619int fn() { // Line 2
620 int a = 11; // Line 3
621 int b = 22; // Line 4
622 int c = 33; // Line 5
623 int d = 44; // Line 6
624 return d; // Line 7
625} // Line 8
626half4 main(float2 xy) { // Line 9
627 return half4(fn()); // Line 10
628} // Line 11
629)");
631 player.reset(trace);
633 player.getLineNumbersReached() ==
634 LineNumberMap({{3, 1}, {4, 1}, {5, 1}, {6, 1}, {7, 1}, {10, 1}}));
635 player.step();
636
637 // We should now be inside main.
638 REPORTER_ASSERT(r, player.getCurrentLine() == 10);
639 REPORTER_ASSERT(r, make_stack_string(*trace, player) == "half4 main(float2 xy)");
640 player.step();
641
642 // We should now be inside fn.
643 REPORTER_ASSERT(r, player.getCurrentLine() == 3);
644 REPORTER_ASSERT(r, make_stack_string(*trace, player) == "half4 main(float2 xy) -> int fn()");
645 REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "");
646 player.step();
647
648 REPORTER_ASSERT(r, player.getCurrentLine() == 4);
649 REPORTER_ASSERT(r, make_stack_string(*trace, player) == "half4 main(float2 xy) -> int fn()");
650 REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "##a = 11");
651 player.step();
652
653 REPORTER_ASSERT(r, player.getCurrentLine() == 5);
654 REPORTER_ASSERT(r, make_stack_string(*trace, player) == "half4 main(float2 xy) -> int fn()");
655 REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "##b = 22, a = 11");
656 player.stepOut();
657
658 // We should now be back inside main(), right where we left off.
659 REPORTER_ASSERT(r, player.getCurrentLine() == 10);
660 REPORTER_ASSERT(r, make_stack_string(*trace, player) == "half4 main(float2 xy)");
662 r,
663 make_local_vars_string(*trace, player) == "##[fn].result = 44, xy.x = 0.5, xy.y = 0.5");
664 player.stepOut();
665
668 make_global_vars_string(*trace, player) ==
669 "##[main].result.x = 44, ##[main].result.y = 44, ##[main].result.z "
670 "= 44, ##[main].result.w = 44");
671}
672
673DEF_TEST(SkSLTracePlayerVariableScope, r) {
675R"( // Line 1
676half4 main(float2 xy) { // Line 2
677 int a = 1; // Line 3
678 { // Line 4
679 int b = 2; // Line 5
680 { // Line 6
681 int c = 3; // Line 7
682 } // Line 8
683 int d = 4; // Line 9
684 } // Line 10
685 int e = 5; // Line 11
686 { // Line 12
687 int f = 6; // Line 13
688 { // Line 14
689 int g = 7; // Line 15
690 } // Line 16
691 int h = 8; // Line 17
692 } // Line 18
693 int i = 9; // Line 19
694 return half4(0); // Line 20
695}
696)");
698 player.reset(trace);
700 player.getLineNumbersReached() == LineNumberMap({{3, 1},
701 {5, 1},
702 {7, 1},
703 {9, 1},
704 {11, 1},
705 {13, 1},
706 {15, 1},
707 {17, 1},
708 {19, 1},
709 {20, 1}}));
710 player.step();
711
712 // We should now be inside main.
713 REPORTER_ASSERT(r, player.getCurrentLine() == 3);
714 REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "##xy.x = 0.5, ##xy.y = 0.5");
715 player.step();
716
717 REPORTER_ASSERT(r, player.getCurrentLine() == 5);
718 REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "##a = 1, xy.x = 0.5, xy.y = 0.5");
719 player.step();
720
721 REPORTER_ASSERT(r, player.getCurrentLine() == 7);
723 r, make_local_vars_string(*trace, player) == "##b = 2, a = 1, xy.x = 0.5, xy.y = 0.5");
724 player.step();
725
726 REPORTER_ASSERT(r, player.getCurrentLine() == 9);
728 r, make_local_vars_string(*trace, player) == "b = 2, a = 1, xy.x = 0.5, xy.y = 0.5");
729 player.step();
730
731 REPORTER_ASSERT(r, player.getCurrentLine() == 11);
732 REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "a = 1, xy.x = 0.5, xy.y = 0.5");
733 player.step();
734
735 REPORTER_ASSERT(r, player.getCurrentLine() == 13);
737 r, make_local_vars_string(*trace, player) == "##e = 5, a = 1, xy.x = 0.5, xy.y = 0.5");
738 player.step();
739
740 REPORTER_ASSERT(r, player.getCurrentLine() == 15);
742 make_local_vars_string(*trace, player) ==
743 "##f = 6, e = 5, a = 1, xy.x = 0.5, xy.y = 0.5");
744 player.step();
745
746 REPORTER_ASSERT(r, player.getCurrentLine() == 17);
748 make_local_vars_string(*trace, player) ==
749 "f = 6, e = 5, a = 1, xy.x = 0.5, xy.y = 0.5");
750 player.step();
751
752 REPORTER_ASSERT(r, player.getCurrentLine() == 19);
754 r, make_local_vars_string(*trace, player) == "e = 5, a = 1, xy.x = 0.5, xy.y = 0.5");
755 player.step();
756
757 REPORTER_ASSERT(r, player.getCurrentLine() == 20);
759 make_local_vars_string(*trace, player) ==
760 "##i = 9, e = 5, a = 1, xy.x = 0.5, xy.y = 0.5");
761 player.step();
762
764}
765
766DEF_TEST(SkSLTracePlayerNestedBlocks, r) {
768R"( // Line 1
769half4 main(float2 xy) { // Line 2
770 {{{{{{{ // Line 3
771 int a, b; // Line 4
772 }}}}}}} // Line 5
773 return half4(0); // Line 6
774}
775)");
777 player.reset(trace);
778 player.step();
779
780 REPORTER_ASSERT(r, player.getCurrentLine() == 4);
781 player.step();
782
783 REPORTER_ASSERT(r, player.getCurrentLine() == 6);
784 player.step();
785
787}
788
789DEF_TEST(SkSLTracePlayerSwitchStatement, r) {
791R"( // Line 1
792half4 main(float2 xy) { // Line 2
793 int x = 2; // Line 3
794 switch (x) { // Line 4
795 case 1: // Line 5
796 break; // Line 6
797 case 2: // Line 7
798 ++x; // Line 8
799 case 3: // Line 9
800 break; // Line 10
801 case 4: // Line 11
802 } // Line 12
803 return half4(x); // Line 13
804}
805)");
807 player.reset(trace);
808 player.step();
809
810 REPORTER_ASSERT(r, player.getCurrentLine() == 3);
811 player.step();
812
813 REPORTER_ASSERT(r, player.getCurrentLine() == 4);
814 player.step();
815
816 REPORTER_ASSERT(r, player.getCurrentLine() == 8);
817 player.step();
818
819 REPORTER_ASSERT(r, player.getCurrentLine() == 10);
820 player.step();
821
822 REPORTER_ASSERT(r, player.getCurrentLine() == 13);
823 player.step();
824
826}
827
828DEF_TEST(SkSLTracePlayerBreakpoint, r) {
830R"( // Line 1
831int counter = 0; // Line 2
832void func() { // Line 3
833 --counter; // Line 4 BREAKPOINT 4 5
834} // Line 5
835half4 main(float2 xy) { // Line 6
836 for (int x = 1; x <= 3; ++x) { // Line 7
837 ++counter; // Line 8 BREAKPOINT 1 2 3
838 } // Line 9
839 func(); // Line 10
840 func(); // Line 11
841 ++counter; // Line 12 BREAKPOINT 6
842 return half4(counter); // Line 13
843} // Line 14
844)");
845 // Run the simulation with a variety of breakpoints set.
847 player.reset(trace);
848 player.setBreakpoints(std::unordered_set<int>{8, 13, 20});
849 player.run();
850 REPORTER_ASSERT(r, player.getCurrentLine() == 8);
851
852 player.run();
853 REPORTER_ASSERT(r, player.getCurrentLine() == 8);
854
855 player.setBreakpoints(std::unordered_set<int>{1, 4, 8});
856 player.run();
857 REPORTER_ASSERT(r, player.getCurrentLine() == 8);
858
859 player.run();
860 REPORTER_ASSERT(r, player.getCurrentLine() == 4);
861
862 player.setBreakpoints(std::unordered_set<int>{4, 12, 14});
863 player.run();
864 REPORTER_ASSERT(r, player.getCurrentLine() == 4);
865
866 player.run();
867 REPORTER_ASSERT(r, player.getCurrentLine() == 12);
868
869 player.run();
871
872 // Run the simulation again with no breakpoints set. We should reach the end of the trace
873 // instantly.
874 player.reset(trace);
875 player.setBreakpoints(std::unordered_set<int>{});
877
878 player.run();
880}
881
882DEF_TEST(SkSLTracePlayerStepOverWithBreakpoint, r) {
884R"( // Line 1
885int counter = 0; // Line 2
886void func() { // Line 3
887 ++counter; // Line 4 BREAKPOINT
888} // Line 5
889half4 main(float2 xy) { // Line 6
890 func(); // Line 7
891 return half4(counter); // Line 8
892} // Line 9
893)");
894 // Try stepping over with no breakpoint set; we will step over.
896 player.reset(trace);
897 player.step();
898 REPORTER_ASSERT(r, player.getCurrentLine() == 7);
899
900 player.stepOver();
901 REPORTER_ASSERT(r, player.getCurrentLine() == 8);
902
903 // Try stepping over with a breakpoint set; we will stop at the breakpoint.
904 player.reset(trace);
905 player.setBreakpoints(std::unordered_set<int>{4});
906 player.step();
907 REPORTER_ASSERT(r, player.getCurrentLine() == 7);
908
909 player.stepOver();
910 REPORTER_ASSERT(r, player.getCurrentLine() == 4);
911}
912
913DEF_TEST(SkSLTracePlayerStepOutWithBreakpoint, r) {
915R"( // Line 1
916int counter = 0; // Line 2
917void func() { // Line 3
918 ++counter; // Line 4
919 ++counter; // Line 5
920 ++counter; // Line 6 BREAKPOINT
921} // Line 7
922half4 main(float2 xy) { // Line 8
923 func(); // Line 9
924 return half4(counter); // Line 10
925} // Line 11
926)");
927 // Try stepping out with no breakpoint set; we will step out.
929 player.reset(trace);
930 player.step();
931 REPORTER_ASSERT(r, player.getCurrentLine() == 9);
932
933 player.step();
934 REPORTER_ASSERT(r, player.getCurrentLine() == 4);
935
936 player.stepOut();
937 REPORTER_ASSERT(r, player.getCurrentLine() == 9);
938
939 // Try stepping out with a breakpoint set; we will stop at the breakpoint.
940 player.reset(trace);
941 player.setBreakpoints(std::unordered_set<int>{6});
942 player.step();
943 REPORTER_ASSERT(r, player.getCurrentLine() == 9);
944
945 player.step();
946 REPORTER_ASSERT(r, player.getCurrentLine() == 4);
947
948 player.stepOut();
949 REPORTER_ASSERT(r, player.getCurrentLine() == 6);
950}
static std::string make_stack_string(const SkSL::DebugTracePriv &trace, const SkSL::SkSLDebugTracePlayer &player)
static std::string make_vars_string(const SkSL::DebugTracePriv &trace, const std::vector< SkSL::SkSLDebugTracePlayer::VariableData > &vars)
SkSL::SkSLDebugTracePlayer::LineNumberMap LineNumberMap
static std::string make_global_vars_string(const SkSL::DebugTracePriv &trace, const SkSL::SkSLDebugTracePlayer &player)
DEF_TEST(SkSLTracePlayerCanResetToNull, r)
static std::string make_local_vars_string(const SkSL::DebugTracePriv &trace, const SkSL::SkSLDebugTracePlayer &player)
static sk_sp< SkSL::DebugTracePriv > make_trace(skiatest::Reporter *r, std::string src)
#define REPORTER_ASSERT(r, cond,...)
Definition: Test.h:286
void run(size_t x, size_t y, size_t w, size_t h) const
void appendConstantColor(SkArenaAlloc *, const float rgba[4])
std::vector< FunctionDebugInfo > fFuncInfo
std::vector< SlotDebugInfo > fSlotInfo
std::string slotValueToString(int slotIndex, double value) const
std::string getSlotComponentSuffix(int slotIndex) const
const LineNumberMap & getLineNumbersReached() const
void reset(sk_sp< DebugTracePriv > trace)
std::vector< VariableData > getGlobalVariables() const
std::vector< VariableData > getLocalVariables(int stackFrameIndex) const
int32_t getCurrentLineInStackFrame(int stackFrameIndex) const
std::unordered_map< int, int > LineNumberMap
void setBreakpoints(std::unordered_set< int > breakpointLines)
std::vector< int > getCallStack() const
double frame
Definition: examples.cpp:31
std::u16string text
std::string void void auto Separator()
Definition: SkSLString.h:30
std::unique_ptr< RP::Program > MakeRasterPipelineProgram(const SkSL::Program &program, const FunctionDefinition &function, DebugTracePriv *debugTrace, bool writeTraceOps)
Definition: main.py:1
compiler
Definition: malisc.py:17
Definition: __init__.py:1