skia2/tests/SkVMDebugTraceTest.cpp
John Stiles 72941b87f0 Group arrays/structs together in the variable pane while debugging.
SkVMSlotInfo now contains a "group index" field in each slot. The
group index starts at zero for the first slot of a variable and
increases by 1 for each slot associated with that variable.

For simple types, this group index will always match the component
index. (This is by far the common case, so the groupIndex field is
omitted from the JSON if the indices match.) For more complicated
types--structs, arrays, or nested combinations thereof--it gives us
a simple way to find the start and end slot of a variable. For a given
slot, we can identify the associated variable's initial slot by
subtracting its group index, and we can identify the last slot of any
variable by walking forward and looking for a group index of zero
(indicating the start of a new, different variable).

Change-Id: Iaa71c89ba470a4f9640206dab0774096a7467cce
Bug: skia:12906
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/506317
Auto-Submit: John Stiles <johnstiles@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
2022-02-09 18:16:29 +00:00

177 lines
7.8 KiB
C++

/*
* Copyright 2021 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "include/core/SkStream.h"
#include "src/sksl/tracing/SkVMDebugTrace.h"
#include "tests/Test.h"
DEF_TEST(SkVMDebugTraceSetSource, r) {
SkSL::SkVMDebugTrace i;
i.setSource("SkVMDebugTrace::setSource unit test\n"
"\t// first line\n"
"\t// second line\n"
"\t// third line");
REPORTER_ASSERT(r, i.fSource.size() == 4);
REPORTER_ASSERT(r, i.fSource[0] == "SkVMDebugTrace::setSource unit test");
REPORTER_ASSERT(r, i.fSource[1] == "\t// first line");
REPORTER_ASSERT(r, i.fSource[2] == "\t// second line");
REPORTER_ASSERT(r, i.fSource[3] == "\t// third line");
}
DEF_TEST(SkVMDebugTraceSetSourceReplacesExistingText, r) {
SkSL::SkVMDebugTrace i;
i.setSource("One");
i.setSource("Two");
i.setSource("Three");
REPORTER_ASSERT(r, i.fSource.size() == 1);
REPORTER_ASSERT(r, i.fSource[0] == "Three");
}
DEF_TEST(SkVMDebugTraceWrite, r) {
SkSL::SkVMDebugTrace i;
i.fSource = {
"\t// first line",
"// \"second line\"",
"//\\\\//\\\\ third line",
};
i.fSlotInfo = {
{"SkVM_DebugTrace", 1, 2, 3, 4, (SkSL::Type::NumberKind)5, 6, -1},
{"Unit_Test", 6, 7, 8, 8, (SkSL::Type::NumberKind)10, 11, 12},
};
i.fFuncInfo = {
{"void testFunc();"},
};
i.fTraceInfo = {
{SkSL::SkVMTraceInfo::Op::kEnter, {0, 0}},
{SkSL::SkVMTraceInfo::Op::kLine, {5, 0}},
{SkSL::SkVMTraceInfo::Op::kVar, {10, 15}},
{SkSL::SkVMTraceInfo::Op::kExit, {20, 0}},
};
SkDynamicMemoryWStream wstream;
i.writeTrace(&wstream);
sk_sp<SkData> trace = wstream.detachAsData();
static constexpr char kExpected[] =
R"({"version":"20220209","source":["\t// first line","// \"second line\"","//\\\\//\\)"
R"(\\ third line"],"slots":[{"name":"SkVM_DebugTrace","columns":1,"rows":2,"index":3,)"
R"("groupIdx":4,"kind":5,"line":6},{"name":"Unit_Test","columns":6,"rows":7,"index":8)"
R"(,"kind":10,"line":11,"retval":12}],"functions":[{"name":"void testFunc();"}],"trac)"
R"(e":[[2],[0,5],[1,10,15],[3,20]]})";
std::string_view actual{reinterpret_cast<const char*>(trace->bytes()), trace->size()};
REPORTER_ASSERT(r, actual == kExpected,
"Expected:\n %s\n\n Actual:\n %.*s\n",
kExpected, (int)actual.size(), actual.data());
}
DEF_TEST(SkVMDebugTraceRead, r) {
const std::string_view kJSONTrace =
R"({"version":"20220209","source":["\t// first line","// \"second line\"","//\\\\//\\)"
R"(\\ third line"],"slots":[{"name":"SkVM_DebugTrace","columns":1,"rows":2,"index":3,)"
R"("groupIdx":4,"kind":5,"line":6},{"name":"Unit_Test","columns":6,"rows":7,"index":8)"
R"(,"kind":10,"line":11,"retval":12}],"functions":[{"name":"void testFunc();"}],"trac)"
R"(e":[[2],[0,5],[1,10,15],[3,20]]})";
SkMemoryStream stream(kJSONTrace.data(), kJSONTrace.size(), /*copyData=*/false);
SkSL::SkVMDebugTrace i;
REPORTER_ASSERT(r, i.readTrace(&stream));
REPORTER_ASSERT(r, i.fSource.size() == 3);
REPORTER_ASSERT(r, i.fSlotInfo.size() == 2);
REPORTER_ASSERT(r, i.fFuncInfo.size() == 1);
REPORTER_ASSERT(r, i.fTraceInfo.size() == 4);
REPORTER_ASSERT(r, i.fSource[0] == "\t// first line");
REPORTER_ASSERT(r, i.fSource[1] == "// \"second line\"");
REPORTER_ASSERT(r, i.fSource[2] == "//\\\\//\\\\ third line");
REPORTER_ASSERT(r, i.fSlotInfo[0].name == "SkVM_DebugTrace");
REPORTER_ASSERT(r, i.fSlotInfo[0].columns == 1);
REPORTER_ASSERT(r, i.fSlotInfo[0].rows == 2);
REPORTER_ASSERT(r, i.fSlotInfo[0].componentIndex == 3);
REPORTER_ASSERT(r, i.fSlotInfo[0].groupIndex == 4);
REPORTER_ASSERT(r, i.fSlotInfo[0].numberKind == (SkSL::Type::NumberKind)5);
REPORTER_ASSERT(r, i.fSlotInfo[0].line == 6);
REPORTER_ASSERT(r, i.fSlotInfo[0].fnReturnValue == -1);
REPORTER_ASSERT(r, i.fSlotInfo[1].name == "Unit_Test");
REPORTER_ASSERT(r, i.fSlotInfo[1].columns == 6);
REPORTER_ASSERT(r, i.fSlotInfo[1].rows == 7);
REPORTER_ASSERT(r, i.fSlotInfo[1].componentIndex == 8);
REPORTER_ASSERT(r, i.fSlotInfo[1].groupIndex == 8);
REPORTER_ASSERT(r, i.fSlotInfo[1].numberKind == (SkSL::Type::NumberKind)10);
REPORTER_ASSERT(r, i.fSlotInfo[1].line == 11);
REPORTER_ASSERT(r, i.fSlotInfo[1].fnReturnValue == 12);
REPORTER_ASSERT(r, i.fFuncInfo[0].name == "void testFunc();");
REPORTER_ASSERT(r, i.fTraceInfo[0].op == SkSL::SkVMTraceInfo::Op::kEnter);
REPORTER_ASSERT(r, i.fTraceInfo[0].data[0] == 0);
REPORTER_ASSERT(r, i.fTraceInfo[0].data[1] == 0);
REPORTER_ASSERT(r, i.fTraceInfo[1].op == SkSL::SkVMTraceInfo::Op::kLine);
REPORTER_ASSERT(r, i.fTraceInfo[1].data[0] == 5);
REPORTER_ASSERT(r, i.fTraceInfo[1].data[1] == 0);
REPORTER_ASSERT(r, i.fTraceInfo[2].op == SkSL::SkVMTraceInfo::Op::kVar);
REPORTER_ASSERT(r, i.fTraceInfo[2].data[0] == 10);
REPORTER_ASSERT(r, i.fTraceInfo[2].data[1] == 15);
REPORTER_ASSERT(r, i.fTraceInfo[3].op == SkSL::SkVMTraceInfo::Op::kExit);
REPORTER_ASSERT(r, i.fTraceInfo[3].data[0] == 20);
REPORTER_ASSERT(r, i.fTraceInfo[3].data[1] == 0);
}
DEF_TEST(SkVMDebugTraceGetSlotComponentSuffix, r) {
// SkVMSlotInfo fields:
// - name
// - columns
// - rows
// - componentIndex
// - numberKind
// - line
// - fnReturnValue
SkSL::SkVMDebugTrace i;
i.fSlotInfo = {{"s", 1, 1, 0, 0, SkSL::Type::NumberKind::kFloat, 0, -1},
{"v", 4, 1, 0, 0, SkSL::Type::NumberKind::kFloat, 0, -1},
{"v", 4, 1, 1, 1, SkSL::Type::NumberKind::kFloat, 0, -1},
{"v", 4, 1, 2, 2, SkSL::Type::NumberKind::kFloat, 0, -1},
{"v", 4, 1, 3, 3, SkSL::Type::NumberKind::kFloat, 0, -1},
{"m", 4, 4, 0, 0, SkSL::Type::NumberKind::kFloat, 0, -1},
{"m", 4, 4, 1, 1, SkSL::Type::NumberKind::kFloat, 0, -1},
{"m", 4, 4, 2, 2, SkSL::Type::NumberKind::kFloat, 0, -1},
{"m", 4, 4, 3, 3, SkSL::Type::NumberKind::kFloat, 0, -1},
{"m", 4, 4, 4, 4, SkSL::Type::NumberKind::kFloat, 0, -1},
{"m", 4, 4, 5, 5, SkSL::Type::NumberKind::kFloat, 0, -1},
{"m", 4, 4, 6, 6, SkSL::Type::NumberKind::kFloat, 0, -1},
{"m", 4, 4, 7, 7, SkSL::Type::NumberKind::kFloat, 0, -1},
{"m", 4, 4, 8, 8, SkSL::Type::NumberKind::kFloat, 0, -1},
{"m", 4, 4, 9, 9, SkSL::Type::NumberKind::kFloat, 0, -1},
{"m", 4, 4, 10, 10, SkSL::Type::NumberKind::kFloat, 0, -1},
{"m", 4, 4, 11, 11, SkSL::Type::NumberKind::kFloat, 0, -1},
{"m", 4, 4, 12, 12, SkSL::Type::NumberKind::kFloat, 0, -1},
{"m", 4, 4, 13, 13, SkSL::Type::NumberKind::kFloat, 0, -1},
{"m", 4, 4, 14, 14, SkSL::Type::NumberKind::kFloat, 0, -1},
{"m", 4, 4, 15, 15, SkSL::Type::NumberKind::kFloat, 0, -1}};
const std::string kExpected[] = {"",
".x", ".y", ".z", ".w",
"[0][0]", "[0][1]", "[0][2]", "[0][3]",
"[1][0]", "[1][1]", "[1][2]", "[1][3]",
"[2][0]", "[2][1]", "[2][2]", "[2][3]",
"[3][0]", "[3][1]", "[3][2]", "[3][3]"};
REPORTER_ASSERT(r, i.fSlotInfo.size() == SK_ARRAY_COUNT(kExpected));
for (size_t index = 0; index < SK_ARRAY_COUNT(kExpected); ++index) {
REPORTER_ASSERT(r, kExpected[index] == i.getSlotComponentSuffix(index));
}
}