xref: /aosp_15_r20/external/perfetto/test/cmdline_integrationtest.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
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 <functional>
18 #include <initializer_list>
19 #include <thread>
20 
21 #include "perfetto/base/build_config.h"
22 #include "perfetto/base/logging.h"
23 #include "perfetto/ext/base/pipe.h"
24 #include "perfetto/ext/base/string_utils.h"
25 #include "perfetto/ext/base/utils.h"
26 #include "perfetto/ext/traced/traced.h"
27 #include "perfetto/protozero/scattered_heap_buffer.h"
28 #include "perfetto/tracing/core/tracing_service_state.h"
29 #include "src/base/test/test_task_runner.h"
30 #include "src/base/test/utils.h"
31 #include "src/perfetto_cmd/bugreport_path.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/test_event.gen.h"
39 #include "protos/perfetto/trace/trace.gen.h"
40 #include "protos/perfetto/trace/trace_packet.gen.h"
41 #include "protos/perfetto/trace/trace_packet.pbzero.h"
42 #include "protos/perfetto/trace/trigger.gen.h"
43 
44 namespace perfetto {
45 
46 namespace {
47 
48 using ::testing::ContainsRegex;
49 using ::testing::Each;
50 using ::testing::ElementsAre;
51 using ::testing::ElementsAreArray;
52 using ::testing::Eq;
53 using ::testing::HasSubstr;
54 using ::testing::IsEmpty;
55 using ::testing::Property;
56 using ::testing::SizeIs;
57 
RandomTraceFileName()58 std::string RandomTraceFileName() {
59 #if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
60   constexpr char kSysTmpPath[] = "/data/misc/perfetto-traces";
61 #else
62   constexpr char kSysTmpPath[] = "/tmp";
63 #endif
64   static int suffix = 0;
65 
66   std::string path;
67   path.assign(kSysTmpPath);
68   path.append("/trace-");
69   path.append(std::to_string(base::GetBootTimeNs().count()));
70   path.append("-");
71   path.append(std::to_string(suffix++));
72   return path;
73 }
74 
75 // For the SaveForBugreport* tests.
CreateTraceConfigForBugreportTest(int score=1,bool add_filter=false,uint32_t msg_count=3,uint32_t msg_size=10)76 TraceConfig CreateTraceConfigForBugreportTest(int score = 1,
77                                               bool add_filter = false,
78                                               uint32_t msg_count = 3,
79                                               uint32_t msg_size = 10) {
80   TraceConfig trace_config;
81   trace_config.add_buffers()->set_size_kb(32768);
82   trace_config.set_duration_ms(60000);  // Will never hit this.
83   trace_config.set_bugreport_score(score);
84 
85   if (add_filter) {
86     // Add a trace filter which disallows the trace config echo-back.
87     protozero::FilterBytecodeGenerator filt;
88     filt.AddNestedField(1 /* root trace.packet*/, 1);
89     filt.EndMessage();
90     // Add a random unrelated field to keep the generator happy.
91     filt.AddSimpleField(protos::pbzero::TracePacket::kTraceUuidFieldNumber);
92     filt.EndMessage();
93     trace_config.mutable_trace_filter()->set_bytecode_v2(filt.Serialize());
94   }
95 
96   auto* ds_config = trace_config.add_data_sources()->mutable_config();
97   ds_config->set_name("android.perfetto.FakeProducer");
98 
99   ds_config->mutable_for_testing()->set_message_count(msg_count);
100   ds_config->mutable_for_testing()->set_message_size(msg_size);
101   return trace_config;
102 }
103 
104 // For the regular tests.
CreateTraceConfigForTest(uint32_t test_msg_count=11,uint32_t test_msg_size=32)105 TraceConfig CreateTraceConfigForTest(uint32_t test_msg_count = 11,
106                                      uint32_t test_msg_size = 32) {
107   TraceConfig trace_config;
108   trace_config.add_buffers()->set_size_kb(1024);
109   auto* ds_config = trace_config.add_data_sources()->mutable_config();
110   ds_config->set_name("android.perfetto.FakeProducer");
111   ds_config->mutable_for_testing()->set_message_count(test_msg_count);
112   ds_config->mutable_for_testing()->set_message_size(test_msg_size);
113   return trace_config;
114 }
115 
ExpectTraceContainsTestMessages(const protos::gen::Trace & trace,uint32_t count)116 void ExpectTraceContainsTestMessages(const protos::gen::Trace& trace,
117                                      uint32_t count) {
118   ssize_t actual_test_packets_count = std::count_if(
119       trace.packet().begin(), trace.packet().end(),
120       [](const protos::gen::TracePacket& tp) { return tp.has_for_testing(); });
121   EXPECT_EQ(count, static_cast<uint32_t>(actual_test_packets_count));
122 }
123 
ExpectTraceContainsTestMessagesWithSize(const protos::gen::Trace & trace,uint32_t message_size)124 void ExpectTraceContainsTestMessagesWithSize(const protos::gen::Trace& trace,
125                                              uint32_t message_size) {
126   for (const auto& packet : trace.packet()) {
127     if (packet.has_for_testing()) {
128       EXPECT_EQ(message_size, packet.for_testing().str().size());
129     }
130   }
131 }
132 
ExpectTraceContainsConfigWithTriggerMode(const protos::gen::Trace & trace,protos::gen::TraceConfig::TriggerConfig::TriggerMode trigger_mode)133 void ExpectTraceContainsConfigWithTriggerMode(
134     const protos::gen::Trace& trace,
135     protos::gen::TraceConfig::TriggerConfig::TriggerMode trigger_mode) {
136   // GTest three level nested Property matcher is hard to read, so we use
137   // 'find_if' with lambda to ensure the trace config properly includes the
138   // trigger mode we set.
139   auto found =
140       std::find_if(trace.packet().begin(), trace.packet().end(),
141                    [trigger_mode](const protos::gen::TracePacket& tp) {
142                      return tp.has_trace_config() &&
143                             tp.trace_config().trigger_config().trigger_mode() ==
144                                 trigger_mode;
145                    });
146   EXPECT_NE(found, trace.packet().end())
147       << "Trace config doesn't include expected trigger mode.";
148 }
149 
150 class ScopedFileRemove {
151  public:
ScopedFileRemove(const std::string & path)152   explicit ScopedFileRemove(const std::string& path) : path_(path) {}
~ScopedFileRemove()153   ~ScopedFileRemove() { remove(path_.c_str()); }
154   std::string path_;
155 };
156 
ParseNotEmptyTraceFromFile(const std::string & trace_path,protos::gen::Trace & out)157 bool ParseNotEmptyTraceFromFile(const std::string& trace_path,
158                                 protos::gen::Trace& out) {
159   std::string trace_str;
160   if (!base::ReadFile(trace_path, &trace_str))
161     return false;
162   if (trace_str.empty())
163     return false;
164   return out.ParseFromString(trace_str);
165 }
166 
GetReceivedTriggerNames(const protos::gen::Trace & trace)167 std::vector<std::string> GetReceivedTriggerNames(
168     const protos::gen::Trace& trace) {
169   std::vector<std::string> triggers;
170   for (const protos::gen::TracePacket& packet : trace.packet()) {
171     if (packet.has_trigger()) {
172       triggers.push_back(packet.trigger().trigger_name());
173     }
174   }
175   return triggers;
176 }
177 
178 class PerfettoCmdlineTest : public ::testing::Test {
179  public:
StartServiceIfRequiredNoNewExecsAfterThis()180   void StartServiceIfRequiredNoNewExecsAfterThis() {
181     exec_allowed_ = false;
182     test_helper_.StartServiceIfRequired();
183   }
184 
test_helper()185   TestHelper& test_helper() { return test_helper_; }
186 
187   // Creates a process that represents the perfetto binary that will
188   // start when Run() is called. |args| will be passed as part of
189   // the command line and |std_in| will be piped into std::cin.
ExecPerfetto(std::initializer_list<std::string> args,std::string std_in="")190   Exec ExecPerfetto(std::initializer_list<std::string> args,
191                     std::string std_in = "") {
192     // You can not fork after you've started the service due to risk of
193     // deadlocks.
194     PERFETTO_CHECK(exec_allowed_);
195     return Exec("perfetto", std::move(args), std::move(std_in));
196   }
197 
198   // Creates a process that represents the trigger_perfetto binary that will
199   // start when Run() is called. |args| will be passed as part of
200   // the command line and |std_in| will be piped into std::cin.
ExecTrigger(std::initializer_list<std::string> args,std::string std_in="")201   Exec ExecTrigger(std::initializer_list<std::string> args,
202                    std::string std_in = "") {
203     // You can not fork after you've started the service due to risk of
204     // deadlocks.
205     PERFETTO_CHECK(exec_allowed_);
206     return Exec("trigger_perfetto", std::move(args), std::move(std_in));
207   }
208 
209   // This is in common to the 3 TEST_F SaveForBugreport* fixtures, which differ
210   // only in the config, passed here as input.
RunBugreportTest(protos::gen::TraceConfig trace_config,bool check_original_trace=true,bool use_explicit_clone=false)211   void RunBugreportTest(protos::gen::TraceConfig trace_config,
212                         bool check_original_trace = true,
213                         bool use_explicit_clone = false) {
214     const std::string path = RandomTraceFileName();
215     ScopedFileRemove remove_on_test_exit(path);
216 
217     auto perfetto_proc = ExecPerfetto(
218         {
219             "-o",
220             path,
221             "-c",
222             "-",
223         },
224         trace_config.SerializeAsString());
225 
226     Exec perfetto_br_proc =
227         use_explicit_clone
228             ? ExecPerfetto({"--out", GetBugreportTracePath(), "--clone", "-1"})
229             : ExecPerfetto({"--save-for-bugreport"});
230 
231     // Start the service and connect a simple fake producer.
232     StartServiceIfRequiredNoNewExecsAfterThis();
233 
234     auto* fake_producer = test_helper().ConnectFakeProducer();
235     ASSERT_TRUE(fake_producer);
236 
237     std::thread background_trace([&perfetto_proc]() {
238       std::string stderr_str;
239       ASSERT_EQ(0, perfetto_proc.Run(&stderr_str)) << stderr_str;
240     });
241 
242     // Wait for the producer to start, and then write out packets.
243     test_helper().WaitForProducerEnabled();
244     auto on_data_written = task_runner_.CreateCheckpoint("data_written");
245     fake_producer->ProduceEventBatch(test_helper().WrapTask(on_data_written));
246     task_runner_.RunUntilCheckpoint("data_written");
247 
248     ASSERT_EQ(0, perfetto_br_proc.Run(&stderr_)) << "stderr: " << stderr_;
249     perfetto_proc.SendSigterm();
250     background_trace.join();
251 
252     uint32_t expected_packets = 0;
253     for (auto& ds : trace_config.data_sources()) {
254       if (ds.config().has_for_testing())
255         expected_packets = ds.config().for_testing().message_count();
256     }
257 
258     auto check_trace_contents = [expected_packets](std::string trace_path) {
259       // Read the trace written in the fixed location
260       // (/data/misc/perfetto-traces/ on Android, /tmp/ on Linux/Mac) and make
261       // sure it has the right contents.
262       protos::gen::Trace trace;
263       ASSERT_TRUE(ParseNotEmptyTraceFromFile(trace_path, trace));
264       uint32_t test_packets = 0;
265       for (const auto& p : trace.packet())
266         test_packets += p.has_for_testing() ? 1 : 0;
267       ASSERT_EQ(test_packets, expected_packets) << trace_path;
268     };
269 
270     // Verify that both the original trace and the cloned bugreport contain
271     // the expected contents.
272     check_trace_contents(GetBugreportTracePath());
273     if (check_original_trace)
274       check_trace_contents(path);
275   }
276 
277   // Tests are allowed to freely use these variables.
278   std::string stderr_;
279   base::TestTaskRunner task_runner_;
280 
281   // We use these two constants to set test data payload parameters and assert
282   // it was correctly written to the trace.
283   static constexpr size_t kTestMessageCount = 11;
284   static constexpr size_t kTestMessageSize = 32;
285 
286  private:
287   bool exec_allowed_ = true;
288   TestHelper test_helper_{&task_runner_};
289 };
290 
291 }  // namespace
292 
293 #if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
294 #define AndroidOnly(x) x
295 #else
296 #define AndroidOnly(x) DISABLED_##x
297 #endif
298 
TEST_F(PerfettoCmdlineTest,InvalidCases)299 TEST_F(PerfettoCmdlineTest, InvalidCases) {
300   std::string cfg("duration_ms: 100");
301 
302   auto invalid_arg = ExecPerfetto({"--invalid-arg"});
303   auto empty_config = ExecPerfetto({"-c", "-", "-o", "-"}, "");
304 
305   // Cannot make assertions on --dropbox because on standalone builds it fails
306   // prematurely due to lack of dropbox.
307   auto missing_dropbox =
308       ExecPerfetto({"-c", "-", "--txt", "-o", "-", "--dropbox=foo"}, cfg);
309   auto either_out_or_dropbox = ExecPerfetto({"-c", "-", "--txt"}, cfg);
310 
311   // Disallow mixing simple and file config.
312   auto simple_and_file_1 =
313       ExecPerfetto({"-o", "-", "-c", "-", "-t", "2s"}, cfg);
314   auto simple_and_file_2 =
315       ExecPerfetto({"-o", "-", "-c", "-", "-b", "2m"}, cfg);
316   auto simple_and_file_3 =
317       ExecPerfetto({"-o", "-", "-c", "-", "-s", "2m"}, cfg);
318 
319   // Invalid --attach / --detach cases.
320   auto invalid_stop =
321       ExecPerfetto({"-c", "-", "--txt", "-o", "-", "--stop"}, cfg);
322   auto attach_and_config_1 =
323       ExecPerfetto({"-c", "-", "--txt", "-o", "-", "--attach=foo"}, cfg);
324   auto attach_and_config_2 =
325       ExecPerfetto({"-t", "2s", "-o", "-", "--attach=foo"}, cfg);
326   auto attach_needs_argument = ExecPerfetto({"--attach"}, cfg);
327   auto detach_needs_argument =
328       ExecPerfetto({"-t", "2s", "-o", "-", "--detach"}, cfg);
329   auto detach_without_out_or_dropbox =
330       ExecPerfetto({"-t", "2s", "--detach=foo"}, cfg);
331 
332   // Cannot trace and use --query.
333   auto trace_and_query_1 = ExecPerfetto({"-t", "2s", "--query"}, cfg);
334   auto trace_and_query_2 = ExecPerfetto({"-c", "-", "--query"}, cfg);
335 
336   // Ensure all Exec:: calls have been saved to prevent deadlocks.
337   StartServiceIfRequiredNoNewExecsAfterThis();
338 
339   EXPECT_EQ(1, invalid_arg.Run(&stderr_));
340 
341   EXPECT_EQ(1, empty_config.Run(&stderr_));
342   EXPECT_THAT(stderr_, HasSubstr("TraceConfig is empty"));
343 
344   // Cannot make assertions on --upload because on standalone builds it fails
345   // prematurely due to lack of dropbox.
346   EXPECT_EQ(1, missing_dropbox.Run(&stderr_));
347 
348   EXPECT_EQ(1, either_out_or_dropbox.Run(&stderr_));
349   EXPECT_THAT(stderr_, HasSubstr("Either --out or --upload"));
350 
351   // Disallow mixing simple and file config.
352   EXPECT_EQ(1, simple_and_file_1.Run(&stderr_));
353   EXPECT_THAT(stderr_, HasSubstr("Cannot specify both -c"));
354 
355   EXPECT_EQ(1, simple_and_file_2.Run(&stderr_));
356   EXPECT_THAT(stderr_, HasSubstr("Cannot specify both -c"));
357 
358   EXPECT_EQ(1, simple_and_file_3.Run(&stderr_));
359   EXPECT_THAT(stderr_, HasSubstr("Cannot specify both -c"));
360 
361   // Invalid --attach / --detach cases.
362   EXPECT_EQ(1, invalid_stop.Run(&stderr_));
363   EXPECT_THAT(stderr_, HasSubstr("--stop is supported only in combination"));
364 
365   EXPECT_EQ(1, attach_and_config_1.Run(&stderr_));
366   EXPECT_THAT(stderr_, HasSubstr("Cannot specify a trace config"));
367 
368   EXPECT_EQ(1, attach_and_config_2.Run(&stderr_));
369   EXPECT_THAT(stderr_, HasSubstr("Cannot specify a trace config"));
370 
371   EXPECT_EQ(1, attach_needs_argument.Run(&stderr_));
372   EXPECT_THAT(stderr_, ContainsRegex("option.*--attach.*requires an argument"));
373 
374   EXPECT_EQ(1, detach_needs_argument.Run(&stderr_));
375   EXPECT_THAT(stderr_, ContainsRegex("option.*--detach.*requires an argument"));
376 
377   EXPECT_EQ(1, detach_without_out_or_dropbox.Run(&stderr_));
378   EXPECT_THAT(stderr_, HasSubstr("--out or --upload is required"));
379 
380   // Cannot trace and use --query.
381   EXPECT_EQ(1, trace_and_query_1.Run(&stderr_));
382   EXPECT_THAT(stderr_, HasSubstr("Cannot specify a trace config"));
383 
384   EXPECT_EQ(1, trace_and_query_2.Run(&stderr_));
385   EXPECT_THAT(stderr_, HasSubstr("Cannot specify a trace config"));
386 }
387 
TEST_F(PerfettoCmdlineTest,Version)388 TEST_F(PerfettoCmdlineTest, Version) {
389   auto perfetto = ExecPerfetto({"--version"});
390   EXPECT_EQ(0, perfetto.Run(&stderr_)) << stderr_;
391 }
392 
TEST_F(PerfettoCmdlineTest,TxtConfig)393 TEST_F(PerfettoCmdlineTest, TxtConfig) {
394   std::string cfg("duration_ms: 100");
395   auto perfetto = ExecPerfetto({"-c", "-", "--txt", "-o", "-"}, cfg);
396   StartServiceIfRequiredNoNewExecsAfterThis();
397   EXPECT_EQ(0, perfetto.Run(&stderr_)) << stderr_;
398 }
399 
TEST_F(PerfettoCmdlineTest,SimpleConfig)400 TEST_F(PerfettoCmdlineTest, SimpleConfig) {
401   auto perfetto = ExecPerfetto({"-o", "-", "-c", "-", "-t", "100ms"});
402   StartServiceIfRequiredNoNewExecsAfterThis();
403   EXPECT_EQ(0, perfetto.Run(&stderr_)) << stderr_;
404 }
405 
TEST_F(PerfettoCmdlineTest,DetachAndAttach)406 TEST_F(PerfettoCmdlineTest, DetachAndAttach) {
407   auto attach_to_not_existing = ExecPerfetto({"--attach=not_existent"});
408 
409   std::string cfg("duration_ms: 10000; write_into_file: true");
410   auto detach_valid_stop =
411       ExecPerfetto({"-o", "-", "-c", "-", "--txt", "--detach=valid_stop"}, cfg);
412   auto stop_valid_stop = ExecPerfetto({"--attach=valid_stop", "--stop"});
413 
414   StartServiceIfRequiredNoNewExecsAfterThis();
415 
416   EXPECT_NE(0, attach_to_not_existing.Run(&stderr_));
417   EXPECT_THAT(stderr_, HasSubstr("Session re-attach failed"));
418 
419   EXPECT_EQ(0, detach_valid_stop.Run(&stderr_)) << stderr_;
420   EXPECT_EQ(0, stop_valid_stop.Run(&stderr_));
421 }
422 
TEST_F(PerfettoCmdlineTest,StartTracingTrigger)423 TEST_F(PerfettoCmdlineTest, StartTracingTrigger) {
424   protos::gen::TraceConfig trace_config =
425       CreateTraceConfigForTest(kTestMessageCount, kTestMessageSize);
426   auto* trigger_cfg = trace_config.mutable_trigger_config();
427   trigger_cfg->set_trigger_mode(
428       protos::gen::TraceConfig::TriggerConfig::START_TRACING);
429   trigger_cfg->set_trigger_timeout_ms(15000);
430   auto* trigger = trigger_cfg->add_triggers();
431   trigger->set_name("trigger_name");
432   // |stop_delay_ms| must be long enough that we can write the packets in
433   // before the trace finishes. This has to be long enough for the slowest
434   // emulator. But as short as possible to prevent the test running a long
435   // time.
436   trigger->set_stop_delay_ms(500);
437 
438   // We have to construct all the processes we want to fork before we start the
439   // service with |StartServiceIfRequired()|. this is because it is unsafe
440   // (could deadlock) to fork after we've spawned some threads which might
441   // printf (and thus hold locks).
442   const std::string path = RandomTraceFileName();
443   ScopedFileRemove remove_on_test_exit(path);
444   auto perfetto_proc = ExecPerfetto(
445       {
446           "-o",
447           path,
448           "-c",
449           "-",
450       },
451       trace_config.SerializeAsString());
452 
453   auto trigger_proc = ExecTrigger({"trigger_name"});
454 
455   // Start the service and connect a simple fake producer.
456   StartServiceIfRequiredNoNewExecsAfterThis();
457 
458   auto* fake_producer = test_helper().ConnectFakeProducer();
459   EXPECT_TRUE(fake_producer);
460 
461   // Start a background thread that will deliver the config now that we've
462   // started the service. See |perfetto_proc| above for the args passed.
463   std::thread background_trace([&perfetto_proc]() {
464     std::string stderr_str;
465     EXPECT_EQ(0, perfetto_proc.Run(&stderr_str)) << stderr_str;
466   });
467 
468   test_helper().WaitForProducerSetup();
469   EXPECT_EQ(0, trigger_proc.Run(&stderr_));
470 
471   // Wait for the producer to start, and then write out some test packets.
472   test_helper().WaitForProducerEnabled();
473   auto on_data_written = task_runner_.CreateCheckpoint("data_written");
474   fake_producer->ProduceEventBatch(test_helper().WrapTask(on_data_written));
475   task_runner_.RunUntilCheckpoint("data_written");
476   background_trace.join();
477 
478   protos::gen::Trace trace;
479   ASSERT_TRUE(ParseNotEmptyTraceFromFile(path, trace));
480   ExpectTraceContainsConfigWithTriggerMode(
481       trace, protos::gen::TraceConfig::TriggerConfig::START_TRACING);
482   EXPECT_THAT(GetReceivedTriggerNames(trace), ElementsAre("trigger_name"));
483   ExpectTraceContainsTestMessages(trace, kTestMessageCount);
484   ExpectTraceContainsTestMessagesWithSize(trace, kTestMessageSize);
485 }
486 
TEST_F(PerfettoCmdlineTest,StopTracingTrigger)487 TEST_F(PerfettoCmdlineTest, StopTracingTrigger) {
488   protos::gen::TraceConfig trace_config =
489       CreateTraceConfigForTest(kTestMessageCount, kTestMessageSize);
490   auto* trigger_cfg = trace_config.mutable_trigger_config();
491   trigger_cfg->set_trigger_mode(
492       protos::gen::TraceConfig::TriggerConfig::STOP_TRACING);
493   trigger_cfg->set_trigger_timeout_ms(15000);
494   auto* trigger = trigger_cfg->add_triggers();
495   trigger->set_name("trigger_name");
496   // |stop_delay_ms| must be long enough that we can write the packets in
497   // before the trace finishes. This has to be long enough for the slowest
498   // emulator. But as short as possible to prevent the test running a long
499   // time.
500   trigger->set_stop_delay_ms(500);
501   trigger = trigger_cfg->add_triggers();
502   trigger->set_name("trigger_name_3");
503   trigger->set_stop_delay_ms(60000);
504 
505   // We have to construct all the processes we want to fork before we start the
506   // service with |StartServiceIfRequired()|. this is because it is unsafe
507   // (could deadlock) to fork after we've spawned some threads which might
508   // printf (and thus hold locks).
509   const std::string path = RandomTraceFileName();
510   ScopedFileRemove remove_on_test_exit(path);
511   auto perfetto_proc = ExecPerfetto(
512       {
513           "-o",
514           path,
515           "-c",
516           "-",
517       },
518       trace_config.SerializeAsString());
519 
520   auto trigger_proc =
521       ExecTrigger({"trigger_name_2", "trigger_name", "trigger_name_3"});
522 
523   // Start the service and connect a simple fake producer.
524   StartServiceIfRequiredNoNewExecsAfterThis();
525   auto* fake_producer = test_helper().ConnectFakeProducer();
526   EXPECT_TRUE(fake_producer);
527 
528   // Start a background thread that will deliver the config now that we've
529   // started the service. See |perfetto_proc| above for the args passed.
530   std::thread background_trace([&perfetto_proc]() {
531     std::string stderr_str;
532     EXPECT_EQ(0, perfetto_proc.Run(&stderr_str)) << stderr_str;
533   });
534 
535   test_helper().WaitForProducerEnabled();
536   // Wait for the producer to start, and then write out some test packets,
537   // before the trace actually starts (the trigger is seen).
538   auto on_data_written = task_runner_.CreateCheckpoint("data_written_1");
539   fake_producer->ProduceEventBatch(test_helper().WrapTask(on_data_written));
540   task_runner_.RunUntilCheckpoint("data_written_1");
541 
542   EXPECT_EQ(0, trigger_proc.Run(&stderr_)) << "stderr: " << stderr_;
543 
544   background_trace.join();
545 
546   protos::gen::Trace trace;
547   ASSERT_TRUE(ParseNotEmptyTraceFromFile(path, trace));
548   ExpectTraceContainsConfigWithTriggerMode(
549       trace, protos::gen::TraceConfig::TriggerConfig::STOP_TRACING);
550   EXPECT_THAT(GetReceivedTriggerNames(trace),
551               ElementsAre("trigger_name", "trigger_name_3"));
552   ExpectTraceContainsTestMessages(trace, kTestMessageCount);
553   ExpectTraceContainsTestMessagesWithSize(trace, kTestMessageSize);
554 }
555 
556 // Dropbox on the commandline client only works on android builds. So disable
557 // this test on all other builds.
TEST_F(PerfettoCmdlineTest,AndroidOnly (NoDataNoFileWithoutTrigger))558 TEST_F(PerfettoCmdlineTest, AndroidOnly(NoDataNoFileWithoutTrigger)) {
559   protos::gen::TraceConfig trace_config =
560       CreateTraceConfigForTest(kTestMessageCount, kTestMessageSize);
561   auto* incident_config = trace_config.mutable_incident_report_config();
562   incident_config->set_destination_package("foo.bar.baz");
563   auto* trigger_cfg = trace_config.mutable_trigger_config();
564   trigger_cfg->set_trigger_mode(
565       protos::gen::TraceConfig::TriggerConfig::STOP_TRACING);
566   trigger_cfg->set_trigger_timeout_ms(1000);
567   auto* trigger = trigger_cfg->add_triggers();
568   trigger->set_name("trigger_name");
569   // |stop_delay_ms| must be long enough that we can write the packets in
570   // before the trace finishes. This has to be long enough for the slowest
571   // emulator. But as short as possible to prevent the test running a long
572   // time.
573   trigger->set_stop_delay_ms(500);
574   trigger = trigger_cfg->add_triggers();
575 
576   // We have to construct all the processes we want to fork before we start the
577   // service with |StartServiceIfRequired()|. this is because it is unsafe
578   // (could deadlock) to fork after we've spawned some threads which might
579   // printf (and thus hold locks).
580   const std::string path = RandomTraceFileName();
581   ScopedFileRemove remove_on_test_exit(path);
582   auto perfetto_proc = ExecPerfetto(
583       {
584           "--dropbox",
585           "TAG",
586           "--no-guardrails",
587           "-c",
588           "-",
589       },
590       trace_config.SerializeAsString());
591 
592   StartServiceIfRequiredNoNewExecsAfterThis();
593   auto* fake_producer = test_helper().ConnectFakeProducer();
594   EXPECT_TRUE(fake_producer);
595 
596   std::string stderr_str;
597   std::thread background_trace([&perfetto_proc, &stderr_str]() {
598     EXPECT_EQ(0, perfetto_proc.Run(&stderr_str));
599   });
600   background_trace.join();
601 
602   EXPECT_THAT(stderr_str,
603               ::testing::HasSubstr("Skipping write to incident. Empty trace."));
604 }
605 
TEST_F(PerfettoCmdlineTest,StopTracingTriggerFromConfig)606 TEST_F(PerfettoCmdlineTest, StopTracingTriggerFromConfig) {
607   protos::gen::TraceConfig trace_config =
608       CreateTraceConfigForTest(kTestMessageCount, kTestMessageSize);
609   auto* trigger_cfg = trace_config.mutable_trigger_config();
610   trigger_cfg->set_trigger_mode(
611       protos::gen::TraceConfig::TriggerConfig::STOP_TRACING);
612   trigger_cfg->set_trigger_timeout_ms(15000);
613   auto* trigger = trigger_cfg->add_triggers();
614   trigger->set_name("trigger_name");
615   // |stop_delay_ms| must be long enough that we can write the packets in
616   // before the trace finishes. This has to be long enough for the slowest
617   // emulator. But as short as possible to prevent the test running a long
618   // time.
619   trigger->set_stop_delay_ms(500);
620   trigger = trigger_cfg->add_triggers();
621   trigger->set_name("trigger_name_3");
622   trigger->set_stop_delay_ms(60000);
623 
624   // We have to construct all the processes we want to fork before we start the
625   // service with |StartServiceIfRequired()|. this is because it is unsafe
626   // (could deadlock) to fork after we've spawned some threads which might
627   // printf (and thus hold locks).
628   const std::string path = RandomTraceFileName();
629   ScopedFileRemove remove_on_test_exit(path);
630   auto perfetto_proc = ExecPerfetto(
631       {
632           "-o",
633           path,
634           "-c",
635           "-",
636       },
637       trace_config.SerializeAsString());
638 
639   std::string triggers = R"(
640     activate_triggers: "trigger_name_2"
641     activate_triggers: "trigger_name"
642     activate_triggers: "trigger_name_3"
643   )";
644   auto perfetto_proc_2 = ExecPerfetto(
645       {
646           "-o",
647           path,
648           "-c",
649           "-",
650           "--txt",
651       },
652       triggers);
653 
654   // Start the service and connect a simple fake producer.
655   StartServiceIfRequiredNoNewExecsAfterThis();
656   auto* fake_producer = test_helper().ConnectFakeProducer();
657   EXPECT_TRUE(fake_producer);
658 
659   std::thread background_trace([&perfetto_proc]() {
660     std::string stderr_str;
661     EXPECT_EQ(0, perfetto_proc.Run(&stderr_str)) << stderr_str;
662   });
663 
664   test_helper().WaitForProducerEnabled();
665   // Wait for the producer to start, and then write out some test packets,
666   // before the trace actually starts (the trigger is seen).
667   auto on_data_written = task_runner_.CreateCheckpoint("data_written_1");
668   fake_producer->ProduceEventBatch(test_helper().WrapTask(on_data_written));
669   task_runner_.RunUntilCheckpoint("data_written_1");
670 
671   EXPECT_EQ(0, perfetto_proc_2.Run(&stderr_)) << "stderr: " << stderr_;
672 
673   background_trace.join();
674 
675   protos::gen::Trace trace;
676   ASSERT_TRUE(ParseNotEmptyTraceFromFile(path, trace));
677   EXPECT_LT(static_cast<int>(kTestMessageCount), trace.packet_size());
678   ExpectTraceContainsConfigWithTriggerMode(
679       trace, protos::gen::TraceConfig::TriggerConfig::STOP_TRACING);
680   EXPECT_THAT(GetReceivedTriggerNames(trace),
681               ElementsAre("trigger_name", "trigger_name_3"));
682   ExpectTraceContainsTestMessages(trace, kTestMessageCount);
683   ExpectTraceContainsTestMessagesWithSize(trace, kTestMessageSize);
684 }
685 
TEST_F(PerfettoCmdlineTest,TriggerFromConfigStopsFileOpening)686 TEST_F(PerfettoCmdlineTest, TriggerFromConfigStopsFileOpening) {
687   protos::gen::TraceConfig trace_config =
688       CreateTraceConfigForTest(kTestMessageCount, kTestMessageSize);
689   auto* trigger_cfg = trace_config.mutable_trigger_config();
690   trigger_cfg->set_trigger_mode(
691       protos::gen::TraceConfig::TriggerConfig::STOP_TRACING);
692   trigger_cfg->set_trigger_timeout_ms(15000);
693   auto* trigger = trigger_cfg->add_triggers();
694   trigger->set_name("trigger_name");
695   // |stop_delay_ms| must be long enough that we can write the packets in
696   // before the trace finishes. This has to be long enough for the slowest
697   // emulator. But as short as possible to prevent the test running a long
698   // time.
699   trigger->set_stop_delay_ms(500);
700   trigger = trigger_cfg->add_triggers();
701   trigger->set_name("trigger_name_3");
702   trigger->set_stop_delay_ms(60000);
703 
704   // We have to construct all the processes we want to fork before we start the
705   // service with |StartServiceIfRequired()|. this is because it is unsafe
706   // (could deadlock) to fork after we've spawned some threads which might
707   // printf (and thus hold locks).
708   const std::string path = RandomTraceFileName();
709   ScopedFileRemove remove_on_test_exit(path);
710   std::string triggers = R"(
711     activate_triggers: "trigger_name_2"
712     activate_triggers: "trigger_name"
713     activate_triggers: "trigger_name_3"
714   )";
715   auto perfetto_proc = ExecPerfetto(
716       {
717           "-o",
718           path,
719           "-c",
720           "-",
721           "--txt",
722       },
723       triggers);
724 
725   // Start the service and connect a simple fake producer.
726   StartServiceIfRequiredNoNewExecsAfterThis();
727   auto* fake_producer = test_helper().ConnectFakeProducer();
728   EXPECT_TRUE(fake_producer);
729 
730   std::string trace_str;
731   EXPECT_FALSE(base::ReadFile(path, &trace_str));
732 
733   EXPECT_EQ(0, perfetto_proc.Run(&stderr_)) << "stderr: " << stderr_;
734 
735   EXPECT_FALSE(base::ReadFile(path, &trace_str));
736 }
737 
TEST_F(PerfettoCmdlineTest,Query)738 TEST_F(PerfettoCmdlineTest, Query) {
739   auto query = ExecPerfetto({"--query"});
740   auto query_raw = ExecPerfetto({"--query-raw"});
741   StartServiceIfRequiredNoNewExecsAfterThis();
742   EXPECT_EQ(0, query.Run(&stderr_)) << stderr_;
743   EXPECT_EQ(0, query_raw.Run(&stderr_)) << stderr_;
744 }
745 
TEST_F(PerfettoCmdlineTest,AndroidOnly (CmdTriggerWithUploadFlag))746 TEST_F(PerfettoCmdlineTest, AndroidOnly(CmdTriggerWithUploadFlag)) {
747   protos::gen::TraceConfig trace_config =
748       CreateTraceConfigForTest(kTestMessageCount, kTestMessageSize);
749   auto* trigger_cfg = trace_config.mutable_trigger_config();
750   trigger_cfg->set_trigger_mode(
751       protos::gen::TraceConfig::TriggerConfig::STOP_TRACING);
752   trigger_cfg->set_trigger_timeout_ms(15000);
753   auto* trigger = trigger_cfg->add_triggers();
754   trigger->set_name("trigger_name");
755   // |stop_delay_ms| must be long enough that we can write the packets in
756   // before the trace finishes. This has to be long enough for the slowest
757   // emulator. But as short as possible to prevent the test running a long
758   // time.
759   trigger->set_stop_delay_ms(500);
760 
761   // We have to construct all the processes we want to fork before we start the
762   // service with |StartServiceIfRequired()|. this is because it is unsafe
763   // (could deadlock) to fork after we've spawned some threads which might
764   // printf (and thus hold locks).
765   const std::string path = RandomTraceFileName();
766   ScopedFileRemove remove_on_test_exit(path);
767   auto perfetto_proc = ExecPerfetto(
768       {
769           "-o",
770           path,
771           "-c",
772           "-",
773       },
774       trace_config.SerializeAsString());
775 
776   std::string triggers = R"(
777     activate_triggers: "trigger_name"
778   )";
779   auto perfetto_proc_2 = ExecPerfetto(
780       {
781           "--upload",
782           "-c",
783           "-",
784           "--txt",
785       },
786       triggers);
787 
788   // Start the service and connect a simple fake producer.
789   StartServiceIfRequiredNoNewExecsAfterThis();
790   auto* fake_producer = test_helper().ConnectFakeProducer();
791   EXPECT_TRUE(fake_producer);
792 
793   std::thread background_trace([&perfetto_proc]() {
794     std::string stderr_str;
795     EXPECT_EQ(0, perfetto_proc.Run(&stderr_str)) << stderr_str;
796   });
797 
798   test_helper().WaitForProducerEnabled();
799   // Wait for the producer to start, and then write out some test packets,
800   // before the trace actually starts (the trigger is seen).
801   auto on_data_written = task_runner_.CreateCheckpoint("data_written_1");
802   fake_producer->ProduceEventBatch(test_helper().WrapTask(on_data_written));
803   task_runner_.RunUntilCheckpoint("data_written_1");
804 
805   EXPECT_EQ(0, perfetto_proc_2.Run(&stderr_)) << "stderr: " << stderr_;
806 
807   background_trace.join();
808 
809   protos::gen::Trace trace;
810   ASSERT_TRUE(ParseNotEmptyTraceFromFile(path, trace));
811   ExpectTraceContainsTestMessages(trace, kTestMessageCount);
812   ExpectTraceContainsTestMessagesWithSize(trace, kTestMessageSize);
813   EXPECT_LT(static_cast<int>(kTestMessageCount), trace.packet_size());
814   EXPECT_THAT(trace.packet(),
815               Contains(Property(&protos::gen::TracePacket::trigger,
816                                 Property(&protos::gen::Trigger::trigger_name,
817                                          Eq("trigger_name")))));
818 }
819 
TEST_F(PerfettoCmdlineTest,TriggerCloneSnapshot)820 TEST_F(PerfettoCmdlineTest, TriggerCloneSnapshot) {
821   protos::gen::TraceConfig trace_config =
822       CreateTraceConfigForTest(kTestMessageCount, kTestMessageSize);
823   auto* trigger_cfg = trace_config.mutable_trigger_config();
824   trigger_cfg->set_trigger_mode(
825       protos::gen::TraceConfig::TriggerConfig::CLONE_SNAPSHOT);
826   trigger_cfg->set_trigger_timeout_ms(600000);
827   auto* trigger = trigger_cfg->add_triggers();
828   trigger->set_name("trigger_name");
829   // |stop_delay_ms| must be long enough that we can write the packets in
830   // before the trace finishes. This has to be long enough for the slowest
831   // emulator. But as short as possible to prevent the test running a long
832   // time.
833   trigger->set_stop_delay_ms(500);
834 
835   // We have to construct all the processes we want to fork before we start the
836   // service with |StartServiceIfRequired()|. this is because it is unsafe
837   // (could deadlock) to fork after we've spawned some threads which might
838   // printf (and thus hold locks).
839   const std::string path = RandomTraceFileName();
840   ScopedFileRemove remove_on_test_exit(path);
841   auto perfetto_proc = ExecPerfetto(
842       {
843           "-o",
844           path,
845           "-c",
846           "-",
847       },
848       trace_config.SerializeAsString());
849 
850   std::string triggers = R"(
851     activate_triggers: "trigger_name"
852   )";
853   auto trigger_proc = ExecPerfetto(
854       {
855           "-c",
856           "-",
857           "--txt",
858       },
859       triggers);
860 
861   // Start the service and connect a simple fake producer.
862   StartServiceIfRequiredNoNewExecsAfterThis();
863   auto* fake_producer = test_helper().ConnectFakeProducer();
864   EXPECT_TRUE(fake_producer);
865 
866   std::thread background_trace([&perfetto_proc]() {
867     std::string stderr_str;
868     EXPECT_EQ(0, perfetto_proc.Run(&stderr_str)) << stderr_str;
869   });
870 
871   test_helper().WaitForProducerEnabled();
872   // Wait for the producer to start, and then write out some test packets,
873   // before the trace actually starts (the trigger is seen).
874   auto on_data_written = task_runner_.CreateCheckpoint("data_written_1");
875   fake_producer->ProduceEventBatch(test_helper().WrapTask(on_data_written));
876   task_runner_.RunUntilCheckpoint("data_written_1");
877 
878   EXPECT_EQ(0, trigger_proc.Run(&stderr_)) << "stderr: " << stderr_;
879 
880   // Now we need to wait that the `perfetto_proc` creates the snapshot trace
881   // file in the trace/path.0 file (appending .0). Once that is done we can
882   // kill the perfetto cmd (otherwise it will keep running for the whole
883   // trigger_timeout_ms, unlike the case of STOP_TRACING.
884   std::string snapshot_path = path + ".0";
885   for (int i = 0; i < 100 && !base::FileExists(snapshot_path); i++) {
886     std::this_thread::sleep_for(std::chrono::milliseconds(100));
887   }
888   ASSERT_TRUE(base::FileExists(snapshot_path));
889 
890   perfetto_proc.SendSigterm();
891   background_trace.join();
892 
893   protos::gen::Trace trace;
894   ASSERT_TRUE(ParseNotEmptyTraceFromFile(snapshot_path, trace));
895   ExpectTraceContainsTestMessages(trace, kTestMessageCount);
896   ExpectTraceContainsTestMessagesWithSize(trace, kTestMessageSize);
897   EXPECT_LT(static_cast<int>(kTestMessageCount), trace.packet_size());
898   EXPECT_THAT(trace.packet(),
899               Contains(Property(&protos::gen::TracePacket::trigger,
900                                 Property(&protos::gen::Trigger::trigger_name,
901                                          Eq("trigger_name")))));
902 }
903 
TEST_F(PerfettoCmdlineTest,MultipleTriggersCloneSnapshot)904 TEST_F(PerfettoCmdlineTest, MultipleTriggersCloneSnapshot) {
905   protos::gen::TraceConfig trace_config =
906       CreateTraceConfigForTest(kTestMessageCount, kTestMessageSize);
907   auto* trigger_cfg = trace_config.mutable_trigger_config();
908   trigger_cfg->set_trigger_mode(
909       protos::gen::TraceConfig::TriggerConfig::CLONE_SNAPSHOT);
910   trigger_cfg->set_trigger_timeout_ms(600000);
911   // Add two triggers, the "trigger_name_2" hits before "trigger_name_1".
912   auto* trigger = trigger_cfg->add_triggers();
913   trigger->set_name("trigger_name_1");
914   trigger->set_stop_delay_ms(1500);
915   trigger = trigger_cfg->add_triggers();
916   trigger->set_name("trigger_name_2");
917   trigger->set_stop_delay_ms(500);
918 
919   // We have to construct all the processes we want to fork before we start the
920   // service with |StartServiceIfRequired()|. this is because it is unsafe
921   // (could deadlock) to fork after we've spawned some threads which might
922   // printf (and thus hold locks).
923   const std::string path = RandomTraceFileName();
924   ScopedFileRemove remove_on_test_exit(path);
925   auto perfetto_proc = ExecPerfetto(
926       {
927           "-o",
928           path,
929           "-c",
930           "-",
931       },
932       trace_config.SerializeAsString());
933 
934   auto triggers_proc = ExecTrigger({"trigger_name_1", "trigger_name_2"});
935 
936   // Start the service and connect a simple fake producer.
937   StartServiceIfRequiredNoNewExecsAfterThis();
938   auto* fake_producer = test_helper().ConnectFakeProducer();
939   EXPECT_TRUE(fake_producer);
940 
941   std::thread background_trace([&perfetto_proc]() {
942     std::string stderr_str;
943     EXPECT_EQ(0, perfetto_proc.Run(&stderr_str)) << stderr_str;
944   });
945 
946   test_helper().WaitForProducerEnabled();
947   // Wait for the producer to start, and then write out some test packets,
948   // before the trace actually starts (the trigger is seen).
949   auto on_data_written = task_runner_.CreateCheckpoint("data_written_1");
950   fake_producer->ProduceEventBatch(test_helper().WrapTask(on_data_written));
951   task_runner_.RunUntilCheckpoint("data_written_1");
952 
953   EXPECT_EQ(0, triggers_proc.Run(&stderr_)) << "stderr: " << stderr_;
954 
955   // Wait for both clone triggers to hit and wait for two snapshot files.
956   std::string snapshot_path = path + ".0";
957   for (int i = 0; i < 100 && !base::FileExists(snapshot_path); i++) {
958     std::this_thread::sleep_for(std::chrono::milliseconds(100));
959   }
960   ASSERT_TRUE(base::FileExists(snapshot_path));
961 
962   std::string snapshot_path_2 = path + ".1";
963   for (int i = 0; i < 100 && !base::FileExists(snapshot_path_2); i++) {
964     std::this_thread::sleep_for(std::chrono::milliseconds(100));
965   }
966   ASSERT_TRUE(base::FileExists(snapshot_path_2));
967 
968   perfetto_proc.SendSigterm();
969   background_trace.join();
970 
971   // We now have two traces, the first one was cloned by "trigger_name_2",
972   // the second was cloned by "trigger_name_1".
973 
974   // Asserts for the first trace.
975   protos::gen::Trace trace;
976   ASSERT_TRUE(ParseNotEmptyTraceFromFile(snapshot_path, trace));
977   EXPECT_LT(static_cast<int>(kTestMessageCount), trace.packet_size());
978   EXPECT_THAT(GetReceivedTriggerNames(trace),
979               ElementsAre("trigger_name_1", "trigger_name_2"));
980 
981   std::vector<protos::gen::TracePacket> clone_trigger_packets;
982   protos::gen::TracePacket trigger_packet;
983   for (const auto& packet : trace.packet()) {
984     if (packet.has_clone_snapshot_trigger()) {
985       clone_trigger_packets.push_back(packet);
986     } else if (packet.has_trigger() &&
987                packet.trigger().trigger_name() == "trigger_name_2") {
988       trigger_packet = packet;
989     }
990   }
991   ASSERT_EQ(clone_trigger_packets.size(), 1ul);
992   EXPECT_EQ(clone_trigger_packets[0].clone_snapshot_trigger().trigger_name(),
993             "trigger_name_2");
994   // Assert that all fields of 'clone_snapshot_trigger' equal to the same fields
995   // of a 'trigger'.
996   EXPECT_EQ(clone_trigger_packets[0].timestamp(), trigger_packet.timestamp());
997   EXPECT_EQ(clone_trigger_packets[0].clone_snapshot_trigger(),
998             trigger_packet.trigger());
999 
1000   // Asserts for the second trace.
1001   protos::gen::Trace trace_2;
1002   ASSERT_TRUE(ParseNotEmptyTraceFromFile(snapshot_path_2, trace_2));
1003   EXPECT_LT(static_cast<int>(kTestMessageCount), trace_2.packet_size());
1004   // List of received triggers from the main session was cleaned after the first
1005   // clone operation happened, the list is empty in the second trace.
1006   EXPECT_THAT(GetReceivedTriggerNames(trace_2), IsEmpty());
1007 
1008   std::vector<protos::gen::TracePacket> clone_trigger_packets_2;
1009   for (const auto& packet : trace_2.packet()) {
1010     if (packet.has_clone_snapshot_trigger()) {
1011       clone_trigger_packets_2.push_back(packet);
1012     }
1013   }
1014   ASSERT_EQ(clone_trigger_packets_2.size(), 1ul);
1015   EXPECT_EQ(clone_trigger_packets_2[0].clone_snapshot_trigger().trigger_name(),
1016             "trigger_name_1");
1017 
1018   // There is no triggers in the second snapshot, but we can compare the
1019   // "clone_snapshot_trigger" with the trigger saved into the first snapshot.
1020   protos::gen::TracePacket trigger_packet_from_first_snapshot;
1021   for (const auto& packet : trace.packet()) {
1022     if (packet.has_trigger() &&
1023         packet.trigger().trigger_name() == "trigger_name_1") {
1024       trigger_packet_from_first_snapshot = packet;
1025     }
1026   }
1027   // Assert that all fields of 'clone_snapshot_trigger' equal to the same fields
1028   // of a 'trigger'.
1029   EXPECT_EQ(clone_trigger_packets_2[0].timestamp(),
1030             trigger_packet_from_first_snapshot.timestamp());
1031   EXPECT_EQ(clone_trigger_packets_2[0].clone_snapshot_trigger(),
1032             trigger_packet_from_first_snapshot.trigger());
1033 }
1034 
TEST_F(PerfettoCmdlineTest,SaveForBugreport)1035 TEST_F(PerfettoCmdlineTest, SaveForBugreport) {
1036   TraceConfig trace_config = CreateTraceConfigForBugreportTest();
1037   RunBugreportTest(std::move(trace_config));
1038 }
1039 
TEST_F(PerfettoCmdlineTest,SaveForBugreport_WriteIntoFile)1040 TEST_F(PerfettoCmdlineTest, SaveForBugreport_WriteIntoFile) {
1041   TraceConfig trace_config = CreateTraceConfigForBugreportTest();
1042   trace_config.set_file_write_period_ms(60000);  // Will never hit this.
1043   trace_config.set_write_into_file(true);
1044   RunBugreportTest(std::move(trace_config));
1045 }
1046 
TEST_F(PerfettoCmdlineTest,Clone)1047 TEST_F(PerfettoCmdlineTest, Clone) {
1048   TraceConfig trace_config = CreateTraceConfigForBugreportTest();
1049   RunBugreportTest(std::move(trace_config), /*check_original_trace=*/true,
1050                    /*use_explicit_clone=*/true);
1051 }
1052 
TEST_F(PerfettoCmdlineTest,CloneByName)1053 TEST_F(PerfettoCmdlineTest, CloneByName) {
1054   protos::gen::TraceConfig trace_config =
1055       CreateTraceConfigForTest(kTestMessageCount, kTestMessageSize);
1056   trace_config.set_unique_session_name("my_unique_session_name");
1057 
1058   // We have to construct all the processes we want to fork before we start the
1059   // service with |StartServiceIfRequired()|. this is because it is unsafe
1060   // (could deadlock) to fork after we've spawned some threads which might
1061   // printf (and thus hold locks).
1062   const std::string path = RandomTraceFileName();
1063   ScopedFileRemove remove_on_test_exit(path);
1064   auto perfetto_proc = ExecPerfetto(
1065       {
1066           "-o",
1067           path,
1068           "-c",
1069           "-",
1070       },
1071       trace_config.SerializeAsString());
1072 
1073   const std::string path_cloned = RandomTraceFileName();
1074   ScopedFileRemove path_cloned_remove(path_cloned);
1075   auto perfetto_proc_clone = ExecPerfetto({
1076       "-o",
1077       path_cloned,
1078       "--clone-by-name",
1079       "my_unique_session_name",
1080   });
1081 
1082   const std::string path_cloned_2 = RandomTraceFileName();
1083   ScopedFileRemove path_cloned_2_remove(path_cloned_2);
1084   auto perfetto_proc_clone_2 = ExecPerfetto({
1085       "-o",
1086       path_cloned_2,
1087       "--clone-by-name",
1088       "non_existing_session_name",
1089   });
1090 
1091   // Start the service and connect a simple fake producer.
1092   StartServiceIfRequiredNoNewExecsAfterThis();
1093   auto* fake_producer = test_helper().ConnectFakeProducer();
1094   EXPECT_TRUE(fake_producer);
1095 
1096   std::thread background_trace([&perfetto_proc]() {
1097     std::string stderr_str;
1098     EXPECT_EQ(0, perfetto_proc.Run(&stderr_str)) << stderr_str;
1099   });
1100 
1101   test_helper().WaitForProducerEnabled();
1102 
1103   auto on_data_written = task_runner_.CreateCheckpoint("data_written_1");
1104   fake_producer->ProduceEventBatch(test_helper().WrapTask(on_data_written));
1105   task_runner_.RunUntilCheckpoint("data_written_1");
1106 
1107   EXPECT_EQ(0, perfetto_proc_clone.Run(&stderr_)) << "stderr: " << stderr_;
1108   EXPECT_TRUE(base::FileExists(path_cloned));
1109 
1110   // The command still returns 0, but doesn't create a file.
1111   EXPECT_EQ(0, perfetto_proc_clone_2.Run(&stderr_)) << "stderr: " << stderr_;
1112   EXPECT_FALSE(base::FileExists(path_cloned_2));
1113 
1114   protos::gen::Trace cloned_trace;
1115   ASSERT_TRUE(ParseNotEmptyTraceFromFile(path_cloned, cloned_trace));
1116   ExpectTraceContainsTestMessages(cloned_trace, kTestMessageCount);
1117   ExpectTraceContainsTestMessagesWithSize(cloned_trace, kTestMessageSize);
1118 
1119   perfetto_proc.SendSigterm();
1120   background_trace.join();
1121 
1122   protos::gen::Trace trace;
1123   ASSERT_TRUE(ParseNotEmptyTraceFromFile(path, trace));
1124   ExpectTraceContainsTestMessages(trace, kTestMessageCount);
1125   ExpectTraceContainsTestMessagesWithSize(trace, kTestMessageSize);
1126 }
1127 
1128 // Regression test for b/279753347: --save-for-bugreport would create an empty
1129 // file if no session with bugreport_score was active.
TEST_F(PerfettoCmdlineTest,UnavailableBugreportLeavesNoEmptyFiles)1130 TEST_F(PerfettoCmdlineTest, UnavailableBugreportLeavesNoEmptyFiles) {
1131   ScopedFileRemove remove_on_test_exit(GetBugreportTracePath());
1132   Exec perfetto_br_proc = ExecPerfetto({"--save-for-bugreport"});
1133   StartServiceIfRequiredNoNewExecsAfterThis();
1134   perfetto_br_proc.Run(&stderr_);
1135   // No file exists. Great.
1136   if (!base::FileExists(GetBugreportTracePath())) {
1137     return;
1138   }
1139   // A file exists. There are two possiblilities:
1140   // 1. There was a bugreport_score session.
1141   // 2. There was no bugreport_score session and we're hitting b/279753347.
1142   //
1143   // Let's check that we're not hitting b/279753347, by checking that the file
1144   // is not empty.
1145   EXPECT_NE(base::GetFileSize(GetBugreportTracePath()), 0);
1146 }
1147 
1148 // Tests that SaveTraceForBugreport() works also if the trace has triggers
1149 // defined and those triggers have not been hit. This is a regression test for
1150 // b/188008375 .
1151 #if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
1152 // Disabled due to b/191940560
1153 #define MAYBE_SaveForBugreport_Triggers DISABLED_SaveForBugreport_Triggers
1154 #else
1155 #define MAYBE_SaveForBugreport_Triggers SaveForBugreport_Triggers
1156 #endif
TEST_F(PerfettoCmdlineTest,MAYBE_SaveForBugreport_Triggers)1157 TEST_F(PerfettoCmdlineTest, MAYBE_SaveForBugreport_Triggers) {
1158   TraceConfig trace_config = CreateTraceConfigForBugreportTest();
1159   trace_config.set_duration_ms(0);  // set_trigger_timeout_ms is used instead.
1160   auto* trigger_config = trace_config.mutable_trigger_config();
1161   trigger_config->set_trigger_timeout_ms(8.64e+7);
1162   trigger_config->set_trigger_mode(TraceConfig::TriggerConfig::STOP_TRACING);
1163   auto* trigger = trigger_config->add_triggers();
1164   trigger->set_name("trigger_name");
1165   trigger->set_stop_delay_ms(1);
1166   RunBugreportTest(std::move(trace_config), /*check_original_trace=*/false);
1167 }
1168 
TEST_F(PerfettoCmdlineTest,SaveAllForBugreport_NoTraces)1169 TEST_F(PerfettoCmdlineTest, SaveAllForBugreport_NoTraces) {
1170   auto save_all_cmd = ExecPerfetto({"--save-all-for-bugreport"});
1171   StartServiceIfRequiredNoNewExecsAfterThis();
1172   EXPECT_EQ(0, save_all_cmd.Run(&stderr_));
1173   EXPECT_THAT(stderr_, HasSubstr("No tracing sessions eligible"));
1174 }
1175 
TEST_F(PerfettoCmdlineTest,SaveAllForBugreport_FourTraces)1176 TEST_F(PerfettoCmdlineTest, SaveAllForBugreport_FourTraces) {
1177   struct TraceProc {
1178     explicit TraceProc(TraceConfig c) : cfg(std::move(c)) {}
1179 
1180     TraceConfig cfg;
1181     std::optional<Exec> proc;
1182     std::thread thd;
1183   };
1184 
1185   auto remove_br_files = [] {
1186     remove((GetBugreportTraceDir() + "/systrace.pftrace").c_str());
1187     remove((GetBugreportTraceDir() + "/custom_name.pftrace").c_str());
1188     remove((GetBugreportTraceDir() + "/custom_name_1.pftrace").c_str());
1189     remove((GetBugreportTraceDir() + "/systrace_1.pftrace").c_str());
1190   };
1191 
1192   remove_br_files();  // Remove both before and after ending the test.
1193   auto remove_on_exit = base::OnScopeExit(remove_br_files);
1194 
1195   auto session_prefix = "bugreport_test_" +
1196                         std::to_string(base::GetWallTimeNs().count() % 1000000);
1197 
1198   // Create four tracing sessions with different bugreport scores.
1199   // Two of them will have the default "systrace.pftrace" name.
1200   std::vector<TraceProc> traces;
1201   const bool add_filt = true;
1202   traces.emplace_back(CreateTraceConfigForBugreportTest(/*score=*/1, add_filt));
1203   traces.back().cfg.set_unique_session_name(session_prefix + "_1");
1204 
1205   traces.emplace_back(CreateTraceConfigForBugreportTest(/*score=*/2, add_filt));
1206   traces.back().cfg.set_bugreport_filename("custom_name.pftrace");
1207   traces.back().cfg.set_unique_session_name(session_prefix + "_2");
1208 
1209   traces.emplace_back(CreateTraceConfigForBugreportTest(/*score=*/3, add_filt));
1210   traces.back().cfg.set_bugreport_filename("custom_name.pftrace");
1211   traces.back().cfg.set_unique_session_name(session_prefix + "_3");
1212 
1213   traces.emplace_back(CreateTraceConfigForBugreportTest(/*score=*/4, add_filt));
1214   traces.back().cfg.set_unique_session_name(session_prefix + "_4");
1215 
1216   for (auto& trace : traces) {
1217     std::string cfg = trace.cfg.SerializeAsString();
1218     trace.proc = ExecPerfetto({"-o", base::kDevNull, "-c", "-"}, cfg);
1219   }
1220 
1221   Exec perfetto_br_proc = ExecPerfetto({"--save-all-for-bugreport"});
1222 
1223   StartServiceIfRequiredNoNewExecsAfterThis();
1224 
1225   for (auto& trace : traces) {
1226     trace.thd = std::thread([&trace] {
1227       std::string stderr_str;
1228       ASSERT_EQ(0, trace.proc->Run(&stderr_str)) << stderr_str;
1229       PERFETTO_DLOG("perfetto-cmd output:\n%s", stderr_str.c_str());
1230     });
1231   }
1232 
1233   // Wait that all tracing sessions are started.
1234   // Note that in CTS mode, the Android test infra will start other tracing
1235   // sessions for performance reasons. We can't just wait to see 4 sessions,
1236   // we need to actually check the unique session name.
1237   test_helper().ConnectConsumer();
1238   test_helper().WaitForConsumerConnect();
1239   for (;;) {
1240     auto state = test_helper().QueryServiceStateAndWait();
1241     const auto& sessions = state.tracing_sessions();
1242     if (std::count_if(sessions.begin(), sessions.end(),
1243                       [&](const TracingServiceState::TracingSession& s) {
1244                         return base::StartsWith(s.unique_session_name(),
1245                                                 session_prefix);
1246                       }) >= 4) {
1247       break;
1248     }
1249     base::SleepMicroseconds(100 * 1000);
1250   }
1251 
1252   EXPECT_EQ(0, perfetto_br_proc.Run(&stderr_)) << stderr_;
1253   PERFETTO_DLOG("perfetto --save-all-for-bugreport output:\n-----\n%s\n-----\n",
1254                 stderr_.c_str());
1255 
1256   // Stop all the four ongoing traces, which by now got cloned.
1257   for (auto& trace : traces) {
1258     trace.proc->SendSigterm();
1259     trace.thd.join();
1260   }
1261 
1262   auto check_trace = [&](std::string fname, int expected_score) {
1263     std::string fpath = GetBugreportTraceDir() + "/" + fname;
1264     ASSERT_TRUE(base::FileExists(fpath)) << fpath;
1265     protos::gen::Trace trace;
1266     ASSERT_TRUE(ParseNotEmptyTraceFromFile(fpath, trace)) << fpath;
1267     EXPECT_THAT(
1268         trace.packet(),
1269         Contains(Property(&protos::gen::TracePacket::trace_config,
1270                           Property(&protos::gen::TraceConfig::bugreport_score,
1271                                    Eq(expected_score)))));
1272   };
1273 
1274   check_trace("systrace.pftrace", /*expected_score=*/4);
1275   check_trace("custom_name.pftrace", /*expected_score=*/3);
1276   check_trace("custom_name_1.pftrace", /*expected_score=*/2);
1277   check_trace("systrace_1.pftrace", /*expected_score=*/1);
1278 }
1279 
TEST_F(PerfettoCmdlineTest,SaveAllForBugreport_LargeTrace)1280 TEST_F(PerfettoCmdlineTest, SaveAllForBugreport_LargeTrace) {
1281   auto remove_br_files = [] {
1282     remove((GetBugreportTraceDir() + "/systrace.pftrace").c_str());
1283   };
1284 
1285   remove_br_files();  // Remove both before and after ending the test.
1286   auto remove_on_exit = base::OnScopeExit(remove_br_files);
1287 
1288   const uint32_t kMsgCount = 10000;
1289   const uint32_t kMsgSize = 1024;
1290   TraceConfig cfg = CreateTraceConfigForBugreportTest(
1291       /*score=*/1, /*add_filter=*/false, kMsgCount, kMsgSize);
1292 
1293   auto session_name = "bugreport_test_" +
1294                       std::to_string(base::GetWallTimeNs().count() % 1000000);
1295 
1296   cfg.set_unique_session_name(session_name);
1297   std::string cfg_str = cfg.SerializeAsString();
1298   Exec trace_proc = ExecPerfetto({"-o", base::kDevNull, "-c", "-"}, cfg_str);
1299   Exec perfetto_br_proc = ExecPerfetto({"--save-all-for-bugreport"});
1300 
1301   StartServiceIfRequiredNoNewExecsAfterThis();
1302 
1303   auto* fake_producer = test_helper().ConnectFakeProducer();
1304   EXPECT_TRUE(fake_producer);
1305 
1306   std::thread thd([&trace_proc] {
1307     std::string stderr_str;
1308     ASSERT_EQ(0, trace_proc.Run(&stderr_str)) << stderr_str;
1309     PERFETTO_DLOG("perfetto-cmd output:\n%s", stderr_str.c_str());
1310   });
1311 
1312   // Wait that the tracing session is started.
1313   test_helper().ConnectConsumer();
1314   test_helper().WaitForConsumerConnect();
1315   for (;;) {
1316     auto state = test_helper().QueryServiceStateAndWait();
1317     const auto& sessions = state.tracing_sessions();
1318     if (std::count_if(sessions.begin(), sessions.end(),
1319                       [&](const TracingServiceState::TracingSession& s) {
1320                         return s.unique_session_name() == session_name;
1321                       }) >= 1) {
1322       break;
1323     }
1324     base::SleepMicroseconds(100 * 1000);
1325   }
1326   test_helper().SyncAndWaitProducer();
1327 
1328   auto on_data_written = task_runner_.CreateCheckpoint("data_written");
1329   fake_producer->ProduceEventBatch(test_helper().WrapTask(on_data_written));
1330   task_runner_.RunUntilCheckpoint("data_written");
1331 
1332   EXPECT_EQ(0, perfetto_br_proc.Run(&stderr_)) << stderr_;
1333   PERFETTO_DLOG("perfetto --save-all-for-bugreport output:\n-----\n%s\n-----\n",
1334                 stderr_.c_str());
1335 
1336   // Stop the ongoing trace, which by now got cloned.
1337   trace_proc.SendSigterm();
1338   thd.join();
1339 
1340   std::string fpath = GetBugreportTraceDir() + "/systrace.pftrace";
1341   ASSERT_TRUE(base::FileExists(fpath)) << fpath;
1342   protos::gen::Trace trace;
1343   ASSERT_TRUE(ParseNotEmptyTraceFromFile(fpath, trace)) << fpath;
1344   ExpectTraceContainsTestMessages(trace, kMsgCount);
1345   ExpectTraceContainsTestMessagesWithSize(trace, kMsgSize);
1346 }
1347 
1348 }  // namespace perfetto
1349