• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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 "perfetto/base/build_config.h"
18 #include "perfetto/base/logging.h"
19 #include "perfetto/ext/base/file_utils.h"
20 #include "perfetto/ext/base/pipe.h"
21 #include "perfetto/ext/base/scoped_file.h"
22 #include "perfetto/ext/base/string_utils.h"
23 #include "perfetto/ext/base/temp_file.h"
24 #include "perfetto/ext/base/utils.h"
25 #include "perfetto/ext/tracing/core/commit_data_request.h"
26 #include "perfetto/ext/tracing/core/trace_packet.h"
27 #include "perfetto/ext/tracing/core/tracing_service.h"
28 #include "perfetto/protozero/scattered_heap_buffer.h"
29 #include "perfetto/tracing/core/tracing_service_state.h"
30 #include "src/base/test/test_task_runner.h"
31 #include "src/base/test/utils.h"
32 #include "src/protozero/filtering/filter_bytecode_generator.h"
33 #include "test/gtest_and_gmock.h"
34 #include "test/test_helper.h"
35 
36 #include "protos/perfetto/config/test_config.gen.h"
37 #include "protos/perfetto/config/trace_config.gen.h"
38 #include "protos/perfetto/trace/perfetto/tracing_service_event.gen.h"
39 #include "protos/perfetto/trace/test_event.gen.h"
40 #include "protos/perfetto/trace/trace.gen.h"
41 #include "protos/perfetto/trace/trace_packet.gen.h"
42 #include "protos/perfetto/trace/trace_packet.pbzero.h"
43 
44 namespace perfetto {
45 
46 namespace {
47 
48 using ::testing::ContainsRegex;
49 using ::testing::Each;
50 using ::testing::ElementsAreArray;
51 using ::testing::HasSubstr;
52 using ::testing::Property;
53 using ::testing::SizeIs;
54 
55 }  // namespace
56 
TEST(PerfettoTracedIntegrationTest,TestFakeProducer)57 TEST(PerfettoTracedIntegrationTest, TestFakeProducer) {
58   base::TestTaskRunner task_runner;
59 
60   TestHelper helper(&task_runner);
61   helper.StartServiceIfRequired();
62   helper.ConnectFakeProducer();
63   helper.ConnectConsumer();
64   helper.WaitForConsumerConnect();
65 
66   TraceConfig trace_config;
67   trace_config.add_buffers()->set_size_kb(1024);
68   trace_config.set_duration_ms(200);
69 
70   auto* ds_config = trace_config.add_data_sources()->mutable_config();
71   ds_config->set_name("android.perfetto.FakeProducer");
72   ds_config->set_target_buffer(0);
73 
74   static constexpr size_t kNumPackets = 11;
75   static constexpr uint32_t kRandomSeed = 42;
76   static constexpr uint32_t kMsgSize = 1024;
77   ds_config->mutable_for_testing()->set_seed(kRandomSeed);
78   ds_config->mutable_for_testing()->set_message_count(kNumPackets);
79   ds_config->mutable_for_testing()->set_message_size(kMsgSize);
80   ds_config->mutable_for_testing()->set_send_batch_on_register(true);
81 
82   helper.StartTracing(trace_config);
83   helper.WaitForTracingDisabled();
84 
85   helper.ReadData();
86   helper.WaitForReadData();
87 
88   const auto& packets = helper.trace();
89   ASSERT_EQ(packets.size(), kNumPackets);
90 
91   std::minstd_rand0 rnd_engine(kRandomSeed);
92   for (const auto& packet : packets) {
93     ASSERT_TRUE(packet.has_for_testing());
94     ASSERT_EQ(packet.for_testing().seq_value(), rnd_engine());
95   }
96 }
97 
TEST(PerfettoTracedIntegrationTest,VeryLargePackets)98 TEST(PerfettoTracedIntegrationTest, VeryLargePackets) {
99   base::TestTaskRunner task_runner;
100 
101   TestHelper helper(&task_runner);
102   helper.StartServiceIfRequired();
103   helper.ConnectFakeProducer();
104   helper.ConnectConsumer();
105   helper.WaitForConsumerConnect();
106 
107   TraceConfig trace_config;
108   trace_config.add_buffers()->set_size_kb(4096 * 10);
109   trace_config.set_duration_ms(500);
110 
111   auto* ds_config = trace_config.add_data_sources()->mutable_config();
112   ds_config->set_name("android.perfetto.FakeProducer");
113   ds_config->set_target_buffer(0);
114 
115   static constexpr size_t kNumPackets = 7;
116   static constexpr uint32_t kRandomSeed = 42;
117   static constexpr uint32_t kMsgSize = 1024 * 1024 - 42;
118   ds_config->mutable_for_testing()->set_seed(kRandomSeed);
119   ds_config->mutable_for_testing()->set_message_count(kNumPackets);
120   ds_config->mutable_for_testing()->set_message_size(kMsgSize);
121   ds_config->mutable_for_testing()->set_send_batch_on_register(true);
122 
123   helper.StartTracing(trace_config);
124   helper.WaitForTracingDisabled();
125 
126   helper.ReadData();
127   helper.WaitForReadData(/* read_count */ 0, /* timeout_ms */ 10000);
128 
129   const auto& packets = helper.trace();
130   ASSERT_EQ(packets.size(), kNumPackets);
131 
132   std::minstd_rand0 rnd_engine(kRandomSeed);
133   for (const auto& packet : packets) {
134     ASSERT_TRUE(packet.has_for_testing());
135     ASSERT_EQ(packet.for_testing().seq_value(), rnd_engine());
136     size_t msg_size = packet.for_testing().str().size();
137     ASSERT_EQ(kMsgSize, msg_size);
138     for (size_t i = 0; i < msg_size; i++)
139       ASSERT_EQ(i < msg_size - 1 ? '.' : 0, packet.for_testing().str()[i]);
140   }
141 }
142 
143 // This is a regression test see b/169051440 for context.
144 //
145 // In this test we ensure that traced will not crash if a Producer stops
146 // responding or draining the socket (i.e. after we fill up the IPC buffer
147 // traced doesn't block on trying to write to the IPC buffer and watchdog
148 // doesn't kill it).
TEST(PerfettoTracedIntegrationTest,UnresponsiveProducer)149 TEST(PerfettoTracedIntegrationTest, UnresponsiveProducer) {
150   base::TestTaskRunner task_runner;
151 
152   TestHelper helper(&task_runner);
153   helper.StartServiceIfRequired();
154   auto* producer = helper.ConnectFakeProducer();
155   helper.ConnectConsumer();
156   helper.WaitForConsumerConnect();
157 
158   TraceConfig trace_config;
159   trace_config.add_buffers()->set_size_kb(4096 * 10);
160   trace_config.set_duration_ms(100);
161   trace_config.set_flush_timeout_ms(1);
162   trace_config.set_data_source_stop_timeout_ms(1);
163 
164   auto* ds_config = trace_config.add_data_sources()->mutable_config();
165   ds_config->set_name("android.perfetto.FakeProducer");
166 
167   static constexpr size_t kNumPackets = 1;
168   static constexpr uint32_t kRandomSeed = 42;
169   static constexpr uint32_t kMsgSize = 1024 * 1024 - 42;
170   ds_config->mutable_for_testing()->set_seed(kRandomSeed);
171   ds_config->mutable_for_testing()->set_message_count(kNumPackets);
172   ds_config->mutable_for_testing()->set_message_size(kMsgSize);
173   ds_config->mutable_for_testing()->set_send_batch_on_register(true);
174 
175   // This string is just used to make the StartDataSource IPC larger.
176   ds_config->set_legacy_config(std::string(8192, '.'));
177   ds_config->set_target_buffer(0);
178 
179   // Run one legit trace, this ensures that the producer above is
180   // valid and correct and mirrors real life producers.
181   helper.StartTracing(trace_config);
182   helper.WaitForProducerEnabled();
183   helper.WaitForTracingDisabled();
184 
185   helper.ReadData();
186   helper.WaitForReadData(/* read_count */ 0, /* timeout_ms */ 10000);
187 
188   const auto& packets = helper.trace();
189   ASSERT_EQ(packets.size(), 1u);
190   ASSERT_TRUE(packets[0].has_for_testing());
191   ASSERT_FALSE(packets[0].for_testing().str().empty());
192   helper.FreeBuffers();
193 
194   // Switch the producer to ignoring the IPC socket. On a pixel 4 it took 13
195   // traces to fill up the IPC buffer and cause traced to block (and eventually
196   // watchdog to kill it).
197   helper.producer_thread()->get()->RemoveFileDescriptorWatch(
198       producer->unix_socket_fd());
199 
200   trace_config.set_duration_ms(1);
201   for (uint32_t i = 0u; i < 15u; i++) {
202     helper.StartTracing(trace_config, base::ScopedFile());
203     helper.WaitForTracingDisabled(/* timeout_ms = */ 20000);
204     helper.FreeBuffers();
205   }
206   // We need to readd the FileDescriptor (otherwise when the UnixSocket attempts
207   // to remove it a the FakeProducer is destroyed will hit a CHECK failure.
208   helper.producer_thread()->get()->AddFileDescriptorWatch(
209       producer->unix_socket_fd(), []() {});
210 }
211 
TEST(PerfettoTracedIntegrationTest,DetachAndReattach)212 TEST(PerfettoTracedIntegrationTest, DetachAndReattach) {
213   base::TestTaskRunner task_runner;
214 
215   TraceConfig trace_config;
216   trace_config.add_buffers()->set_size_kb(1024);
217   trace_config.set_duration_ms(10000);  // Max timeout, session is ended before.
218   auto* ds_config = trace_config.add_data_sources()->mutable_config();
219   ds_config->set_name("android.perfetto.FakeProducer");
220   static constexpr size_t kNumPackets = 11;
221   ds_config->mutable_for_testing()->set_message_count(kNumPackets);
222   ds_config->mutable_for_testing()->set_message_size(32);
223 
224   // Enable tracing and detach as soon as it gets started.
225   TestHelper helper(&task_runner);
226   helper.StartServiceIfRequired();
227   auto* fake_producer = helper.ConnectFakeProducer();
228   helper.ConnectConsumer();
229   helper.WaitForConsumerConnect();
230   helper.StartTracing(trace_config);
231 
232   // Detach.
233   helper.DetachConsumer("key");
234 
235   // Write data while detached.
236   helper.WaitForProducerEnabled();
237   auto on_data_written = task_runner.CreateCheckpoint("data_written");
238   fake_producer->ProduceEventBatch(helper.WrapTask(on_data_written));
239   task_runner.RunUntilCheckpoint("data_written");
240 
241   // Then reattach the consumer.
242   helper.ConnectConsumer();
243   helper.WaitForConsumerConnect();
244   helper.AttachConsumer("key");
245 
246   helper.DisableTracing();
247   helper.WaitForTracingDisabled();
248 
249   helper.ReadData();
250   helper.WaitForReadData();
251   const auto& packets = helper.trace();
252   ASSERT_EQ(packets.size(), kNumPackets);
253 }
254 
255 // Tests that a detached trace session is automatically cleaned up if the
256 // consumer doesn't re-attach before its expiration time.
TEST(PerfettoTracedIntegrationTest,ReattachFailsAfterTimeout)257 TEST(PerfettoTracedIntegrationTest, ReattachFailsAfterTimeout) {
258   base::TestTaskRunner task_runner;
259 
260   TraceConfig trace_config;
261   trace_config.add_buffers()->set_size_kb(1024);
262   trace_config.set_duration_ms(250);
263   trace_config.set_write_into_file(true);
264   trace_config.set_file_write_period_ms(100000);
265   auto* ds_config = trace_config.add_data_sources()->mutable_config();
266   ds_config->set_name("android.perfetto.FakeProducer");
267   ds_config->mutable_for_testing()->set_message_count(1);
268   ds_config->mutable_for_testing()->set_message_size(32);
269   ds_config->mutable_for_testing()->set_send_batch_on_register(true);
270 
271   // Enable tracing and detach as soon as it gets started.
272   TestHelper helper(&task_runner);
273   helper.StartServiceIfRequired();
274   helper.ConnectFakeProducer();
275   helper.ConnectConsumer();
276   helper.WaitForConsumerConnect();
277 
278   auto pipe_pair = base::Pipe::Create();
279   helper.StartTracing(trace_config, std::move(pipe_pair.wr));
280 
281   // Detach.
282   helper.DetachConsumer("key");
283 
284   // Use the file EOF (write end closed) as a way to detect when the trace
285   // session is ended.
286   char buf[1024];
287   while (PERFETTO_EINTR(read(*pipe_pair.rd, buf, sizeof(buf))) > 0) {
288   }
289 
290   // Give some margin for the tracing service to destroy the session.
291   usleep(250000);
292 
293   // Reconnect and find out that it's too late and the session is gone.
294   helper.ConnectConsumer();
295   helper.WaitForConsumerConnect();
296   EXPECT_FALSE(helper.AttachConsumer("key"));
297 }
298 
TEST(PerfettoTracedIntegrationTest,TestProducerProvidedSMB)299 TEST(PerfettoTracedIntegrationTest, TestProducerProvidedSMB) {
300   base::TestTaskRunner task_runner;
301 
302   TestHelper helper(&task_runner);
303   helper.CreateProducerProvidedSmb();
304 
305   protos::gen::TestConfig test_config;
306   test_config.set_seed(42);
307   test_config.set_message_count(1);
308   test_config.set_message_size(1024);
309   test_config.set_send_batch_on_register(true);
310 
311   // Write a first batch before connection.
312   helper.ProduceStartupEventBatch(test_config);
313 
314   helper.StartServiceIfRequired();
315   helper.ConnectFakeProducer();
316   helper.ConnectConsumer();
317   helper.WaitForConsumerConnect();
318 
319   TraceConfig trace_config;
320   trace_config.add_buffers()->set_size_kb(1024);
321   trace_config.set_duration_ms(200);
322 
323   auto* ds_config = trace_config.add_data_sources()->mutable_config();
324   ds_config->set_name("android.perfetto.FakeProducer");
325   ds_config->set_target_buffer(0);
326   *ds_config->mutable_for_testing() = test_config;
327 
328   // The data source is configured to emit another batch when it is started via
329   // send_batch_on_register in the TestConfig.
330   helper.StartTracing(trace_config);
331   helper.WaitForTracingDisabled();
332 
333   EXPECT_TRUE(helper.IsShmemProvidedByProducer());
334 
335   helper.ReadData();
336   helper.WaitForReadData();
337 
338   const auto& packets = helper.trace();
339   // We should have produced two batches, one before the producer connected and
340   // another one when the data source was started.
341   ASSERT_EQ(packets.size(), 2u);
342   ASSERT_TRUE(packets[0].has_for_testing());
343   ASSERT_TRUE(packets[1].has_for_testing());
344 }
345 
346 // Regression test for b/153142114.
TEST(PerfettoTracedIntegrationTest,QueryServiceStateLargeResponse)347 TEST(PerfettoTracedIntegrationTest, QueryServiceStateLargeResponse) {
348   base::TestTaskRunner task_runner;
349 
350   TestHelper helper(&task_runner);
351   helper.StartServiceIfRequired();
352   helper.ConnectConsumer();
353   helper.WaitForConsumerConnect();
354 
355   FakeProducer* producer = helper.ConnectFakeProducer();
356 
357   // Register 5 data sources with very large descriptors. Each descriptor will
358   // max out the IPC message size, so that the service has no other choice
359   // than chunking them.
360   std::map<std::string, std::string> ds_expected;
361   for (int i = 0; i < 5; i++) {
362     DataSourceDescriptor dsd;
363     std::string name = "big_ds_" + std::to_string(i);
364     dsd.set_name(name);
365     std::string descriptor(ipc::kIPCBufferSize - 64,
366                            static_cast<char>((' ' + i) % 64));
367     dsd.set_track_event_descriptor_raw(descriptor);
368     ds_expected[name] = std::move(descriptor);
369     producer->RegisterDataSource(dsd);
370   }
371 
372   // Linearize the producer with the service. We need to make sure that all the
373   // RegisterDataSource() calls above have been seen by the service before
374   // continuing.
375   helper.SyncAndWaitProducer();
376 
377   // Now invoke QueryServiceState() and wait for the reply. The service will
378   // send 6 (1 + 5) IPCs which will be merged together in
379   // producer_ipc_client_impl.cc.
380   auto svc_state = helper.QueryServiceStateAndWait();
381 
382   ASSERT_GE(svc_state.producers().size(), 1u);
383 
384   std::map<std::string, std::string> ds_found;
385   for (const auto& ds : svc_state.data_sources()) {
386     if (!base::StartsWith(ds.ds_descriptor().name(), "big_ds_"))
387       continue;
388     ds_found[ds.ds_descriptor().name()] =
389         ds.ds_descriptor().track_event_descriptor_raw();
390   }
391   EXPECT_THAT(ds_found, ElementsAreArray(ds_expected));
392 }
393 
394 // Regression test for b/195065199. Check that trace filtering works when a
395 // packet size exceeds the IPC limit. This tests that the tracing service, when
396 // reassembling packets after filtering, doesn't "overglue" them. They still
397 // need to be slice-able to fit into the ReadBuffers ipc.
TEST(PerfettoTracedIntegrationTest,TraceFilterLargePackets)398 TEST(PerfettoTracedIntegrationTest, TraceFilterLargePackets) {
399   base::TestTaskRunner task_runner;
400   TestHelper helper(&task_runner);
401 
402   helper.StartServiceIfRequired();
403   helper.ConnectFakeProducer();
404   helper.ConnectConsumer();
405   helper.WaitForConsumerConnect();
406 
407   TraceConfig trace_config;
408   trace_config.add_buffers()->set_size_kb(1024 * 16);
409   trace_config.set_duration_ms(500);
410   auto* prod_config = trace_config.add_producers();
411   prod_config->set_producer_name("android.perfetto.FakeProducer");
412   prod_config->set_shm_size_kb(1024 * 16);
413   prod_config->set_page_size_kb(32);
414 
415   static constexpr size_t kNumPackets = 3;
416   static constexpr uint32_t kRandomSeed = 42;
417   static constexpr uint32_t kMsgSize = 8 * ipc::kIPCBufferSize;
418   auto* ds_config = trace_config.add_data_sources()->mutable_config();
419   ds_config->set_name("android.perfetto.FakeProducer");
420   auto* test_config = ds_config->mutable_for_testing();
421   test_config->set_seed(kRandomSeed);
422   test_config->set_message_count(kNumPackets);
423   test_config->set_message_size(kMsgSize);
424   test_config->set_send_batch_on_register(true);
425 
426   protozero::FilterBytecodeGenerator filt;
427   // Message 0: root Trace proto.
428   filt.AddNestedField(1 /* root trace.packet*/, 1);
429   filt.EndMessage();
430 
431   // Message 1: TracePacket proto. Allow all fields.
432   filt.AddSimpleFieldRange(1, 1000);
433   filt.EndMessage();
434 
435   trace_config.mutable_trace_filter()->set_bytecode(filt.Serialize());
436 
437   // The data source is configured to emit another batch when it is started via
438   // send_batch_on_register in the TestConfig.
439   helper.StartTracing(trace_config);
440   helper.WaitForTracingDisabled();
441 
442   helper.ReadData();
443   helper.WaitForReadData(/* read_count */ 0, /* timeout_ms */ 10000);
444 
445   const std::vector<protos::gen::TracePacket>& packets = helper.trace();
446   EXPECT_EQ(packets.size(), kNumPackets);
447   EXPECT_THAT(packets,
448               Each(Property(&protos::gen::TracePacket::has_for_testing, true)));
449   EXPECT_THAT(
450       packets,
451       Each(Property(&protos::gen::TracePacket::for_testing,
452                     Property(&protos::gen::TestEvent::str, SizeIs(kMsgSize)))));
453 }
454 
455 }  // namespace perfetto
456