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