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 #ifndef TEST_TEST_HELPER_H_
18 #define TEST_TEST_HELPER_H_
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <optional>
23
24 #include "perfetto/base/build_config.h"
25 #include "perfetto/ext/base/file_utils.h"
26 #include "perfetto/ext/base/scoped_file.h"
27 #include "perfetto/ext/base/subprocess.h"
28 #include "perfetto/ext/base/thread_task_runner.h"
29 #include "perfetto/ext/base/utils.h"
30 #include "perfetto/ext/tracing/core/consumer.h"
31 #include "perfetto/ext/tracing/core/shared_memory_arbiter.h"
32 #include "perfetto/ext/tracing/core/trace_packet.h"
33 #include "perfetto/ext/tracing/ipc/consumer_ipc_client.h"
34 #include "perfetto/ext/tracing/ipc/default_socket.h"
35 #include "perfetto/ext/tracing/ipc/service_ipc_host.h"
36 #include "perfetto/tracing/core/trace_config.h"
37 #include "src/base/test/test_task_runner.h"
38 #include "test/fake_producer.h"
39
40 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
41 #include "src/tracing/ipc/shared_memory_windows.h"
42 #else
43 #include <signal.h>
44
45 #include "src/traced/probes/probes_producer.h"
46 #include "src/tracing/ipc/posix_shared_memory.h"
47 #endif
48
49 #include "protos/perfetto/trace/trace_packet.gen.h"
50
51 namespace perfetto {
52
53 // This value has been bumped to 10s in Oct 2020 because the GCE-based emulator
54 // can be sensibly slower than real hw (more than 10x) and caused flakes.
55 // See bugs duped against b/171771440.
56 constexpr uint32_t kDefaultTestTimeoutMs = 30000;
57
GetTestProducerSockName()58 inline const char* GetTestProducerSockName() {
59 // If we're building on Android and starting the daemons ourselves,
60 // create the sockets in a world-writable location.
61 #if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) && \
62 PERFETTO_BUILDFLAG(PERFETTO_START_DAEMONS)
63 return "/data/local/tmp/traced_producer";
64 #else
65 return ::perfetto::GetProducerSocket();
66 #endif
67 }
68
69 // Captures the values of some environment variables when constructed and
70 // restores them when destroyed.
71 class TestEnvCleaner {
72 public:
TestEnvCleaner()73 TestEnvCleaner() {}
TestEnvCleaner(std::initializer_list<const char * > env_vars)74 TestEnvCleaner(std::initializer_list<const char*> env_vars) {
75 prev_state_.reserve(env_vars.size());
76 for (const char* name : env_vars) {
77 prev_state_.emplace_back();
78 Var& var = prev_state_.back();
79 var.name = name;
80 const char* prev_value = getenv(name);
81 if (prev_value) {
82 var.value.emplace(prev_value);
83 }
84 }
85 }
~TestEnvCleaner()86 ~TestEnvCleaner() { Clean(); }
87
88 TestEnvCleaner(const TestEnvCleaner&) = delete;
TestEnvCleaner(TestEnvCleaner && obj)89 TestEnvCleaner(TestEnvCleaner&& obj) noexcept { *this = std::move(obj); }
90 TestEnvCleaner& operator=(const TestEnvCleaner&) = delete;
91 TestEnvCleaner& operator=(TestEnvCleaner&& obj) noexcept {
92 PERFETTO_CHECK(prev_state_.empty());
93 this->prev_state_ = std::move(obj.prev_state_);
94 obj.prev_state_.clear();
95 return *this;
96 }
97
Clean()98 void Clean() {
99 for (const Var& var : prev_state_) {
100 if (var.value) {
101 base::SetEnv(var.name, *var.value);
102 } else {
103 base::UnsetEnv(var.name);
104 }
105 }
106 prev_state_.clear();
107 }
108
109 private:
110 struct Var {
111 const char* name;
112 std::optional<std::string> value;
113 };
114 std::vector<Var> prev_state_;
115 };
116
117 // This is used only in daemon starting integrations tests.
118 class ServiceThread {
119 public:
ServiceThread(const std::string & producer_socket,const std::string & consumer_socket)120 ServiceThread(const std::string& producer_socket,
121 const std::string& consumer_socket)
122 : producer_socket_(producer_socket), consumer_socket_(consumer_socket) {}
123
~ServiceThread()124 ~ServiceThread() { Stop(); }
125
Start()126 TestEnvCleaner Start() {
127 TestEnvCleaner env_cleaner(
128 {"PERFETTO_PRODUCER_SOCK_NAME", "PERFETTO_CONSUMER_SOCK_NAME"});
129 runner_ = base::ThreadTaskRunner::CreateAndStart("perfetto.svc");
130 runner_->PostTaskAndWaitForTesting([this]() {
131 svc_ = ServiceIPCHost::CreateInstance(runner_->get());
132 if (remove(producer_socket_.c_str()) == -1) {
133 if (errno != ENOENT)
134 PERFETTO_FATAL("Failed to remove %s", producer_socket_.c_str());
135 }
136 if (remove(consumer_socket_.c_str()) == -1) {
137 if (errno != ENOENT)
138 PERFETTO_FATAL("Failed to remove %s", consumer_socket_.c_str());
139 }
140 base::SetEnv("PERFETTO_PRODUCER_SOCK_NAME", producer_socket_);
141 base::SetEnv("PERFETTO_CONSUMER_SOCK_NAME", consumer_socket_);
142 bool res =
143 svc_->Start(producer_socket_.c_str(), consumer_socket_.c_str());
144 if (!res) {
145 PERFETTO_FATAL("Failed to start service listening on %s and %s",
146 producer_socket_.c_str(), consumer_socket_.c_str());
147 }
148 });
149 return env_cleaner;
150 }
151
Stop()152 void Stop() {
153 if (!runner_)
154 return;
155 runner_->PostTaskAndWaitForTesting([this]() { svc_.reset(); });
156 runner_.reset();
157 }
158
runner()159 base::ThreadTaskRunner* runner() { return runner_ ? &*runner_ : nullptr; }
160
161 private:
162 std::optional<base::ThreadTaskRunner> runner_; // Keep first.
163
164 std::string producer_socket_;
165 std::string consumer_socket_;
166 std::unique_ptr<ServiceIPCHost> svc_;
167 };
168
169 // This is used only in daemon starting integrations tests.
170 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
171 // On Windows we don't have any traced_probes, make this a no-op to avoid
172 // propagating #ifdefs to the outer test.
173 class ProbesProducerThread {
174 public:
ProbesProducerThread(const std::string &)175 ProbesProducerThread(const std::string& /*producer_socket*/) {}
Connect()176 void Connect() {}
177 };
178 #else
179 class ProbesProducerThread {
180 public:
ProbesProducerThread(const std::string & producer_socket)181 ProbesProducerThread(const std::string& producer_socket)
182 : producer_socket_(producer_socket) {}
183
~ProbesProducerThread()184 ~ProbesProducerThread() {
185 if (!runner_)
186 return;
187 runner_->PostTaskAndWaitForTesting([this]() { producer_.reset(); });
188 }
189
Connect()190 void Connect() {
191 runner_ = base::ThreadTaskRunner::CreateAndStart("perfetto.prd.probes");
192 runner_->PostTaskAndWaitForTesting([this]() {
193 producer_.reset(new ProbesProducer());
194 producer_->ConnectWithRetries(producer_socket_.c_str(), runner_->get());
195 });
196 }
197
198 private:
199 std::optional<base::ThreadTaskRunner> runner_; // Keep first.
200
201 std::string producer_socket_;
202 std::unique_ptr<ProbesProducer> producer_;
203 };
204 #endif // !OS_WIN
205
206 class FakeProducerThread {
207 public:
FakeProducerThread(const std::string & producer_socket,std::function<void ()> connect_callback,std::function<void ()> setup_callback,std::function<void ()> start_callback)208 FakeProducerThread(const std::string& producer_socket,
209 std::function<void()> connect_callback,
210 std::function<void()> setup_callback,
211 std::function<void()> start_callback)
212 : producer_socket_(producer_socket),
213 connect_callback_(std::move(connect_callback)),
214 setup_callback_(std::move(setup_callback)),
215 start_callback_(std::move(start_callback)) {
216 runner_ = base::ThreadTaskRunner::CreateAndStart("perfetto.prd.fake");
217 runner_->PostTaskAndWaitForTesting([this]() {
218 producer_.reset(
219 new FakeProducer("android.perfetto.FakeProducer", runner_->get()));
220 });
221 }
222
~FakeProducerThread()223 ~FakeProducerThread() {
224 runner_->PostTaskAndWaitForTesting([this]() { producer_.reset(); });
225 }
226
Connect()227 void Connect() {
228 runner_->PostTaskAndWaitForTesting([this]() {
229 producer_->Connect(producer_socket_.c_str(), std::move(connect_callback_),
230 std::move(setup_callback_), std::move(start_callback_),
231 std::move(shm_), std::move(shm_arbiter_));
232 });
233 }
234
runner()235 base::ThreadTaskRunner* runner() { return runner_ ? &*runner_ : nullptr; }
236
producer()237 FakeProducer* producer() { return producer_.get(); }
238
CreateProducerProvidedSmb()239 void CreateProducerProvidedSmb() {
240 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
241 SharedMemoryWindows::Factory factory;
242 #else
243 PosixSharedMemory::Factory factory;
244 #endif
245 shm_ = factory.CreateSharedMemory(1024 * 1024);
246 shm_arbiter_ = SharedMemoryArbiter::CreateUnboundInstance(shm_.get(), 4096);
247 }
248
ProduceStartupEventBatch(const protos::gen::TestConfig & config,std::function<void ()> callback)249 void ProduceStartupEventBatch(const protos::gen::TestConfig& config,
250 std::function<void()> callback) {
251 PERFETTO_CHECK(shm_arbiter_);
252 producer_->ProduceStartupEventBatch(config, shm_arbiter_.get(), callback);
253 }
254
255 private:
256 std::optional<base::ThreadTaskRunner> runner_; // Keep first.
257
258 std::string producer_socket_;
259 std::unique_ptr<FakeProducer> producer_;
260 std::function<void()> connect_callback_;
261 std::function<void()> setup_callback_;
262 std::function<void()> start_callback_;
263 std::unique_ptr<SharedMemory> shm_;
264 std::unique_ptr<SharedMemoryArbiter> shm_arbiter_;
265 };
266
267 class TestHelper : public Consumer {
268 public:
269 enum class Mode {
270 kStartDaemons,
271 kUseSystemService,
272 };
273 static Mode kDefaultMode;
274
275 static const char* GetDefaultModeConsumerSocketName();
276 static const char* GetDefaultModeProducerSocketName();
277
TestHelper(base::TestTaskRunner * task_runner)278 explicit TestHelper(base::TestTaskRunner* task_runner)
279 : TestHelper(task_runner, kDefaultMode) {}
280
281 explicit TestHelper(base::TestTaskRunner* task_runner, Mode mode);
282
283 // Consumer implementation.
284 void OnConnect() override;
285 void OnDisconnect() override;
286 void OnTracingDisabled(const std::string& error) override;
287 virtual void ReadTraceData(std::vector<TracePacket> packets);
288 void OnTraceData(std::vector<TracePacket> packets, bool has_more) override;
289 void OnDetach(bool) override;
290 void OnAttach(bool, const TraceConfig&) override;
291 void OnTraceStats(bool, const TraceStats&) override;
292 void OnObservableEvents(const ObservableEvents&) override;
293 void OnSessionCloned(const OnSessionClonedArgs&) override;
294
295 // Starts the tracing service if in kStartDaemons mode.
296 void StartServiceIfRequired();
297
298 // Restarts the tracing service. Only valid in kStartDaemons mode.
299 void RestartService();
300
301 // Connects the producer and waits that the service has seen the
302 // RegisterDataSource() call.
303 FakeProducer* ConnectFakeProducer();
304
305 void ConnectConsumer();
306 void StartTracing(const TraceConfig& config,
307 base::ScopedFile = base::ScopedFile());
308 void DisableTracing();
309 void FlushAndWait(uint32_t timeout_ms);
310 void ReadData(uint32_t read_count = 0);
311 void FreeBuffers();
312 void DetachConsumer(const std::string& key);
313 bool AttachConsumer(const std::string& key);
314 void CreateProducerProvidedSmb();
315 bool IsShmemProvidedByProducer();
316 void ProduceStartupEventBatch(const protos::gen::TestConfig& config);
317
318 void WaitFor(std::function<bool()> predicate,
319 const std::string& error_msg,
320 uint32_t timeout_ms = kDefaultTestTimeoutMs);
321 void WaitForConsumerConnect();
322 void WaitForProducerSetup();
323 void WaitForProducerEnabled();
324 void WaitForDataSourceConnected(const std::string& ds_name);
325 void WaitForTracingDisabled(uint32_t timeout_ms = kDefaultTestTimeoutMs);
326 void WaitForReadData(uint32_t read_count = 0,
327 uint32_t timeout_ms = kDefaultTestTimeoutMs);
328 void SyncAndWaitProducer();
329 TracingServiceState QueryServiceStateAndWait();
330
AddID(const std::string & checkpoint)331 std::string AddID(const std::string& checkpoint) {
332 return checkpoint + "." + std::to_string(instance_num_);
333 }
334
CreateCheckpoint(const std::string & checkpoint)335 std::function<void()> CreateCheckpoint(const std::string& checkpoint) {
336 return task_runner_->CreateCheckpoint(AddID(checkpoint));
337 }
338
339 void RunUntilCheckpoint(const std::string& checkpoint,
340 uint32_t timeout_ms = kDefaultTestTimeoutMs) {
341 return task_runner_->RunUntilCheckpoint(AddID(checkpoint), timeout_ms);
342 }
343
344 std::function<void()> WrapTask(const std::function<void()>& function);
345
service_thread()346 base::ThreadTaskRunner* service_thread() { return service_thread_.runner(); }
producer_thread()347 base::ThreadTaskRunner* producer_thread() {
348 return fake_producer_thread_.runner();
349 }
full_trace()350 const std::vector<protos::gen::TracePacket>& full_trace() {
351 return full_trace_;
352 }
trace()353 const std::vector<protos::gen::TracePacket>& trace() { return trace_; }
354
355 // Some fixtures want to reuse a global TestHelper in different testcases
356 // without destroying and recreating it, but they still need to avoid
357 // polluting environment variables.
358 //
359 // This restores the previous environment variables.
CleanEnv()360 void CleanEnv() { env_cleaner_.Clean(); }
361
362 private:
363 static uint64_t next_instance_num_;
364 uint64_t instance_num_;
365 base::TestTaskRunner* task_runner_ = nullptr;
366 int cur_consumer_num_ = 0;
367 uint64_t trace_count_ = 0;
368
369 std::function<void()> on_connect_callback_;
370 std::function<void()> on_packets_finished_callback_;
371 std::function<void()> on_stop_tracing_callback_;
372 std::function<void()> on_detach_callback_;
373 std::function<void(bool)> on_attach_callback_;
374
375 std::vector<protos::gen::TracePacket> full_trace_;
376 std::vector<protos::gen::TracePacket> trace_;
377
378 Mode mode_;
379 const char* producer_socket_;
380 const char* consumer_socket_;
381 ServiceThread service_thread_;
382 FakeProducerThread fake_producer_thread_;
383
384 TestEnvCleaner env_cleaner_;
385
386 std::unique_ptr<TracingService::ConsumerEndpoint> endpoint_; // Keep last.
387 };
388
389 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
390
391 // This class is a reference to a child process that has in essence been execv
392 // to the requested binary. The process will start and then wait for Run()
393 // before proceeding. We use this to fork new processes before starting any
394 // additional threads in the parent process (otherwise you would risk
395 // deadlocks), but pause the forked processes until remaining setup (including
396 // any necessary threads) in the parent process is complete.
397 class Exec {
398 public:
399 // Starts the forked process that was created. If not null then |stderr_out|
400 // will contain the stderr of the process.
401 int Run(std::string* stderr_out = nullptr) {
402 // We can't be the child process.
403 PERFETTO_CHECK(getpid() != subprocess_.pid());
404 // Will cause the entrypoint to continue.
405 PERFETTO_CHECK(write(*sync_pipe_.wr, "1", 1) == 1);
406 sync_pipe_.wr.reset();
407 subprocess_.Wait();
408
409 if (stderr_out) {
410 *stderr_out = std::move(subprocess_.output());
411 } else {
412 PERFETTO_LOG("Child proc %d exited with stderr: \"%s\"",
413 subprocess_.pid(), subprocess_.output().c_str());
414 }
415 return subprocess_.returncode();
416 }
417
418 Exec(const std::string& argv0,
419 std::initializer_list<std::string> args,
420 std::string input = "") {
421 subprocess_.args.stderr_mode = base::Subprocess::OutputMode::kBuffer;
422 subprocess_.args.stdout_mode = base::Subprocess::OutputMode::kDevNull;
423 subprocess_.args.input = input;
424
425 #if PERFETTO_BUILDFLAG(PERFETTO_START_DAEMONS)
426 constexpr bool kUseSystemBinaries = false;
427 #else
428 constexpr bool kUseSystemBinaries = true;
429 #endif
430
431 auto pass_env = [](const std::string& var, base::Subprocess* proc) {
432 const char* val = getenv(var.c_str());
433 if (val)
434 proc->args.env.push_back(var + "=" + val);
435 };
436
437 std::vector<std::string>& cmd = subprocess_.args.exec_cmd;
438 if (kUseSystemBinaries) {
439 PERFETTO_CHECK(TestHelper::kDefaultMode ==
440 TestHelper::Mode::kUseSystemService);
441 cmd.push_back("/system/bin/" + argv0);
442 cmd.insert(cmd.end(), args.begin(), args.end());
443 } else {
444 PERFETTO_CHECK(TestHelper::kDefaultMode ==
445 TestHelper::Mode::kStartDaemons);
446 subprocess_.args.env.push_back(
447 std::string("PERFETTO_PRODUCER_SOCK_NAME=") +
448 TestHelper::GetDefaultModeProducerSocketName());
449 subprocess_.args.env.push_back(
450 std::string("PERFETTO_CONSUMER_SOCK_NAME=") +
451 TestHelper::GetDefaultModeConsumerSocketName());
452 pass_env("TMPDIR", &subprocess_);
453 pass_env("TMP", &subprocess_);
454 pass_env("TEMP", &subprocess_);
455 cmd.push_back(base::GetCurExecutableDir() + "/" + argv0);
456 cmd.insert(cmd.end(), args.begin(), args.end());
457 }
458
459 if (!base::FileExists(cmd[0])) {
460 PERFETTO_FATAL(
461 "Cannot find %s. Make sure that the target has been built and, on "
462 "Android, pushed to the device.",
463 cmd[0].c_str());
464 }
465
466 // This pipe blocks the execution of the child process until the main test
467 // process calls Run(). There are two conflicting problems here:
468 // 1) We can't fork() subprocesses too late, because the test spawns threads
469 // for hosting the service. fork+threads = bad (see aosp/1089744).
470 // 2) We can't run the subprocess too early, because we need to wait that
471 // the service threads are ready before trying to connect from the child
472 // process.
473 sync_pipe_ = base::Pipe::Create();
474 int sync_pipe_rd = *sync_pipe_.rd;
475 subprocess_.args.preserve_fds.push_back(sync_pipe_rd);
476
477 // This lambda will be called on the forked child process after having
478 // setup pipe redirection and closed all FDs, right before the exec().
479 // The Subprocesss harness will take care of closing also |sync_pipe_.wr|.
480 subprocess_.args.posix_entrypoint_for_testing = [sync_pipe_rd] {
481 // Don't add any logging here, all file descriptors are closed and trying
482 // to log will likely cause undefined behaviors.
483 char ignored = 0;
484 PERFETTO_CHECK(PERFETTO_EINTR(read(sync_pipe_rd, &ignored, 1)) > 0);
485 PERFETTO_CHECK(close(sync_pipe_rd) == 0 || errno == EINTR);
486 };
487
488 subprocess_.Start();
489 sync_pipe_.rd.reset();
490 }
491
SendSigterm()492 void SendSigterm() {
493 #ifdef SIGTERM
494 kill(subprocess_.pid(), SIGTERM);
495 #else
496 // This code is never used on Windows tests, not bothering.
497 if (subprocess_.pid()) // Always true, but avoids Wnoreturn compile errors.
498 PERFETTO_FATAL("SendSigterm() not implemented on this platform");
499 #endif
500 }
501
502 private:
503 base::Subprocess subprocess_;
504 base::Pipe sync_pipe_;
505 };
506
507 #endif // !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
508
509 } // namespace perfetto
510
511 #endif // TEST_TEST_HELPER_H_
512