xref: /aosp_15_r20/external/perfetto/src/tracing/internal/tracing_muxer_impl_integrationtest.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1 #include "perfetto/tracing/tracing.h"
2 
3 #include <stdio.h>
4 #include <optional>
5 
6 #include "perfetto/ext/base/thread_task_runner.h"
7 #include "perfetto/ext/base/waitable_event.h"
8 #include "perfetto/ext/tracing/ipc/service_ipc_host.h"
9 #include "perfetto/tracing/backend_type.h"
10 #include "protos/perfetto/config/trace_config.gen.h"
11 #include "protos/perfetto/trace/trace.gen.h"
12 #include "protos/perfetto/trace/trace_packet.gen.h"
13 #include "protos/perfetto/trace/trigger.gen.h"
14 #include "src/base/test/test_task_runner.h"
15 #include "src/base/test/tmp_dir_tree.h"
16 #include "test/gtest_and_gmock.h"
17 
18 namespace perfetto {
19 namespace internal {
20 namespace {
21 
22 using ::testing::NiceMock;
23 using ::testing::NotNull;
24 using ::testing::Property;
25 
26 class TracingMuxerImplIntegrationTest : public testing::Test {
27  protected:
SetUp()28   void SetUp() override {
29 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
30     GTEST_SKIP() << "Unix sockets not supported on windows";
31 #endif
32   }
33 
34   // Sets the environment variable `name` to `value`. Restores it to the
35   // previous value when the test finishes.
SetEnvVar(const char * name,const char * value)36   void SetEnvVar(const char* name, const char* value) {
37     prev_state_.emplace();
38     EnvVar& var = prev_state_.top();
39     var.name = name;
40     const char* prev_value = getenv(name);
41     if (prev_value) {
42       var.value.emplace(prev_value);
43     }
44     base::SetEnv(name, value);
45   }
46 
~TracingMuxerImplIntegrationTest()47   ~TracingMuxerImplIntegrationTest() override {
48     perfetto::Tracing::ResetForTesting();
49     while (!prev_state_.empty()) {
50       const EnvVar& var = prev_state_.top();
51       if (var.value) {
52         base::SetEnv(var.name, *var.value);
53       } else {
54         base::UnsetEnv(var.name);
55       }
56       prev_state_.pop();
57     }
58   }
59 
60   struct EnvVar {
61     const char* name;
62     std::optional<std::string> value;
63   };
64   // Stores previous values of environment variables overridden by tests. We
65   // need to to this because some android integration tests need to talk to the
66   // real system tracing service and need the PERFETTO_PRODUCER_SOCK_NAME and
67   // PERFETTO_CONSUMER_SOCK_NAME to be set to their original value.
68   std::stack<EnvVar> prev_state_;
69 };
70 
71 class TracingServiceThread {
72  public:
TracingServiceThread(const std::string & producer_socket,const std::string & consumer_socket)73   TracingServiceThread(const std::string& producer_socket,
74                        const std::string& consumer_socket)
75       : runner_(base::ThreadTaskRunner::CreateAndStart("perfetto.svc")),
76         producer_socket_(producer_socket),
77         consumer_socket_(consumer_socket) {
78     runner_.PostTaskAndWaitForTesting([this]() {
79       svc_ = ServiceIPCHost::CreateInstance(&runner_);
80       bool res =
81           svc_->Start(producer_socket_.c_str(), consumer_socket_.c_str());
82       if (!res) {
83         PERFETTO_FATAL("Failed to start service listening on %s and %s",
84                        producer_socket_.c_str(), consumer_socket_.c_str());
85       }
86     });
87   }
88 
~TracingServiceThread()89   ~TracingServiceThread() {
90     runner_.PostTaskAndWaitForTesting([this]() { svc_.reset(); });
91   }
92 
producer_socket() const93   const std::string& producer_socket() const { return producer_socket_; }
consumer_socket() const94   const std::string& consumer_socket() const { return consumer_socket_; }
95 
96  private:
97   base::ThreadTaskRunner runner_;
98 
99   std::string producer_socket_;
100   std::string consumer_socket_;
101   std::unique_ptr<ServiceIPCHost> svc_;
102 };
103 
TEST_F(TracingMuxerImplIntegrationTest,ActivateTriggers)104 TEST_F(TracingMuxerImplIntegrationTest, ActivateTriggers) {
105   base::TmpDirTree tmpdir_;
106 
107   base::TestTaskRunner task_runner;
108 
109   ASSERT_FALSE(perfetto::Tracing::IsInitialized());
110 
111   tmpdir_.TrackFile("producer2.sock");
112   tmpdir_.TrackFile("consumer.sock");
113   TracingServiceThread tracing_service(tmpdir_.AbsolutePath("producer2.sock"),
114                                        tmpdir_.AbsolutePath("consumer.sock"));
115   // Instead of being a unix socket, producer.sock is a regular empty file.
116   tmpdir_.AddFile("producer.sock", "");
117 
118   // Wrong producer socket: the producer won't connect yet, but the consumer
119   // will.
120   SetEnvVar("PERFETTO_PRODUCER_SOCK_NAME",
121             tmpdir_.AbsolutePath("producer.sock").c_str());
122   SetEnvVar("PERFETTO_CONSUMER_SOCK_NAME",
123             tmpdir_.AbsolutePath("consumer.sock").c_str());
124 
125   TracingInitArgs args;
126   args.backends = perfetto::kSystemBackend;
127   perfetto::Tracing::Initialize(args);
128 
129   // TracingMuxerImpl::ActivateTriggers will be called without the producer side
130   // of the service being connected. It should store the trigger for 10000ms.
131   perfetto::Tracing::ActivateTriggers({"trigger2", "trigger1"}, 10000);
132 
133   perfetto::TraceConfig cfg;
134   cfg.add_buffers()->set_size_kb(1024);
135   perfetto::TraceConfig::TriggerConfig* tr_cfg = cfg.mutable_trigger_config();
136   tr_cfg->set_trigger_mode(perfetto::TraceConfig::TriggerConfig::STOP_TRACING);
137   tr_cfg->set_trigger_timeout_ms(10000);
138   perfetto::TraceConfig::TriggerConfig::Trigger* trigger =
139       tr_cfg->add_triggers();
140   trigger->set_name("trigger1");
141 
142   std::unique_ptr<TracingSession> session =
143       perfetto::Tracing::NewTrace(perfetto::kSystemBackend);
144   base::WaitableEvent on_stop;
145   session->SetOnStopCallback([&on_stop] { on_stop.Notify(); });
146   session->Setup(cfg);
147 
148   session->StartBlocking();
149 
150   // Swap producer.sock and producer2.sock. Now the client should connect to the
151   // tracing service as a producer.
152   ASSERT_EQ(rename(tmpdir_.AbsolutePath("producer2.sock").c_str(),
153                    tmpdir_.AbsolutePath("producer3.sock").c_str()),
154             0);
155   ASSERT_EQ(rename(tmpdir_.AbsolutePath("producer.sock").c_str(),
156                    tmpdir_.AbsolutePath("producer2.sock").c_str()),
157             0);
158   ASSERT_EQ(rename(tmpdir_.AbsolutePath("producer3.sock").c_str(),
159                    tmpdir_.AbsolutePath("producer.sock").c_str()),
160             0);
161 
162   on_stop.Wait();
163 
164   std::vector<char> bytes = session->ReadTraceBlocking();
165   perfetto::protos::gen::Trace parsed_trace;
166   ASSERT_TRUE(parsed_trace.ParseFromArray(bytes.data(), bytes.size()));
167   EXPECT_THAT(
168       parsed_trace,
169       Property(&perfetto::protos::gen::Trace::packet,
170                Contains(Property(
171                    &perfetto::protos::gen::TracePacket::trigger,
172                    Property(&perfetto::protos::gen::Trigger::trigger_name,
173                             "trigger1")))));
174 }
175 
176 }  // namespace
177 }  // namespace internal
178 }  // namespace perfetto
179