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