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