• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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