xref: /aosp_15_r20/external/perfetto/test/test_helper.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
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 {
ProducerSocketForMode(TestHelper::Mode mode)31 const char* ProducerSocketForMode(TestHelper::Mode mode) {
32 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
33   base::ignore_result(mode);
34   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 }
44 
ConsumerSocketForMode(TestHelper::Mode mode)45 const char* ConsumerSocketForMode(TestHelper::Mode mode) {
46 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
47   base::ignore_result(mode);
48   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 }
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 
TestHelper(base::TestTaskRunner * task_runner,Mode mode)67 TestHelper::TestHelper(base::TestTaskRunner* task_runner, Mode mode)
68     : TestHelper(task_runner, mode, ProducerSocketForMode(mode)) {}
69 
TestHelper(base::TestTaskRunner * task_runner,Mode mode,const char * producer_socket,bool enable_relay_endpoint)70 TestHelper::TestHelper(base::TestTaskRunner* task_runner,
71                        Mode mode,
72                        const char* producer_socket,
73                        bool enable_relay_endpoint)
74     : instance_num_(next_instance_num_++),
75       task_runner_(task_runner),
76       mode_(mode),
77       producer_socket_(producer_socket),
78       consumer_socket_(ConsumerSocketForMode(mode)),
79       service_thread_(producer_socket_,
80                       consumer_socket_,
81                       enable_relay_endpoint) {
82   auto producer_sockets = TokenizeProducerSockets(producer_socket_);
83   static constexpr const char* kDefaultFakeProducerName =
84       "android.perfetto.FakeProducer";
85   for (size_t i = 0; i < producer_sockets.size(); i++) {
86     auto cp_connect = "producer." + std::to_string(i) + ".connect";
87     auto cp_setup = "producer." + std::to_string(i) + ".setup";
88     auto cp_enabled = "producer." + std::to_string(i) + ".enabled";
89     std::string producer_name =
90         (!!i) ? +kDefaultFakeProducerName + std::string(".") + std::to_string(i)
91               : kDefaultFakeProducerName;
92     fake_producer_threads_.emplace_back(std::make_unique<FakeProducerThread>(
93         producer_sockets[i], WrapTask(CreateCheckpoint(cp_connect)),
94         WrapTask(CreateCheckpoint(cp_setup)),
95         WrapTask(CreateCheckpoint(cp_enabled)), producer_name));
96   }
97 }
98 
OnConnect()99 void TestHelper::OnConnect() {
100   endpoint_->ObserveEvents(ObservableEvents::TYPE_ALL_DATA_SOURCES_STARTED);
101   std::move(on_connect_callback_)();
102 }
103 
OnDisconnect()104 void TestHelper::OnDisconnect() {
105   PERFETTO_FATAL("Consumer unexpectedly disconnected from the service");
106 }
107 
OnTracingDisabled(const std::string &)108 void TestHelper::OnTracingDisabled(const std::string& /*error*/) {
109   std::move(on_stop_tracing_callback_)();
110   on_stop_tracing_callback_ = nullptr;
111 }
112 
ReadTraceData(std::vector<TracePacket> packets)113 void TestHelper::ReadTraceData(std::vector<TracePacket> packets) {
114   for (auto& encoded_packet : packets) {
115     protos::gen::TracePacket packet;
116     PERFETTO_CHECK(
117         packet.ParseFromString(encoded_packet.GetRawBytesForTesting()));
118     full_trace_.push_back(packet);
119     if (packet.has_clock_snapshot() || packet.has_trace_uuid() ||
120         packet.has_trace_config() || packet.has_trace_stats() ||
121         !packet.synchronization_marker().empty() || packet.has_system_info() ||
122         packet.has_service_event()) {
123       continue;
124     }
125     PERFETTO_CHECK(packet.has_trusted_uid());
126     trace_.push_back(std::move(packet));
127   }
128 }
129 
OnTraceData(std::vector<TracePacket> packets,bool has_more)130 void TestHelper::OnTraceData(std::vector<TracePacket> packets, bool has_more) {
131   ReadTraceData(std::move(packets));
132   if (!has_more) {
133     std::move(on_packets_finished_callback_)();
134   }
135 }
136 
StartServiceIfRequired()137 void TestHelper::StartServiceIfRequired() {
138   if (mode_ == Mode::kStartDaemons)
139     env_cleaner_ = service_thread_.Start();
140 }
141 
RestartService()142 void TestHelper::RestartService() {
143   PERFETTO_CHECK(mode_ == Mode::kStartDaemons);
144   service_thread_.Stop();
145   service_thread_.Start();
146 }
147 
ConnectFakeProducer(size_t idx)148 FakeProducer* TestHelper::ConnectFakeProducer(size_t idx) {
149   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   RunUntilCheckpoint("producer." + std::to_string(idx) + ".connect");
153   return fake_producer_threads_[idx]->producer();
154 }
155 
ConnectConsumer()156 void TestHelper::ConnectConsumer() {
157   cur_consumer_num_++;
158   on_connect_callback_ = CreateCheckpoint("consumer.connected." +
159                                           std::to_string(cur_consumer_num_));
160   endpoint_ = ConsumerIPCClient::Connect(consumer_socket_, this, task_runner_);
161 }
162 
DetachConsumer(const std::string & key)163 void TestHelper::DetachConsumer(const std::string& key) {
164   on_detach_callback_ = CreateCheckpoint("detach." + key);
165   endpoint_->Detach(key);
166   RunUntilCheckpoint("detach." + key);
167   endpoint_.reset();
168 }
169 
AttachConsumer(const std::string & key)170 bool TestHelper::AttachConsumer(const std::string& key) {
171   bool success = false;
172   auto checkpoint = CreateCheckpoint("attach." + key);
173   on_attach_callback_ = [&success, checkpoint](bool s) {
174     success = s;
175     checkpoint();
176   };
177   endpoint_->Attach(key);
178   RunUntilCheckpoint("attach." + key);
179   return success;
180 }
181 
CreateProducerProvidedSmb()182 void TestHelper::CreateProducerProvidedSmb() {
183   for (auto& thread : fake_producer_threads_)
184     thread->CreateProducerProvidedSmb();
185 }
186 
IsShmemProvidedByProducer(size_t i)187 bool TestHelper::IsShmemProvidedByProducer(size_t i) {
188   return fake_producer_threads_[i]->producer()->IsShmemProvidedByProducer();
189 }
190 
ProduceStartupEventBatch(const protos::gen::TestConfig & config)191 void TestHelper::ProduceStartupEventBatch(
192     const protos::gen::TestConfig& config) {
193   for (size_t i = 0; i < fake_producer_threads_.size(); i++) {
194     auto checkpoint_name =
195         base::StackString<32>("startup_data_written.%zu", i).ToStdString();
196     auto on_data_written = CreateCheckpoint(checkpoint_name);
197     fake_producer_threads_[i]->ProduceStartupEventBatch(
198         config, WrapTask(on_data_written));
199     RunUntilCheckpoint(checkpoint_name);
200   }
201 }
202 
StartTracing(const TraceConfig & config,base::ScopedFile file)203 void TestHelper::StartTracing(const TraceConfig& config,
204                               base::ScopedFile file) {
205   PERFETTO_CHECK(!on_stop_tracing_callback_);
206   trace_.clear();
207   on_stop_tracing_callback_ =
208       CreateCheckpoint("stop.tracing" + std::to_string(++trace_count_));
209   on_all_ds_started_callback_ = CreateCheckpoint("all.datasources.started" +
210                                                  std::to_string(trace_count_));
211 
212   endpoint_->EnableTracing(config, std::move(file));
213 }
214 
DisableTracing()215 void TestHelper::DisableTracing() {
216   endpoint_->DisableTracing();
217 }
218 
FlushAndWait(uint32_t timeout_ms,FlushFlags flush_flags)219 void TestHelper::FlushAndWait(uint32_t timeout_ms, FlushFlags flush_flags) {
220   static int flush_num = 0;
221   std::string checkpoint_name = "flush." + std::to_string(flush_num++);
222   auto checkpoint = CreateCheckpoint(checkpoint_name);
223   endpoint_->Flush(
224       timeout_ms, [checkpoint](bool) { checkpoint(); }, flush_flags);
225   RunUntilCheckpoint(checkpoint_name, timeout_ms + 1000);
226 }
227 
ReadData(uint32_t read_count)228 void TestHelper::ReadData(uint32_t read_count) {
229   on_packets_finished_callback_ =
230       CreateCheckpoint("readback.complete." + std::to_string(read_count));
231   endpoint_->ReadBuffers();
232 }
233 
FreeBuffers()234 void TestHelper::FreeBuffers() {
235   endpoint_->FreeBuffers();
236 }
237 
WaitForConsumerConnect()238 void TestHelper::WaitForConsumerConnect() {
239   RunUntilCheckpoint("consumer.connected." + std::to_string(cur_consumer_num_));
240 }
241 
WaitForProducerSetup(size_t idx)242 void TestHelper::WaitForProducerSetup(size_t idx) {
243   RunUntilCheckpoint("producer." + std::to_string(idx) + ".setup");
244 }
245 
WaitForProducerEnabled(size_t idx)246 void TestHelper::WaitForProducerEnabled(size_t idx) {
247   RunUntilCheckpoint("producer." + std::to_string(idx) + ".enabled");
248 }
249 
WaitForTracingDisabled(uint32_t timeout_ms)250 void TestHelper::WaitForTracingDisabled(uint32_t timeout_ms) {
251   RunUntilCheckpoint("stop.tracing" + std::to_string(trace_count_), timeout_ms);
252 }
253 
WaitForAllDataSourceStarted(uint32_t timeout_ms)254 void TestHelper::WaitForAllDataSourceStarted(uint32_t timeout_ms) {
255   RunUntilCheckpoint("all.datasources.started" + std::to_string(trace_count_),
256                      timeout_ms);
257 }
258 
WaitForReadData(uint32_t read_count,uint32_t timeout_ms)259 void TestHelper::WaitForReadData(uint32_t read_count, uint32_t timeout_ms) {
260   RunUntilCheckpoint("readback.complete." + std::to_string(read_count),
261                      timeout_ms);
262 }
263 
WaitFor(std::function<bool ()> predicate,const std::string & error_msg,uint32_t timeout_ms)264 void TestHelper::WaitFor(std::function<bool()> predicate,
265                          const std::string& error_msg,
266                          uint32_t timeout_ms) {
267   int64_t deadline_ms = base::GetWallTimeMs().count() + timeout_ms;
268   while (base::GetWallTimeMs().count() < deadline_ms) {
269     if (predicate())
270       return;
271     base::SleepMicroseconds(500 * 1000);  // 0.5 s.
272   }
273   PERFETTO_FATAL("Test timed out waiting for: %s", error_msg.c_str());
274 }
275 
WaitForDataSourceConnected(const std::string & ds_name)276 void TestHelper::WaitForDataSourceConnected(const std::string& ds_name) {
277   auto predicate = [&] {
278     auto dss = QueryServiceStateAndWait().data_sources();
279     return std::any_of(dss.begin(), dss.end(),
280                        [&](const TracingServiceState::DataSource& ds) {
281                          return ds.ds_descriptor().name() == ds_name;
282                        });
283   };
284   WaitFor(predicate, "connection of data source " + ds_name);
285 }
286 
SyncAndWaitProducer(size_t idx)287 void TestHelper::SyncAndWaitProducer(size_t idx) {
288   static int sync_id = 0;
289   std::string checkpoint_name =
290       "producer_sync_" + std::to_string(idx) + "_" + std::to_string(++sync_id);
291   auto checkpoint = CreateCheckpoint(checkpoint_name);
292   fake_producer_threads_[idx]->producer()->Sync(
293       [this, &checkpoint] { task_runner_->PostTask(checkpoint); });
294   RunUntilCheckpoint(checkpoint_name);
295 }
296 
QueryServiceStateAndWait()297 TracingServiceState TestHelper::QueryServiceStateAndWait() {
298   TracingServiceState res;
299   static int n = 0;
300   std::string checkpoint_name = "query_svc_state_" + std::to_string(n++);
301   auto checkpoint = CreateCheckpoint(checkpoint_name);
302   auto callback = [&checkpoint, &res](bool, const TracingServiceState& tss) {
303     res = tss;
304     checkpoint();
305   };
306   endpoint_->QueryServiceState({}, callback);
307   RunUntilCheckpoint(checkpoint_name);
308   return res;
309 }
310 
WrapTask(const std::function<void ()> & function)311 std::function<void()> TestHelper::WrapTask(
312     const std::function<void()>& function) {
313   return [this, function] { task_runner_->PostTask(function); };
314 }
315 
OnDetach(bool)316 void TestHelper::OnDetach(bool) {
317   if (on_detach_callback_)
318     std::move(on_detach_callback_)();
319 }
320 
OnAttach(bool success,const TraceConfig &)321 void TestHelper::OnAttach(bool success, const TraceConfig&) {
322   if (on_attach_callback_)
323     std::move(on_attach_callback_)(success);
324 }
325 
OnTraceStats(bool,const TraceStats &)326 void TestHelper::OnTraceStats(bool, const TraceStats&) {}
327 
OnObservableEvents(const ObservableEvents & events)328 void TestHelper::OnObservableEvents(const ObservableEvents& events) {
329   if (events.all_data_sources_started())
330     std::move(on_all_ds_started_callback_)();
331 }
332 
OnSessionCloned(const OnSessionClonedArgs &)333 void TestHelper::OnSessionCloned(const OnSessionClonedArgs&) {}
334 
335 // static
GetDefaultModeConsumerSocketName()336 const char* TestHelper::GetDefaultModeConsumerSocketName() {
337   return ConsumerSocketForMode(TestHelper::kDefaultMode);
338 }
339 
340 // static
GetDefaultModeProducerSocketName()341 const char* TestHelper::GetDefaultModeProducerSocketName() {
342   return ProducerSocketForMode(TestHelper::kDefaultMode);
343 }
344 
345 }  // namespace perfetto
346