• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
8 #include "include/core/SkRefCnt.h"
9 #include "include/core/SkSpan.h"
10 #include "include/private/SkSLProgramKind.h"
11 #include "include/private/SkSLString.h"
12 #include "src/core/SkVM.h"
13 #include "src/sksl/SkSLCompiler.h"
14 #include "src/sksl/SkSLProgramSettings.h"
15 #include "src/sksl/SkSLUtil.h"
16 #include "src/sksl/codegen/SkSLVMCodeGenerator.h"
17 #include "src/sksl/ir/SkSLFunctionDeclaration.h"
18 #include "src/sksl/ir/SkSLProgram.h"
19 #include "src/sksl/tracing/SkSLDebugInfo.h"
20 #include "src/sksl/tracing/SkVMDebugTrace.h"
21 #include "src/sksl/tracing/SkVMDebugTracePlayer.h"
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 <vector>
30 
31 using LineNumberMap = SkSL::SkVMDebugTracePlayer::LineNumberMap;
32 
make_trace(skiatest::Reporter * r,std::string src)33 static sk_sp<SkSL::SkVMDebugTrace> make_trace(skiatest::Reporter* r, std::string src) {
34     SkSL::ShaderCaps caps;
35     SkSL::Compiler compiler(&caps);
36     SkSL::ProgramSettings settings;
37     settings.fOptimize = false;
38 
39     skvm::Builder b;
40     std::unique_ptr<SkSL::Program> program = compiler.convertProgram(SkSL::ProgramKind::kGeneric,
41                                                                      src, settings);
42     REPORTER_ASSERT(r, program);
43 
44     const SkSL::FunctionDeclaration* main = program->getFunction("main");
45     auto debugTrace = sk_make_sp<SkSL::SkVMDebugTrace>();
46     SkSL::ProgramToSkVM(*program, *main->definition(), &b, debugTrace.get(), /*uniforms=*/{});
47     skvm::Program p = b.done();
48     REPORTER_ASSERT(r, p.nargs() == 1);
49 
50     int result;
51     p.eval(1, &result);
52 
53     return debugTrace;
54 }
55 
make_stack_string(const SkSL::SkVMDebugTrace & trace,const SkSL::SkVMDebugTracePlayer & player)56 static std::string make_stack_string(const SkSL::SkVMDebugTrace& trace,
57                                      const SkSL::SkVMDebugTracePlayer& player) {
58     std::vector<int> callStack = player.getCallStack();
59     std::string text;
60     const char* separator = "";
61     for (int frame : callStack) {
62         text += separator;
63         separator = " -> ";
64 
65         if (frame >= 0 && (size_t)frame < trace.fFuncInfo.size()) {
66             text += trace.fFuncInfo[frame].name;
67         } else {
68             text += "???";
69         }
70     }
71 
72     return text;
73 }
74 
make_vars_string(const SkSL::SkVMDebugTrace & trace,const std::vector<SkSL::SkVMDebugTracePlayer::VariableData> & vars)75 static std::string make_vars_string(
76         const SkSL::SkVMDebugTrace& trace,
77         const std::vector<SkSL::SkVMDebugTracePlayer::VariableData>& vars) {
78     std::string text;
79     auto separator = SkSL::String::Separator();
80     for (const SkSL::SkVMDebugTracePlayer::VariableData& var : vars) {
81         text += separator();
82 
83         if (var.fSlotIndex < 0 || (size_t)var.fSlotIndex >= trace.fSlotInfo.size()) {
84             text += "???";
85             continue;
86         }
87 
88         const SkSL::SlotDebugInfo& slot = trace.fSlotInfo[var.fSlotIndex];
89         text += var.fDirty ? "##": "";
90         text += slot.name;
91         text += trace.getSlotComponentSuffix(var.fSlotIndex);
92         text += " = ";
93         text += trace.slotValueToString(var.fSlotIndex, var.fValue);
94     }
95 
96     return text;
97 }
98 
make_local_vars_string(const SkSL::SkVMDebugTrace & trace,const SkSL::SkVMDebugTracePlayer & player)99 static std::string make_local_vars_string(const SkSL::SkVMDebugTrace& trace,
100                                           const SkSL::SkVMDebugTracePlayer& player) {
101     int frame = player.getStackDepth() - 1;
102     return make_vars_string(trace, player.getLocalVariables(frame));
103 }
104 
make_global_vars_string(const SkSL::SkVMDebugTrace & trace,const SkSL::SkVMDebugTracePlayer & player)105 static std::string make_global_vars_string(const SkSL::SkVMDebugTrace& trace,
106                                            const SkSL::SkVMDebugTracePlayer& player) {
107     return make_vars_string(trace, player.getGlobalVariables());
108 }
109 
DEF_TEST(SkSLTracePlayerCanResetToNull,r)110 DEF_TEST(SkSLTracePlayerCanResetToNull, r) {
111     SkSL::SkVMDebugTracePlayer player;
112     player.reset(nullptr);
113 
114     // We should be in a reasonable state.
115     REPORTER_ASSERT(r, player.cursor() == 0);
116     REPORTER_ASSERT(r, player.getCurrentLine() == -1);
117     REPORTER_ASSERT(r, player.traceHasCompleted());
118     REPORTER_ASSERT(r, player.getCallStack().empty());
119     REPORTER_ASSERT(r, player.getGlobalVariables().empty());
120     REPORTER_ASSERT(r, player.getLineNumbersReached().empty());
121 }
122 
DEF_TEST(SkSLTracePlayerHelloWorld,r)123 DEF_TEST(SkSLTracePlayerHelloWorld, r) {
124     sk_sp<SkSL::SkVMDebugTrace> trace = make_trace(r,
125 R"(                // Line 1
126 int main() {       // Line 2
127     return 2 + 2;  // Line 3
128 }                  // Line 4
129 )");
130     SkSL::SkVMDebugTracePlayer player;
131     player.reset(trace);
132 
133     // We have not started tracing yet.
134     REPORTER_ASSERT(r, player.cursor() == 0);
135     REPORTER_ASSERT(r, player.getCurrentLine() == -1);
136     REPORTER_ASSERT(r, !player.traceHasCompleted());
137     REPORTER_ASSERT(r, player.getCallStack().empty());
138     REPORTER_ASSERT(r, player.getGlobalVariables().empty());
139     REPORTER_ASSERT(r, player.getLineNumbersReached() == LineNumberMap({{3, 1}}));
140 
141     player.step();
142 
143     // We should now be inside main.
144     REPORTER_ASSERT(r, player.cursor() > 0);
145     REPORTER_ASSERT(r, !player.traceHasCompleted());
146     REPORTER_ASSERT(r, player.getCurrentLine() == 3);
147     REPORTER_ASSERT(r, make_stack_string(*trace, player) == "int main()");
148     REPORTER_ASSERT(r, player.getGlobalVariables().empty());
149     REPORTER_ASSERT(r, player.getLocalVariables(0).empty());
150 
151     player.step();
152 
153     // We have now completed the trace.
154     REPORTER_ASSERT(r, player.cursor() > 0);
155     REPORTER_ASSERT(r, player.traceHasCompleted());
156     REPORTER_ASSERT(r, player.getCurrentLine() == -1);
157     REPORTER_ASSERT(r, player.getCallStack().empty());
158     REPORTER_ASSERT(r, make_global_vars_string(*trace, player) == "##[main].result = 4");
159 }
160 
DEF_TEST(SkSLTracePlayerReset,r)161 DEF_TEST(SkSLTracePlayerReset, r) {
162     sk_sp<SkSL::SkVMDebugTrace> trace = make_trace(r,
163 R"(                // Line 1
164 int main() {       // Line 2
165     return 2 + 2;  // Line 3
166 }                  // Line 4
167 )");
168     SkSL::SkVMDebugTracePlayer player;
169     player.reset(trace);
170 
171     // We have not started tracing yet.
172     REPORTER_ASSERT(r, player.cursor() == 0);
173     REPORTER_ASSERT(r, player.getCurrentLine() == -1);
174     REPORTER_ASSERT(r, !player.traceHasCompleted());
175     REPORTER_ASSERT(r, player.getCallStack().empty());
176     REPORTER_ASSERT(r, player.getGlobalVariables().empty());
177 
178     player.step();
179 
180     // We should now be inside main.
181     REPORTER_ASSERT(r, player.cursor() > 0);
182     REPORTER_ASSERT(r, player.getCurrentLine() == 3);
183     REPORTER_ASSERT(r, make_stack_string(*trace, player) == "int main()");
184     REPORTER_ASSERT(r, player.getGlobalVariables().empty());
185     REPORTER_ASSERT(r, player.getLocalVariables(0).empty());
186 
187     player.reset(trace);
188 
189     // We should be back to square one.
190     REPORTER_ASSERT(r, player.cursor() == 0);
191     REPORTER_ASSERT(r, player.getCurrentLine() == -1);
192     REPORTER_ASSERT(r, !player.traceHasCompleted());
193     REPORTER_ASSERT(r, player.getCallStack().empty());
194     REPORTER_ASSERT(r, player.getGlobalVariables().empty());
195 }
196 
DEF_TEST(SkSLTracePlayerFunctions,r)197 DEF_TEST(SkSLTracePlayerFunctions, r) {
198     sk_sp<SkSL::SkVMDebugTrace> trace = make_trace(r,
199 R"(                             // Line 1
200 int fnB() {                     // Line 2
201     return 2 + 2;               // Line 3
202 }                               // Line 4
203 int fnA() {                     // Line 5
204     return fnB();               // Line 6
205 }                               // Line 7
206 int main() {                    // Line 8
207     return fnA();               // Line 9
208 }                               // Line 10
209 )");
210     SkSL::SkVMDebugTracePlayer player;
211     player.reset(trace);
212 
213     // We have not started tracing yet.
214     REPORTER_ASSERT(r, player.cursor() == 0);
215     REPORTER_ASSERT(r, player.getCurrentLine() == -1);
216     REPORTER_ASSERT(r, !player.traceHasCompleted());
217     REPORTER_ASSERT(r, player.getCallStack().empty());
218     REPORTER_ASSERT(r, player.getGlobalVariables().empty());
219     REPORTER_ASSERT(r, player.getLineNumbersReached() == LineNumberMap({{3, 1}, {6, 1}, {9, 1}}));
220 
221     player.step();
222 
223     // We should now be inside main.
224     REPORTER_ASSERT(r, !player.traceHasCompleted());
225     REPORTER_ASSERT(r, player.getCurrentLine() == 9);
226     REPORTER_ASSERT(r, make_stack_string(*trace, player) == "int main()");
227     REPORTER_ASSERT(r, player.getGlobalVariables().empty());
228     REPORTER_ASSERT(r, player.getLocalVariables(0).empty());
229 
230     player.stepOver();
231 
232     // We should now have completed execution.
233     REPORTER_ASSERT(r, player.traceHasCompleted());
234     REPORTER_ASSERT(r, player.getCurrentLine() == -1);
235     REPORTER_ASSERT(r, player.getCallStack().empty());
236     REPORTER_ASSERT(r, make_global_vars_string(*trace, player) == "##[main].result = 4");
237 
238     // Watch the stack grow and shrink as single-step.
239     player.reset(trace);
240     player.step();
241 
242     REPORTER_ASSERT(r, make_stack_string(*trace, player) == "int main()");
243     REPORTER_ASSERT(r, player.getCurrentLineInStackFrame(0) == 9);
244     REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "");
245     REPORTER_ASSERT(r, make_global_vars_string(*trace, player) == "");
246     player.step();
247 
248     REPORTER_ASSERT(r, make_stack_string(*trace, player) == "int main() -> int fnA()");
249     REPORTER_ASSERT(r, player.getCurrentLineInStackFrame(0) == 9);
250     REPORTER_ASSERT(r, player.getCurrentLineInStackFrame(1) == 6);
251     REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "");
252     REPORTER_ASSERT(r, make_global_vars_string(*trace, player) == "");
253     player.step();
254 
255     REPORTER_ASSERT(r, make_stack_string(*trace, player) == "int main() -> int fnA() -> int fnB()");
256     REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "");
257     REPORTER_ASSERT(r, make_global_vars_string(*trace, player) == "");
258     REPORTER_ASSERT(r, player.getCurrentLineInStackFrame(0) == 9);
259     REPORTER_ASSERT(r, player.getCurrentLineInStackFrame(1) == 6);
260     REPORTER_ASSERT(r, player.getCurrentLineInStackFrame(2) == 3);
261     player.step();
262 
263     REPORTER_ASSERT(r, make_stack_string(*trace, player) == "int main() -> int fnA()");
264     REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "##[fnB].result = 4");
265     REPORTER_ASSERT(r, make_global_vars_string(*trace, player) == "");
266     player.step();
267 
268     REPORTER_ASSERT(r, make_stack_string(*trace, player) == "int main()");
269     REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "##[fnA].result = 4");
270     REPORTER_ASSERT(r, make_global_vars_string(*trace, player) == "");
271 
272     player.step();
273     REPORTER_ASSERT(r, player.traceHasCompleted());
274     REPORTER_ASSERT(r, make_global_vars_string(*trace, player) == "##[main].result = 4");
275 }
276 
DEF_TEST(SkSLTracePlayerVariables,r)277 DEF_TEST(SkSLTracePlayerVariables, r) {
278     sk_sp<SkSL::SkVMDebugTrace> trace = make_trace(r,
279 R"(                                   // Line 1
280 float func() {                        // Line 2
281     float x = 4, y = 5, z = 6;        // Line 3
282     return z;                         // Line 4
283 }                                     // Line 5
284 int main() {                          // Line 6
285     int a = 123;                      // Line 7
286     bool b = true;                    // Line 8
287     func();                           // Line 9
288     float4 c = float4(0, 0.5, 1, -1); // Line 10
289     float3x3 d = float3x3(2);         // Line 11
290     return a;                         // Line 12
291 }                                     // Line 13
292 )");
293     SkSL::SkVMDebugTracePlayer player;
294     player.reset(trace);
295 
296     REPORTER_ASSERT(r, player.getLineNumbersReached() == LineNumberMap({{3, 1}, {4, 1}, {7, 1},
297                                                                         {8, 1}, {9, 1}, {10, 1},
298                                                                         {11, 1}, {12, 1}}));
299     player.step();
300 
301     REPORTER_ASSERT(r, player.getCurrentLine() == 7);
302     REPORTER_ASSERT(r, make_stack_string(*trace, player) == "int main()");
303     REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "");
304     player.step();
305 
306     REPORTER_ASSERT(r, player.getCurrentLine() == 8);
307     REPORTER_ASSERT(r, make_stack_string(*trace, player) == "int main()");
308     REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "##a = 123");
309     player.step();
310 
311     REPORTER_ASSERT(r, player.getCurrentLine() == 9);
312     REPORTER_ASSERT(r, make_stack_string(*trace, player) == "int main()");
313     REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "##b = true, a = 123");
314     player.step();
315 
316     REPORTER_ASSERT(r, player.getCurrentLine() == 3);
317     REPORTER_ASSERT(r, make_stack_string(*trace, player) == "int main() -> float func()");
318     REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "");
319     player.step();
320 
321     REPORTER_ASSERT(r, player.getCurrentLine() == 4);
322     REPORTER_ASSERT(r, make_stack_string(*trace, player) == "int main() -> float func()");
323     REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "##z = 6, ##y = 5, ##x = 4");
324     player.step();
325 
326     REPORTER_ASSERT(r, player.getCurrentLine() == 9);
327     REPORTER_ASSERT(r, make_stack_string(*trace, player) == "int main()");
328     REPORTER_ASSERT(r, make_local_vars_string(*trace, player) ==
329                        "##[func].result = 6, b = true, a = 123");
330     player.step();
331 
332     REPORTER_ASSERT(r, player.getCurrentLine() == 10);
333     REPORTER_ASSERT(r, make_stack_string(*trace, player) == "int main()");
334     REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "b = true, a = 123");
335     player.step();
336 
337     REPORTER_ASSERT(r, player.getCurrentLine() == 11);
338     REPORTER_ASSERT(r, make_stack_string(*trace, player) == "int main()");
339     REPORTER_ASSERT(r, make_local_vars_string(*trace, player) ==
340                        "##c.x = 0, ##c.y = 0.5, ##c.z = 1, ##c.w = -1, b = true, a = 123");
341     player.step();
342 
343     REPORTER_ASSERT(r, player.getCurrentLine() == 12);
344     REPORTER_ASSERT(r, make_stack_string(*trace, player) == "int main()");
345     REPORTER_ASSERT(r, make_local_vars_string(*trace, player) ==
346                        "##d[0][0] = 2, ##d[0][1] = 0, ##d[0][2] = 0, "
347                        "##d[1][0] = 0, ##d[1][1] = 2, ##d[1][2] = 0, "
348                        "##d[2][0] = 0, ##d[2][1] = 0, ##d[2][2] = 2, "
349                        "c.x = 0, c.y = 0.5, c.z = 1, c.w = -1, b = true, a = 123");
350 
351 
352     player.step();
353     REPORTER_ASSERT(r, player.traceHasCompleted());
354     REPORTER_ASSERT(r, make_stack_string(*trace, player) == "");
355     REPORTER_ASSERT(r, make_global_vars_string(*trace, player) == "##[main].result = 123");
356 }
357 
DEF_TEST(SkSLTracePlayerVariableGroups,r)358 DEF_TEST(SkSLTracePlayerVariableGroups, r) {
359     sk_sp<SkSL::SkVMDebugTrace> trace = make_trace(r,
360 R"(                                   // Line 1
361 struct S { int x, y, z; };            // Line 2
362 int main() {                          // Line 3
363     S s;                              // Line 4
364     int arr[3];                       // Line 5
365     s.y = 1;                          // Line 6
366     arr[1] = 2;                       // Line 7
367     s.x = 3;                          // Line 8
368     arr[2] = 4;                       // Line 9
369     return 0;                         // Line 10
370 }                                     // Line 11
371 )");
372     SkSL::SkVMDebugTracePlayer player;
373     player.reset(trace);
374     player.step();
375 
376     REPORTER_ASSERT(r, player.getCurrentLine() == 4);
377     REPORTER_ASSERT(r, make_stack_string(*trace, player) == "int main()");
378     REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "");
379     player.step();
380 
381     REPORTER_ASSERT(r, player.getCurrentLine() == 5);
382     REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "##s.x = 0, ##s.y = 0, ##s.z = 0");
383     player.step();
384 
385     REPORTER_ASSERT(r, player.getCurrentLine() == 6);
386     REPORTER_ASSERT(r, make_local_vars_string(*trace, player) ==
387                        "##arr[0] = 0, ##arr[1] = 0, ##arr[2] = 0, s.x = 0, s.y = 0, s.z = 0");
388     player.step();
389 
390     REPORTER_ASSERT(r, player.getCurrentLine() == 7);
391     REPORTER_ASSERT(r, make_local_vars_string(*trace, player) ==
392                        "s.x = 0, ##s.y = 1, s.z = 0, arr[0] = 0, arr[1] = 0, arr[2] = 0");
393     player.step();
394 
395     REPORTER_ASSERT(r, player.getCurrentLine() == 8);
396     REPORTER_ASSERT(r, make_local_vars_string(*trace, player) ==
397                        "arr[0] = 0, ##arr[1] = 2, arr[2] = 0, s.x = 0, s.y = 1, s.z = 0");
398     player.step();
399 
400     REPORTER_ASSERT(r, player.getCurrentLine() == 9);
401     REPORTER_ASSERT(r, make_local_vars_string(*trace, player) ==
402                        "##s.x = 3, s.y = 1, s.z = 0, arr[0] = 0, arr[1] = 2, arr[2] = 0");
403     player.step();
404 
405     REPORTER_ASSERT(r, player.getCurrentLine() == 10);
406     REPORTER_ASSERT(r, make_local_vars_string(*trace, player) ==
407                        "arr[0] = 0, arr[1] = 2, ##arr[2] = 4, s.x = 3, s.y = 1, s.z = 0");
408 }
409 
410 
DEF_TEST(SkSLTracePlayerIfStatement,r)411 DEF_TEST(SkSLTracePlayerIfStatement, r) {
412     sk_sp<SkSL::SkVMDebugTrace> trace = make_trace(r,
413 R"(                   // Line 1
414 int main() {          // Line 2
415     int val;          // Line 3
416     if (true) {       // Line 4
417         int temp = 1; // Line 5
418         val = temp;   // Line 6
419     } else {          // Line 7
420         val = 2;      // Line 8
421     }                 // Line 9
422     if (false) {      // Line 10
423         int temp = 3; // Line 11
424         val = temp;   // Line 12
425     } else {          // Line 13
426         val = 4;      // Line 14
427     }                 // Line 15
428     return val;       // Line 16
429 }                     // Line 17
430 )");
431     SkSL::SkVMDebugTracePlayer player;
432     player.reset(trace);
433 
434     REPORTER_ASSERT(r, player.getLineNumbersReached() == LineNumberMap({{3, 1}, {4, 1}, {5, 1},
435                                                                         {6, 1}, {10, 1}, {14, 1},
436                                                                         {16, 1}}));
437     player.step();
438 
439     REPORTER_ASSERT(r, player.getCurrentLine() == 3);
440     REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "");
441     player.step();
442 
443     REPORTER_ASSERT(r, player.getCurrentLine() == 4);
444     REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "##val = 0");
445     player.step();
446 
447     REPORTER_ASSERT(r, player.getCurrentLine() == 5);
448     REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "val = 0");
449     player.step();
450 
451     REPORTER_ASSERT(r, player.getCurrentLine() == 6);
452     REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "##temp = 1, val = 0");
453     player.step();
454 
455     // We skip over the false-branch.
456     REPORTER_ASSERT(r, player.getCurrentLine() == 10);
457     REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "##val = 1");
458     player.step();
459 
460     // We skip over the true-branch.
461     REPORTER_ASSERT(r, player.getCurrentLine() == 14);
462     REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "val = 1");
463     player.step();
464 
465     REPORTER_ASSERT(r, player.getCurrentLine() == 16);
466     REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "##val = 4");
467     player.step();
468 
469     REPORTER_ASSERT(r, player.traceHasCompleted());
470     REPORTER_ASSERT(r, make_global_vars_string(*trace, player) == "##[main].result = 4");
471 }
472 
DEF_TEST(SkSLTracePlayerForLoop,r)473 DEF_TEST(SkSLTracePlayerForLoop, r) {
474     sk_sp<SkSL::SkVMDebugTrace> trace = make_trace(r,
475 R"(                                // Line 1
476 int main() {                       // Line 2
477     int val = 0;                   // Line 3
478     for (int x = 1; x < 3; ++x) {  // Line 4
479         val = x;                   // Line 5
480     }                              // Line 6
481     return val;                    // Line 7
482 }                                  // Line 8
483 )");
484     SkSL::SkVMDebugTracePlayer player;
485     player.reset(trace);
486 
487     REPORTER_ASSERT(r, player.getLineNumbersReached() == LineNumberMap({{3, 1}, {4, 3}, {5, 2},
488                                                                         {7, 1}}));
489     player.step();
490 
491     REPORTER_ASSERT(r, player.getCurrentLine() == 3);
492     REPORTER_ASSERT(r, player.getLineNumbersReached() == LineNumberMap({{3, 0}, {4, 3}, {5, 2},
493                                                                         {7, 1}}));
494     REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "");
495     player.step();
496 
497     REPORTER_ASSERT(r, player.getCurrentLine() == 4);
498     REPORTER_ASSERT(r, player.getLineNumbersReached() == LineNumberMap({{3, 0}, {4, 2}, {5, 2},
499                                                                         {7, 1}}));
500     REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "##val = 0");
501     player.step();
502 
503     REPORTER_ASSERT(r, player.getCurrentLine() == 5);
504     REPORTER_ASSERT(r, player.getLineNumbersReached() == LineNumberMap({{3, 0}, {4, 2}, {5, 1},
505                                                                         {7, 1}}));
506     REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "##x = 1, val = 0");
507     player.step();
508 
509     REPORTER_ASSERT(r, player.getCurrentLine() == 4);
510     REPORTER_ASSERT(r, player.getLineNumbersReached() == LineNumberMap({{3, 0}, {4, 1}, {5, 1},
511                                                                         {7, 1}}));
512     REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "##val = 1, x = 1");
513     player.step();
514 
515     REPORTER_ASSERT(r, player.getCurrentLine() == 5);
516     REPORTER_ASSERT(r, player.getLineNumbersReached() == LineNumberMap({{3, 0}, {4, 1}, {5, 0},
517                                                                         {7, 1}}));
518     REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "##x = 2, val = 1");
519     player.step();
520 
521     REPORTER_ASSERT(r, player.getCurrentLine() == 4);
522     REPORTER_ASSERT(r, player.getLineNumbersReached() == LineNumberMap({{3, 0}, {4, 0}, {5, 0},
523                                                                         {7, 1}}));
524     REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "##val = 2, x = 2");
525     player.step();
526 
527     REPORTER_ASSERT(r, player.getCurrentLine() == 7);
528     REPORTER_ASSERT(r, player.getLineNumbersReached() == LineNumberMap({{3, 0}, {4, 0}, {5, 0},
529                                                                         {7, 0}}));
530     REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "val = 2");
531     player.step();
532 
533     REPORTER_ASSERT(r, player.traceHasCompleted());
534     REPORTER_ASSERT(r, make_global_vars_string(*trace, player) == "##[main].result = 2");
535 }
536 
DEF_TEST(SkSLTracePlayerStepOut,r)537 DEF_TEST(SkSLTracePlayerStepOut, r) {
538     sk_sp<SkSL::SkVMDebugTrace> trace = make_trace(r,
539 R"(               // Line 1
540 int fn() {        // Line 2
541     int a = 11;   // Line 3
542     int b = 22;   // Line 4
543     int c = 33;   // Line 5
544     int d = 44;   // Line 6
545     return d;     // Line 7
546 }                 // Line 8
547 int main() {      // Line 9
548     return fn();  // Line 10
549 }                 // Line 11
550 )");
551     SkSL::SkVMDebugTracePlayer player;
552     player.reset(trace);
553     REPORTER_ASSERT(r, player.getLineNumbersReached() == LineNumberMap({{3, 1}, {4, 1}, {5, 1},
554                                                                         {6, 1}, {7, 1}, {10, 1}}));
555     player.step();
556 
557     // We should now be inside main.
558     REPORTER_ASSERT(r, player.getCurrentLine() == 10);
559     REPORTER_ASSERT(r, make_stack_string(*trace, player) == "int main()");
560     player.step();
561 
562     // We should now be inside fn.
563     REPORTER_ASSERT(r, player.getCurrentLine() == 3);
564     REPORTER_ASSERT(r, make_stack_string(*trace, player) == "int main() -> int fn()");
565     REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "");
566     player.step();
567 
568     REPORTER_ASSERT(r, player.getCurrentLine() == 4);
569     REPORTER_ASSERT(r, make_stack_string(*trace, player) == "int main() -> int fn()");
570     REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "##a = 11");
571     player.step();
572 
573     REPORTER_ASSERT(r, player.getCurrentLine() == 5);
574     REPORTER_ASSERT(r, make_stack_string(*trace, player) == "int main() -> int fn()");
575     REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "##b = 22, a = 11");
576     player.stepOut();
577 
578     // We should now be back inside main(), right where we left off.
579     REPORTER_ASSERT(r, player.getCurrentLine() == 10);
580     REPORTER_ASSERT(r, make_stack_string(*trace, player) == "int main()");
581     REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "##[fn].result = 44");
582     player.stepOut();
583 
584     REPORTER_ASSERT(r, player.traceHasCompleted());
585     REPORTER_ASSERT(r, make_global_vars_string(*trace, player) == "##[main].result = 44");
586 }
587 
DEF_TEST(SkSLTracePlayerVariableScope,r)588 DEF_TEST(SkSLTracePlayerVariableScope, r) {
589     sk_sp<SkSL::SkVMDebugTrace> trace = make_trace(r,
590 R"(                         // Line 1
591 int main() {                // Line 2
592     int a = 1;              // Line 3
593     {                       // Line 4
594         int b = 2;          // Line 5
595         {                   // Line 6
596             int c = 3;      // Line 7
597         }                   // Line 8
598         int d = 4;          // Line 9
599     }                       // Line 10
600     int e = 5;              // Line 11
601     {                       // Line 12
602         int f = 6;          // Line 13
603         {                   // Line 14
604             int g = 7;      // Line 15
605         }                   // Line 16
606         int h = 8;          // Line 17
607     }                       // Line 18
608     int i = 9;              // Line 19
609     return 0;               // Line 20
610 }
611 )");
612     SkSL::SkVMDebugTracePlayer player;
613     player.reset(trace);
614     REPORTER_ASSERT(r, player.getLineNumbersReached() == LineNumberMap({{3, 1}, {5, 1}, {7, 1},
615                                                                         {9, 1}, {11, 1}, {13, 1},
616                                                                         {15, 1}, {17, 1}, {19, 1},
617                                                                         {20, 1}}));
618     player.step();
619 
620     // We should now be inside main.
621     REPORTER_ASSERT(r, player.getCurrentLine() == 3);
622     REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "");
623     player.step();
624 
625     REPORTER_ASSERT(r, player.getCurrentLine() == 5);
626     REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "##a = 1");
627     player.step();
628 
629     REPORTER_ASSERT(r, player.getCurrentLine() == 7);
630     REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "##b = 2, a = 1");
631     player.step();
632 
633     REPORTER_ASSERT(r, player.getCurrentLine() == 9);
634     REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "b = 2, a = 1");
635     player.step();
636 
637     REPORTER_ASSERT(r, player.getCurrentLine() == 11);
638     REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "a = 1");
639     player.step();
640 
641     REPORTER_ASSERT(r, player.getCurrentLine() == 13);
642     REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "##e = 5, a = 1");
643     player.step();
644 
645     REPORTER_ASSERT(r, player.getCurrentLine() == 15);
646     REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "##f = 6, e = 5, a = 1");
647     player.step();
648 
649     REPORTER_ASSERT(r, player.getCurrentLine() == 17);
650     REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "f = 6, e = 5, a = 1");
651     player.step();
652 
653     REPORTER_ASSERT(r, player.getCurrentLine() == 19);
654     REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "e = 5, a = 1");
655     player.step();
656 
657     REPORTER_ASSERT(r, player.getCurrentLine() == 20);
658     REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "##i = 9, e = 5, a = 1");
659     player.step();
660 
661     REPORTER_ASSERT(r, player.traceHasCompleted());
662 }
663 
DEF_TEST(SkSLTracePlayerNestedBlocks,r)664 DEF_TEST(SkSLTracePlayerNestedBlocks, r) {
665     sk_sp<SkSL::SkVMDebugTrace> trace = make_trace(r,
666 R"(                         // Line 1
667 int main() {                // Line 2
668     {{{{{{{                 // Line 3
669             int a, b;       // Line 4
670     }}}}}}}                 // Line 5
671     return 0;               // Line 6
672 }
673 )");
674     SkSL::SkVMDebugTracePlayer player;
675     player.reset(trace);
676     player.step();
677 
678     REPORTER_ASSERT(r, player.getCurrentLine() == 4);
679     player.step();
680 
681     REPORTER_ASSERT(r, player.getCurrentLine() == 6);
682     player.step();
683 
684     REPORTER_ASSERT(r, player.traceHasCompleted());
685 }
686 
DEF_TEST(SkSLTracePlayerSwitchStatement,r)687 DEF_TEST(SkSLTracePlayerSwitchStatement, r) {
688     sk_sp<SkSL::SkVMDebugTrace> trace = make_trace(r,
689 R"(                         // Line 1
690 int main() {                // Line 2
691     int x = 2;              // Line 3
692     switch (x) {            // Line 4
693         case 1:             // Line 5
694             break;          // Line 6
695         case 2:             // Line 7
696             ++x;            // Line 8
697         case 3:             // Line 9
698             break;          // Line 10
699         case 4:             // Line 11
700     }                       // Line 12
701     return x;               // Line 13
702 }
703 )");
704     SkSL::SkVMDebugTracePlayer player;
705     player.reset(trace);
706     player.step();
707 
708     REPORTER_ASSERT(r, player.getCurrentLine() == 3);
709     player.step();
710 
711     REPORTER_ASSERT(r, player.getCurrentLine() == 4);
712     player.step();
713 
714     REPORTER_ASSERT(r, player.getCurrentLine() == 8);
715     player.step();
716 
717     REPORTER_ASSERT(r, player.getCurrentLine() == 10);
718     player.step();
719 
720     REPORTER_ASSERT(r, player.getCurrentLine() == 13);
721     player.step();
722 
723     REPORTER_ASSERT(r, player.traceHasCompleted());
724 }
725 
DEF_TEST(SkSLTracePlayerBreakpoint,r)726 DEF_TEST(SkSLTracePlayerBreakpoint, r) {
727     sk_sp<SkSL::SkVMDebugTrace> trace = make_trace(r,
728 R"(                                // Line 1
729 int counter = 0;                   // Line 2
730 void func() {                      // Line 3
731     --counter;                     // Line 4   BREAKPOINT 4 5
732 }                                  // Line 5
733 int main() {                       // Line 6
734     for (int x = 1; x <= 3; ++x) { // Line 7
735         ++counter;                 // Line 8   BREAKPOINT 1 2 3
736     }                              // Line 9
737     func();                        // Line 10
738     func();                        // Line 11
739     ++counter;                     // Line 12  BREAKPOINT 6
740     return counter;                // Line 13
741 }                                  // Line 14
742 )");
743     // Run the simulation with a variety of breakpoints set.
744     SkSL::SkVMDebugTracePlayer player;
745     player.reset(trace);
746     player.setBreakpoints(std::unordered_set<int>{8, 13, 20});
747     player.run();
748     REPORTER_ASSERT(r, player.getCurrentLine() == 8);
749 
750     player.run();
751     REPORTER_ASSERT(r, player.getCurrentLine() == 8);
752 
753     player.setBreakpoints(std::unordered_set<int>{1, 4, 8});
754     player.run();
755     REPORTER_ASSERT(r, player.getCurrentLine() == 8);
756 
757     player.run();
758     REPORTER_ASSERT(r, player.getCurrentLine() == 4);
759 
760     player.setBreakpoints(std::unordered_set<int>{4, 12, 14});
761     player.run();
762     REPORTER_ASSERT(r, player.getCurrentLine() == 4);
763 
764     player.run();
765     REPORTER_ASSERT(r, player.getCurrentLine() == 12);
766 
767     player.run();
768     REPORTER_ASSERT(r, player.traceHasCompleted());
769 
770     // Run the simulation again with no breakpoints set. We should reach the end of the trace
771     // instantly.
772     player.reset(trace);
773     player.setBreakpoints(std::unordered_set<int>{});
774     REPORTER_ASSERT(r, !player.traceHasCompleted());
775 
776     player.run();
777     REPORTER_ASSERT(r, player.traceHasCompleted());
778 }
779 
DEF_TEST(SkSLTracePlayerStepOverWithBreakpoint,r)780 DEF_TEST(SkSLTracePlayerStepOverWithBreakpoint, r) {
781     sk_sp<SkSL::SkVMDebugTrace> trace = make_trace(r,
782 R"(                   // Line 1
783 int counter = 0;      // Line 2
784 void func() {         // Line 3
785     ++counter;        // Line 4   BREAKPOINT
786 }                     // Line 5
787 int main() {          // Line 6
788     func();           // Line 7
789     return counter;   // Line 8
790 }                     // Line 9
791 )");
792     // Try stepping over with no breakpoint set; we will step over.
793     SkSL::SkVMDebugTracePlayer player;
794     player.reset(trace);
795     player.step();
796     REPORTER_ASSERT(r, player.getCurrentLine() == 7);
797 
798     player.stepOver();
799     REPORTER_ASSERT(r, player.getCurrentLine() == 8);
800 
801     // Try stepping over with a breakpoint set; we will stop at the breakpoint.
802     player.reset(trace);
803     player.setBreakpoints(std::unordered_set<int>{4});
804     player.step();
805     REPORTER_ASSERT(r, player.getCurrentLine() == 7);
806 
807     player.stepOver();
808     REPORTER_ASSERT(r, player.getCurrentLine() == 4);
809 }
810 
DEF_TEST(SkSLTracePlayerStepOutWithBreakpoint,r)811 DEF_TEST(SkSLTracePlayerStepOutWithBreakpoint, r) {
812     sk_sp<SkSL::SkVMDebugTrace> trace = make_trace(r,
813 R"(                   // Line 1
814 int counter = 0;      // Line 2
815 void func() {         // Line 3
816     ++counter;        // Line 4
817     ++counter;        // Line 5
818     ++counter;        // Line 6   BREAKPOINT
819 }                     // Line 7
820 int main() {          // Line 8
821     func();           // Line 9
822     return counter;   // Line 10
823 }                     // Line 11
824 )");
825     // Try stepping out with no breakpoint set; we will step out.
826     SkSL::SkVMDebugTracePlayer player;
827     player.reset(trace);
828     player.step();
829     REPORTER_ASSERT(r, player.getCurrentLine() == 9);
830 
831     player.step();
832     REPORTER_ASSERT(r, player.getCurrentLine() == 4);
833 
834     player.stepOut();
835     REPORTER_ASSERT(r, player.getCurrentLine() == 9);
836 
837     // Try stepping out with a breakpoint set; we will stop at the breakpoint.
838     player.reset(trace);
839     player.setBreakpoints(std::unordered_set<int>{6});
840     player.step();
841     REPORTER_ASSERT(r, player.getCurrentLine() == 9);
842 
843     player.step();
844     REPORTER_ASSERT(r, player.getCurrentLine() == 4);
845 
846     player.stepOut();
847     REPORTER_ASSERT(r, player.getCurrentLine() == 6);
848 }
849