Coverage Report

Created: 2025-12-31 06:11

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/perfetto/test/test_helper.cc
Line
Count
Source
1
/*
2
 * Copyright (C) 2018 The Android Open Source Project
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
17
#include "test/test_helper.h"
18
#include <string>
19
20
#include "perfetto/base/compiler.h"
21
#include "perfetto/ext/base/string_utils.h"
22
#include "perfetto/ext/tracing/core/trace_packet.h"
23
#include "perfetto/tracing/core/tracing_service_state.h"
24
#include "perfetto/tracing/default_socket.h"
25
26
#include "protos/perfetto/trace/trace_packet.pbzero.h"
27
28
namespace perfetto {
29
30
namespace {
31
322
const char* ProducerSocketForMode(TestHelper::Mode mode) {
32
322
#if !PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
33
322
  base::ignore_result(mode);
34
322
  return ::perfetto::GetProducerSocket();
35
#else
36
  switch (mode) {
37
    case TestHelper::Mode::kStartDaemons:
38
      return "/data/local/tmp/traced_producer";
39
    case TestHelper::Mode::kUseSystemService:
40
      return ::perfetto::GetProducerSocket();
41
  }
42
#endif
43
322
}
44
45
311
const char* ConsumerSocketForMode(TestHelper::Mode mode) {
46
311
#if !PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
47
311
  base::ignore_result(mode);
48
311
  return ::perfetto::GetConsumerSocket();
49
#else
50
  switch (mode) {
51
    case TestHelper::Mode::kStartDaemons:
52
      return "/data/local/tmp/traced_consumer";
53
    case TestHelper::Mode::kUseSystemService:
54
      return ::perfetto::GetConsumerSocket();
55
  }
56
#endif
57
311
}
58
}  // namespace
59
60
uint64_t TestHelper::next_instance_num_ = 0;
61
#if PERFETTO_BUILDFLAG(PERFETTO_START_DAEMONS)
62
TestHelper::Mode TestHelper::kDefaultMode = Mode::kStartDaemons;
63
#else
64
TestHelper::Mode TestHelper::kDefaultMode = Mode::kUseSystemService;
65
#endif
66
67
TestHelper::TestHelper(base::TestTaskRunner* task_runner, Mode mode)
68
311
    : TestHelper(task_runner, mode, ProducerSocketForMode(mode)) {}
69
70
TestHelper::TestHelper(base::TestTaskRunner* task_runner,
71
                       Mode mode,
72
                       const char* producer_socket,
73
                       bool enable_relay_endpoint)
74
311
    : instance_num_(next_instance_num_++),
75
311
      task_runner_(task_runner),
76
311
      mode_(mode),
77
311
      producer_socket_(producer_socket),
78
311
      consumer_socket_(ConsumerSocketForMode(mode)),
79
311
      service_thread_(producer_socket_,
80
311
                      consumer_socket_,
81
311
                      enable_relay_endpoint) {
82
311
  auto producer_sockets = TokenizeProducerSockets(producer_socket_);
83
311
  static constexpr const char* kDefaultFakeProducerName =
84
311
      "android.perfetto.FakeProducer";
85
622
  for (size_t i = 0; i < producer_sockets.size(); i++) {
86
311
    auto cp_connect = "producer." + std::to_string(i) + ".connect";
87
311
    auto cp_setup = "producer." + std::to_string(i) + ".setup";
88
311
    auto cp_enabled = "producer." + std::to_string(i) + ".enabled";
89
311
    std::string producer_name =
90
311
        (!!i) ? +kDefaultFakeProducerName + std::string(".") + std::to_string(i)
91
311
              : kDefaultFakeProducerName;
92
311
    fake_producer_threads_.emplace_back(std::make_unique<FakeProducerThread>(
93
311
        producer_sockets[i], WrapTask(CreateCheckpoint(cp_connect)),
94
311
        WrapTask(CreateCheckpoint(cp_setup)),
95
311
        WrapTask(CreateCheckpoint(cp_enabled)), producer_name));
96
311
  }
97
311
}
98
99
300
void TestHelper::OnConnect() {
100
300
  endpoint_->ObserveEvents(ObservableEvents::TYPE_ALL_DATA_SOURCES_STARTED);
101
300
  std::move(on_connect_callback_)();
102
300
}
103
104
0
void TestHelper::OnDisconnect() {
105
0
  PERFETTO_FATAL("Consumer unexpectedly disconnected from the service");
106
0
}
107
108
0
void TestHelper::OnTracingDisabled(const std::string& /*error*/) {
109
0
  std::move(on_stop_tracing_callback_)();
110
0
  on_stop_tracing_callback_ = nullptr;
111
0
}
112
113
0
void TestHelper::ReadTraceData(std::vector<TracePacket> packets) {
114
0
  for (auto& encoded_packet : packets) {
115
0
    protos::gen::TracePacket packet;
116
0
    PERFETTO_CHECK(
117
0
        packet.ParseFromString(encoded_packet.GetRawBytesForTesting()));
118
0
    full_trace_.push_back(packet);
119
0
    if (packet.has_clock_snapshot() || packet.has_trace_uuid() ||
120
0
        packet.has_trace_config() || packet.has_trace_stats() ||
121
0
        !packet.synchronization_marker().empty() || packet.has_system_info() ||
122
0
        packet.has_service_event()) {
123
0
      continue;
124
0
    }
125
0
    PERFETTO_CHECK(packet.has_trusted_uid());
126
0
    trace_.push_back(std::move(packet));
127
0
  }
128
0
}
129
130
300
void TestHelper::OnTraceData(std::vector<TracePacket> packets, bool has_more) {
131
300
  ReadTraceData(std::move(packets));
132
300
  if (!has_more) {
133
300
    std::move(on_packets_finished_callback_)();
134
300
  }
135
300
}
136
137
311
void TestHelper::StartServiceIfRequired() {
138
311
  if (mode_ == Mode::kStartDaemons)
139
311
    env_cleaner_ = service_thread_.Start();
140
311
}
141
142
0
void TestHelper::RestartService() {
143
0
  PERFETTO_CHECK(mode_ == Mode::kStartDaemons);
144
0
  service_thread_.Stop();
145
0
  service_thread_.Start();
146
0
}
147
148
0
FakeProducer* TestHelper::ConnectFakeProducer(size_t idx) {
149
0
  fake_producer_threads_[idx]->Connect();
150
  // This will wait until the service has seen the RegisterDataSource() call
151
  // (because of the Sync() in FakeProducer::OnConnect()).
152
0
  RunUntilCheckpoint("producer." + std::to_string(idx) + ".connect");
153
0
  return fake_producer_threads_[idx]->producer();
154
0
}
155
156
300
void TestHelper::ConnectConsumer() {
157
300
  cur_consumer_num_++;
158
300
  on_connect_callback_ = CreateCheckpoint("consumer.connected." +
159
300
                                          std::to_string(cur_consumer_num_));
160
300
  endpoint_ = ConsumerIPCClient::Connect(consumer_socket_, this, task_runner_);
161
300
}
162
163
0
void TestHelper::DetachConsumer(const std::string& key) {
164
0
  on_detach_callback_ = CreateCheckpoint("detach." + key);
165
0
  endpoint_->Detach(key);
166
0
  RunUntilCheckpoint("detach." + key);
167
0
  endpoint_.reset();
168
0
}
169
170
0
bool TestHelper::AttachConsumer(const std::string& key) {
171
0
  bool success = false;
172
0
  auto checkpoint = CreateCheckpoint("attach." + key);
173
0
  on_attach_callback_ = [&success, checkpoint](bool s) {
174
0
    success = s;
175
0
    checkpoint();
176
0
  };
177
0
  endpoint_->Attach(key);
178
0
  RunUntilCheckpoint("attach." + key);
179
0
  return success;
180
0
}
181
182
0
void TestHelper::CreateProducerProvidedSmb() {
183
0
  for (auto& thread : fake_producer_threads_)
184
0
    thread->CreateProducerProvidedSmb();
185
0
}
186
187
0
bool TestHelper::IsShmemProvidedByProducer(size_t i) {
188
0
  return fake_producer_threads_[i]->producer()->IsShmemProvidedByProducer();
189
0
}
190
191
void TestHelper::ProduceStartupEventBatch(
192
0
    const protos::gen::TestConfig& config) {
193
0
  for (size_t i = 0; i < fake_producer_threads_.size(); i++) {
194
0
    auto checkpoint_name =
195
0
        base::StackString<32>("startup_data_written.%zu", i).ToStdString();
196
0
    auto on_data_written = CreateCheckpoint(checkpoint_name);
197
0
    fake_producer_threads_[i]->ProduceStartupEventBatch(
198
0
        config, WrapTask(on_data_written));
199
0
    RunUntilCheckpoint(checkpoint_name);
200
0
  }
201
0
}
202
203
void TestHelper::StartTracing(const TraceConfig& config,
204
300
                              base::ScopedFile file) {
205
300
  PERFETTO_CHECK(!on_stop_tracing_callback_);
206
300
  trace_.clear();
207
300
  on_stop_tracing_callback_ =
208
300
      CreateCheckpoint("stop.tracing" + std::to_string(++trace_count_));
209
300
  on_all_ds_started_callback_ = CreateCheckpoint("all.datasources.started" +
210
300
                                                 std::to_string(trace_count_));
211
212
300
  endpoint_->EnableTracing(config, std::move(file));
213
300
}
214
215
0
void TestHelper::DisableTracing() {
216
0
  endpoint_->DisableTracing();
217
0
}
218
219
0
void TestHelper::FlushAndWait(uint32_t timeout_ms, FlushFlags flush_flags) {
220
0
  static int flush_num = 0;
221
0
  std::string checkpoint_name = "flush." + std::to_string(flush_num++);
222
0
  auto checkpoint = CreateCheckpoint(checkpoint_name);
223
0
  endpoint_->Flush(
224
0
      timeout_ms, [checkpoint](bool) { checkpoint(); }, flush_flags);
225
0
  RunUntilCheckpoint(checkpoint_name, timeout_ms + 1000);
226
0
}
227
228
300
void TestHelper::ReadData(uint32_t read_count) {
229
300
  on_packets_finished_callback_ =
230
300
      CreateCheckpoint("readback.complete." + std::to_string(read_count));
231
300
  endpoint_->ReadBuffers();
232
300
}
233
234
0
void TestHelper::FreeBuffers() {
235
0
  endpoint_->FreeBuffers();
236
0
}
237
238
300
void TestHelper::WaitForConsumerConnect() {
239
300
  RunUntilCheckpoint("consumer.connected." + std::to_string(cur_consumer_num_));
240
300
}
241
242
0
void TestHelper::WaitForProducerSetup(size_t idx) {
243
0
  RunUntilCheckpoint("producer." + std::to_string(idx) + ".setup");
244
0
}
245
246
0
void TestHelper::WaitForProducerEnabled(size_t idx) {
247
0
  RunUntilCheckpoint("producer." + std::to_string(idx) + ".enabled");
248
0
}
249
250
0
void TestHelper::WaitForTracingDisabled(uint32_t timeout_ms) {
251
0
  RunUntilCheckpoint("stop.tracing" + std::to_string(trace_count_), timeout_ms);
252
0
}
253
254
0
void TestHelper::WaitForAllDataSourceStarted(uint32_t timeout_ms) {
255
0
  RunUntilCheckpoint("all.datasources.started" + std::to_string(trace_count_),
256
0
                     timeout_ms);
257
0
}
258
259
300
void TestHelper::WaitForReadData(uint32_t read_count, uint32_t timeout_ms) {
260
300
  RunUntilCheckpoint("readback.complete." + std::to_string(read_count),
261
300
                     timeout_ms);
262
300
}
263
264
void TestHelper::WaitFor(std::function<bool()> predicate,
265
                         const std::string& error_msg,
266
0
                         uint32_t timeout_ms) {
267
0
  int64_t deadline_ms = base::GetWallTimeMs().count() + timeout_ms;
268
0
  while (base::GetWallTimeMs().count() < deadline_ms) {
269
0
    if (predicate())
270
0
      return;
271
0
    base::SleepMicroseconds(500 * 1000);  // 0.5 s.
272
0
  }
273
0
  PERFETTO_FATAL("Test timed out waiting for: %s", error_msg.c_str());
274
0
}
275
276
0
void TestHelper::WaitForDataSourceConnected(const std::string& ds_name) {
277
0
  auto predicate = [&] {
278
0
    auto dss = QueryServiceStateAndWait().data_sources();
279
0
    return std::any_of(dss.begin(), dss.end(),
280
0
                       [&](const TracingServiceState::DataSource& ds) {
281
0
                         return ds.ds_descriptor().name() == ds_name;
282
0
                       });
283
0
  };
284
0
  WaitFor(predicate, "connection of data source " + ds_name);
285
0
}
286
287
0
void TestHelper::SyncAndWaitProducer(size_t idx) {
288
0
  static int sync_id = 0;
289
0
  std::string checkpoint_name =
290
0
      "producer_sync_" + std::to_string(idx) + "_" + std::to_string(++sync_id);
291
0
  auto checkpoint = CreateCheckpoint(checkpoint_name);
292
0
  fake_producer_threads_[idx]->producer()->Sync(
293
0
      [this, &checkpoint] { task_runner_->PostTask(checkpoint); });
294
0
  RunUntilCheckpoint(checkpoint_name);
295
0
}
296
297
0
TracingServiceState TestHelper::QueryServiceStateAndWait() {
298
0
  TracingServiceState res;
299
0
  static int n = 0;
300
0
  std::string checkpoint_name = "query_svc_state_" + std::to_string(n++);
301
0
  auto checkpoint = CreateCheckpoint(checkpoint_name);
302
0
  auto callback = [&checkpoint, &res](bool, const TracingServiceState& tss) {
303
0
    res = tss;
304
0
    checkpoint();
305
0
  };
306
0
  endpoint_->QueryServiceState({}, callback);
307
0
  RunUntilCheckpoint(checkpoint_name);
308
0
  return res;
309
0
}
310
311
std::function<void()> TestHelper::WrapTask(
312
1.23k
    const std::function<void()>& function) {
313
1.23k
  return [this, function] { task_runner_->PostTask(function); };
314
1.23k
}
315
316
0
void TestHelper::OnDetach(bool) {
317
0
  if (on_detach_callback_)
318
0
    std::move(on_detach_callback_)();
319
0
}
320
321
0
void TestHelper::OnAttach(bool success, const TraceConfig&) {
322
0
  if (on_attach_callback_)
323
0
    std::move(on_attach_callback_)(success);
324
0
}
325
326
0
void TestHelper::OnTraceStats(bool, const TraceStats&) {}
327
328
300
void TestHelper::OnObservableEvents(const ObservableEvents& events) {
329
300
  if (events.all_data_sources_started())
330
300
    std::move(on_all_ds_started_callback_)();
331
300
}
332
333
0
void TestHelper::OnSessionCloned(const OnSessionClonedArgs&) {}
334
335
// static
336
0
const char* TestHelper::GetDefaultModeConsumerSocketName() {
337
0
  return ConsumerSocketForMode(TestHelper::kDefaultMode);
338
0
}
339
340
// static
341
11
const char* TestHelper::GetDefaultModeProducerSocketName() {
342
11
  return ProducerSocketForMode(TestHelper::kDefaultMode);
343
11
}
344
345
}  // namespace perfetto