1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
base / test / test_trace_processor_impl.cc [blame]
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "test_trace_processor_impl.h"
#include <sstream>
#include "third_party/perfetto/include/perfetto/trace_processor/trace_processor.h"
namespace base::test {
QueryResultOrError::QueryResultOrError(const QueryResult& result)
: result_(result) {}
QueryResultOrError::QueryResultOrError(const std::string& error)
: error_(error) {}
QueryResultOrError::~QueryResultOrError() = default;
TestTraceProcessorImpl::TestTraceProcessorImpl() {
config_ = std::make_unique<perfetto::trace_processor::Config>();
trace_processor_ =
perfetto::trace_processor::TraceProcessor::CreateInstance(*config_);
}
TestTraceProcessorImpl::~TestTraceProcessorImpl() = default;
TestTraceProcessorImpl::TestTraceProcessorImpl(TestTraceProcessorImpl&& other) =
default;
TestTraceProcessorImpl& TestTraceProcessorImpl::operator=(
TestTraceProcessorImpl&& other) = default;
QueryResultOrError TestTraceProcessorImpl::ExecuteQuery(
const std::string& sql) const {
QueryResultOrError::QueryResult result;
auto it = trace_processor_->ExecuteQuery(sql);
// Write column names.
std::vector<std::string> column_names;
for (uint32_t c = 0; c < it.ColumnCount(); ++c) {
column_names.push_back(it.GetColumnName(c));
}
result.push_back(column_names);
// Write rows.
while (it.Next()) {
std::vector<std::string> row;
for (uint32_t c = 0; c < it.ColumnCount(); ++c) {
perfetto::trace_processor::SqlValue sql_value = it.Get(c);
std::ostringstream ss;
switch (sql_value.type) {
case perfetto::trace_processor::SqlValue::Type::kLong:
ss << sql_value.AsLong();
row.push_back(ss.str());
break;
case perfetto::trace_processor::SqlValue::Type::kDouble:
ss << sql_value.AsDouble();
row.push_back(ss.str());
break;
case perfetto::trace_processor::SqlValue::Type::kString:
row.push_back(sql_value.AsString());
break;
case perfetto::trace_processor::SqlValue::Type::kBytes:
row.push_back("<raw bytes>");
break;
case perfetto::trace_processor::SqlValue::Type::kNull:
row.push_back("[NULL]");
break;
default:
row.push_back("unknown");
}
}
result.push_back(row);
}
if (!it.Status().ok()) {
return QueryResultOrError(it.Status().message());
}
return QueryResultOrError(result);
}
absl::Status TestTraceProcessorImpl::ParseTrace(
const std::vector<char>& raw_trace) {
auto status =
trace_processor_->Parse(perfetto::trace_processor::TraceBlobView(
perfetto::trace_processor::TraceBlob::CopyFrom(raw_trace.data(),
raw_trace.size())));
// TODO(rasikan): Add DCHECK that the trace is well-formed and parsing doesn't
// have any errors (e.g. to catch the cases when someone emits overlapping
// trace events on the same track).
if (!status.ok()) {
return absl::UnknownError(status.message());
}
status = trace_processor_->NotifyEndOfFile();
return status.ok() ? absl::OkStatus() : absl::UnknownError(status.message());
}
absl::Status TestTraceProcessorImpl::OverrideSqlModule(
const std::string& module_name,
const TestTraceProcessorImpl::PerfettoSQLModule& module) {
auto status =
trace_processor_->RegisterSqlModule({module_name, module, true});
return status.ok() ? absl::OkStatus() : absl::UnknownError(status.message());
}
} // namespace base::test