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