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 "src/base/SkArenaAlloc.h"
10 #include "src/core/SkRasterPipeline.h"
11 #include "src/sksl/SkSLCompiler.h"
12 #include "src/sksl/SkSLProgramKind.h"
13 #include "src/sksl/SkSLProgramSettings.h"
14 #include "src/sksl/SkSLString.h"
15 #include "src/sksl/SkSLUtil.h"
16 #include "src/sksl/codegen/SkSLRasterPipelineBuilder.h"
17 #include "src/sksl/codegen/SkSLRasterPipelineCodeGenerator.h"
18 #include "src/sksl/ir/SkSLFunctionDeclaration.h"
19 #include "src/sksl/ir/SkSLProgram.h" // IWYU pragma: keep
20 #include "src/sksl/tracing/SkSLDebugTracePlayer.h"
21 #include "src/sksl/tracing/SkSLDebugTracePriv.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 <utility>
30 #include <vector>
31
32 using LineNumberMap = SkSL::SkSLDebugTracePlayer::LineNumberMap;
33
make_trace(skiatest::Reporter * r,std::string src)34 static sk_sp<SkSL::DebugTracePriv> make_trace(skiatest::Reporter* r,
35 std::string src) {
36 auto debugTrace = sk_make_sp<SkSL::DebugTracePriv>();
37
38 SkSL::Compiler compiler;
39 SkSL::ProgramSettings settings;
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");
48 REPORTER_ASSERT(r, 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
make_stack_string(const SkSL::DebugTracePriv & trace,const SkSL::SkSLDebugTracePlayer & player)74 static 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
make_vars_string(const SkSL::DebugTracePriv & trace,const std::vector<SkSL::SkSLDebugTracePlayer::VariableData> & vars)93 static 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();
98 for (const SkSL::SkSLDebugTracePlayer::VariableData& var : vars) {
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
make_local_vars_string(const SkSL::DebugTracePriv & trace,const SkSL::SkSLDebugTracePlayer & player)117 static 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
make_global_vars_string(const SkSL::DebugTracePriv & trace,const SkSL::SkSLDebugTracePlayer & player)123 static 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
DEF_TEST(SkSLTracePlayerCanResetToNull,r)128 DEF_TEST(SkSLTracePlayerCanResetToNull, r) {
129 SkSL::SkSLDebugTracePlayer player;
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);
135 REPORTER_ASSERT(r, player.traceHasCompleted());
136 REPORTER_ASSERT(r, player.getCallStack().empty());
137 REPORTER_ASSERT(r, player.getGlobalVariables().empty());
138 REPORTER_ASSERT(r, player.getLineNumbersReached().empty());
139 }
140
DEF_TEST(SkSLTracePlayerHelloWorld,r)141 DEF_TEST(SkSLTracePlayerHelloWorld, r) {
142 sk_sp<SkSL::DebugTracePriv> trace = make_trace(r,
143 R"( // Line 1
144 half4 main(float2 xy) { // Line 2
145 return half4(2 + 2); // Line 3
146 } // Line 4
147 )");
148 SkSL::SkSLDebugTracePlayer player;
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);
154 REPORTER_ASSERT(r, !player.traceHasCompleted());
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);
163 REPORTER_ASSERT(r, !player.traceHasCompleted());
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);
173 REPORTER_ASSERT(r, player.traceHasCompleted());
174 REPORTER_ASSERT(r, player.getCurrentLine() == -1);
175 REPORTER_ASSERT(r, player.getCallStack().empty());
176 REPORTER_ASSERT(r,
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
DEF_TEST(SkSLTracePlayerReset,r)182 DEF_TEST(SkSLTracePlayerReset, r) {
183 sk_sp<SkSL::DebugTracePriv> trace = make_trace(r,
184 R"( // Line 1
185 half4 main(float2 xy) { // Line 2
186 return half4(2 + 2); // Line 3
187 } // Line 4
188 )");
189 SkSL::SkSLDebugTracePlayer player;
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);
195 REPORTER_ASSERT(r, !player.traceHasCompleted());
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);
213 REPORTER_ASSERT(r, !player.traceHasCompleted());
214 REPORTER_ASSERT(r, player.getCallStack().empty());
215 REPORTER_ASSERT(r, player.getGlobalVariables().empty());
216 }
217
DEF_TEST(SkSLTracePlayerFunctions,r)218 DEF_TEST(SkSLTracePlayerFunctions, r) {
219 sk_sp<SkSL::DebugTracePriv> trace = make_trace(r,
220 R"( // Line 1
221 int fnB() { // Line 2
222 return 2 + 2; // Line 3
223 } // Line 4
224 int fnA() { // Line 5
225 return fnB(); // Line 6
226 } // Line 7
227 half4 main(float2 xy) { // Line 8
228 return half4(fnA()); // Line 9
229 } // Line 10
230 )");
231 SkSL::SkSLDebugTracePlayer player;
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);
237 REPORTER_ASSERT(r, !player.traceHasCompleted());
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.
245 REPORTER_ASSERT(r, !player.traceHasCompleted());
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.
254 REPORTER_ASSERT(r, player.traceHasCompleted());
255 REPORTER_ASSERT(r, player.getCurrentLine() == -1);
256 REPORTER_ASSERT(r, player.getCallStack().empty());
257 REPORTER_ASSERT(r,
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)");
267 REPORTER_ASSERT(r, player.getCurrentLineInStackFrame(0) == 9);
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()");
273 REPORTER_ASSERT(r, player.getCurrentLineInStackFrame(0) == 9);
274 REPORTER_ASSERT(r, player.getCurrentLineInStackFrame(1) == 6);
275 REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "");
276 REPORTER_ASSERT(r, make_global_vars_string(*trace, player) == "");
277 player.step();
278
279 REPORTER_ASSERT(
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) == "");
284 REPORTER_ASSERT(r, player.getCurrentLineInStackFrame(0) == 9);
285 REPORTER_ASSERT(r, player.getCurrentLineInStackFrame(1) == 6);
286 REPORTER_ASSERT(r, player.getCurrentLineInStackFrame(2) == 3);
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)");
295 REPORTER_ASSERT(
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();
301 REPORTER_ASSERT(r, player.traceHasCompleted());
302 REPORTER_ASSERT(r,
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
DEF_TEST(SkSLTracePlayerVariables,r)308 DEF_TEST(SkSLTracePlayerVariables, r) {
309 sk_sp<SkSL::DebugTracePriv> trace = make_trace(r,
310 R"( // Line 1
311 float func() { // Line 2
312 float x = 4, y = 5, z = 6; // Line 3
313 return z; // Line 4
314 } // Line 5
315 half4 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 )");
324 SkSL::SkSLDebugTracePlayer player;
325 player.reset(trace);
326
327 REPORTER_ASSERT(
328 r,
329 player.getLineNumbersReached() ==
330 LineNumberMap(
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)");
341 REPORTER_ASSERT(r,
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)");
347 REPORTER_ASSERT(r,
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);
353 REPORTER_ASSERT(r,
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);
359 REPORTER_ASSERT(r,
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)");
366 REPORTER_ASSERT(r,
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)");
373 REPORTER_ASSERT(
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)");
380 REPORTER_ASSERT(r,
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)");
388 REPORTER_ASSERT(r,
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();
397 REPORTER_ASSERT(r, player.traceHasCompleted());
398 REPORTER_ASSERT(r, make_stack_string(*trace, player) == "");
399 REPORTER_ASSERT(r,
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
DEF_TEST(SkSLTracePlayerVariableGroups,r)405 DEF_TEST(SkSLTracePlayerVariableGroups, r) {
406 sk_sp<SkSL::DebugTracePriv> trace = make_trace(r,
407 R"( // Line 1
408 struct S { int x, y, z; }; // Line 2
409 half4 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 )");
419 SkSL::SkSLDebugTracePlayer player;
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();
427
428 REPORTER_ASSERT(r, player.getCurrentLine() == 5);
429 REPORTER_ASSERT(r,
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);
435 REPORTER_ASSERT(r,
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);
442 REPORTER_ASSERT(r,
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);
449 REPORTER_ASSERT(r,
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);
456 REPORTER_ASSERT(r,
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);
463 REPORTER_ASSERT(r,
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
DEF_TEST(SkSLTracePlayerIfStatement,r)469 DEF_TEST(SkSLTracePlayerIfStatement, r) {
470 sk_sp<SkSL::DebugTracePriv> trace = make_trace(r,
471 R"( // Line 1
472 half4 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 )");
489 SkSL::SkSLDebugTracePlayer player;
490 player.reset(trace);
491
492 REPORTER_ASSERT(
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);
503 REPORTER_ASSERT(r,
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);
512 REPORTER_ASSERT(r,
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);
519 REPORTER_ASSERT(r,
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);
529 REPORTER_ASSERT(r,
530 make_local_vars_string(*trace, player) == "##val = 4, xy.x = 0.5, xy.y = 0.5");
531 player.step();
532
533 REPORTER_ASSERT(r, player.traceHasCompleted());
534 REPORTER_ASSERT(r,
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
DEF_TEST(SkSLTracePlayerForLoop,r)540 DEF_TEST(SkSLTracePlayerForLoop, r) {
541 sk_sp<SkSL::DebugTracePriv> trace = make_trace(r,
542 R"( // Line 1
543 half4 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 )");
551 SkSL::SkSLDebugTracePlayer player;
552 player.reset(trace);
553
554 REPORTER_ASSERT(
555 r, player.getLineNumbersReached() == LineNumberMap({{3, 1}, {4, 3}, {5, 2}, {7, 1}}));
556 player.step();
557
558 REPORTER_ASSERT(r, player.getCurrentLine() == 3);
559 REPORTER_ASSERT(
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);
565 REPORTER_ASSERT(
566 r, player.getLineNumbersReached() == LineNumberMap({{3, 0}, {4, 2}, {5, 2}, {7, 1}}));
567 REPORTER_ASSERT(r,
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);
572 REPORTER_ASSERT(
573 r, player.getLineNumbersReached() == LineNumberMap({{3, 0}, {4, 2}, {5, 1}, {7, 1}}));
574 REPORTER_ASSERT(
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);
580 REPORTER_ASSERT(
581 r, player.getLineNumbersReached() == LineNumberMap({{3, 0}, {4, 1}, {5, 1}, {7, 1}}));
582 REPORTER_ASSERT(
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);
588 REPORTER_ASSERT(
589 r, player.getLineNumbersReached() == LineNumberMap({{3, 0}, {4, 1}, {5, 0}, {7, 1}}));
590 REPORTER_ASSERT(
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
595 REPORTER_ASSERT(r, player.getCurrentLine() == 4);
596 REPORTER_ASSERT(
597 r, player.getLineNumbersReached() == LineNumberMap({{3, 0}, {4, 0}, {5, 0}, {7, 1}}));
598 REPORTER_ASSERT(
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);
604 REPORTER_ASSERT(
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
609 REPORTER_ASSERT(r, player.traceHasCompleted());
610 REPORTER_ASSERT(r,
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
DEF_TEST(SkSLTracePlayerStepOut,r)616 DEF_TEST(SkSLTracePlayerStepOut, r) {
617 sk_sp<SkSL::DebugTracePriv> trace = make_trace(r,
618 R"( // Line 1
619 int 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
626 half4 main(float2 xy) { // Line 9
627 return half4(fn()); // Line 10
628 } // Line 11
629 )");
630 SkSL::SkSLDebugTracePlayer player;
631 player.reset(trace);
632 REPORTER_ASSERT(r,
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)");
661 REPORTER_ASSERT(
662 r,
663 make_local_vars_string(*trace, player) == "##[fn].result = 44, xy.x = 0.5, xy.y = 0.5");
664 player.stepOut();
665
666 REPORTER_ASSERT(r, player.traceHasCompleted());
667 REPORTER_ASSERT(r,
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
DEF_TEST(SkSLTracePlayerVariableScope,r)673 DEF_TEST(SkSLTracePlayerVariableScope, r) {
674 sk_sp<SkSL::DebugTracePriv> trace = make_trace(r,
675 R"( // Line 1
676 half4 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 )");
697 SkSL::SkSLDebugTracePlayer player;
698 player.reset(trace);
699 REPORTER_ASSERT(r,
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);
722 REPORTER_ASSERT(
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);
727 REPORTER_ASSERT(
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);
736 REPORTER_ASSERT(
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);
741 REPORTER_ASSERT(r,
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);
747 REPORTER_ASSERT(r,
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);
753 REPORTER_ASSERT(
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);
758 REPORTER_ASSERT(r,
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
763 REPORTER_ASSERT(r, player.traceHasCompleted());
764 }
765
DEF_TEST(SkSLTracePlayerNestedBlocks,r)766 DEF_TEST(SkSLTracePlayerNestedBlocks, r) {
767 sk_sp<SkSL::DebugTracePriv> trace = make_trace(r,
768 R"( // Line 1
769 half4 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 )");
776 SkSL::SkSLDebugTracePlayer player;
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
786 REPORTER_ASSERT(r, player.traceHasCompleted());
787 }
788
DEF_TEST(SkSLTracePlayerSwitchStatement,r)789 DEF_TEST(SkSLTracePlayerSwitchStatement, r) {
790 sk_sp<SkSL::DebugTracePriv> trace = make_trace(r,
791 R"( // Line 1
792 half4 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 )");
806 SkSL::SkSLDebugTracePlayer player;
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
825 REPORTER_ASSERT(r, player.traceHasCompleted());
826 }
827
DEF_TEST(SkSLTracePlayerBreakpoint,r)828 DEF_TEST(SkSLTracePlayerBreakpoint, r) {
829 sk_sp<SkSL::DebugTracePriv> trace = make_trace(r,
830 R"( // Line 1
831 int counter = 0; // Line 2
832 void func() { // Line 3
833 --counter; // Line 4 BREAKPOINT 4 5
834 } // Line 5
835 half4 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.
846 SkSL::SkSLDebugTracePlayer player;
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();
870 REPORTER_ASSERT(r, player.traceHasCompleted());
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>{});
876 REPORTER_ASSERT(r, !player.traceHasCompleted());
877
878 player.run();
879 REPORTER_ASSERT(r, player.traceHasCompleted());
880 }
881
DEF_TEST(SkSLTracePlayerStepOverWithBreakpoint,r)882 DEF_TEST(SkSLTracePlayerStepOverWithBreakpoint, r) {
883 sk_sp<SkSL::DebugTracePriv> trace = make_trace(r,
884 R"( // Line 1
885 int counter = 0; // Line 2
886 void func() { // Line 3
887 ++counter; // Line 4 BREAKPOINT
888 } // Line 5
889 half4 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.
895 SkSL::SkSLDebugTracePlayer player;
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
DEF_TEST(SkSLTracePlayerStepOutWithBreakpoint,r)913 DEF_TEST(SkSLTracePlayerStepOutWithBreakpoint, r) {
914 sk_sp<SkSL::DebugTracePriv> trace = make_trace(r,
915 R"( // Line 1
916 int counter = 0; // Line 2
917 void func() { // Line 3
918 ++counter; // Line 4
919 ++counter; // Line 5
920 ++counter; // Line 6 BREAKPOINT
921 } // Line 7
922 half4 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.
928 SkSL::SkSLDebugTracePlayer player;
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 }
951