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