1 /*
2 * Copyright (C) 2018 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 <unistd.h>
18
19 #include <chrono>
20 #include <condition_variable>
21 #include <functional>
22 #include <initializer_list>
23 #include <random>
24 #include <thread>
25
26 #include "gmock/gmock.h"
27 #include "gtest/gtest.h"
28 #include "perfetto/base/build_config.h"
29 #include "perfetto/base/file_utils.h"
30 #include "perfetto/base/logging.h"
31 #include "perfetto/base/pipe.h"
32 #include "perfetto/base/temp_file.h"
33 #include "perfetto/traced/traced.h"
34 #include "perfetto/tracing/core/trace_config.h"
35 #include "perfetto/tracing/core/trace_packet.h"
36 #include "src/base/test/test_task_runner.h"
37 #include "src/traced/probes/ftrace/ftrace_controller.h"
38 #include "src/traced/probes/ftrace/ftrace_procfs.h"
39 #include "src/tracing/ipc/default_socket.h"
40 #include "test/task_runner_thread.h"
41 #include "test/task_runner_thread_delegates.h"
42 #include "test/test_helper.h"
43
44 #include "perfetto/trace/trace.pb.h"
45 #include "perfetto/trace/trace_packet.pb.h"
46 #include "perfetto/trace/trace_packet.pbzero.h"
47
48 namespace perfetto {
49
50 namespace {
51
52 using ::testing::ContainsRegex;
53 using ::testing::HasSubstr;
54
RandomTraceFileName()55 std::string RandomTraceFileName() {
56 #if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
57 constexpr char kSysTmpPath[] = "/data/misc/perfetto-traces";
58 #else
59 constexpr char kSysTmpPath[] = "/tmp";
60 #endif
61 static int suffix = 0;
62
63 std::string path;
64 path.assign(kSysTmpPath);
65 path.append("/trace-");
66 path.append(std::to_string(base::GetBootTimeNs().count()));
67 path.append("-");
68 path.append(std::to_string(suffix++));
69 return path;
70 }
71
72 class PerfettoTest : public ::testing::Test {
73 public:
SetUp()74 void SetUp() override {
75 // TODO(primiano): refactor this, it's copy/pasted in three places now.
76 size_t index = 0;
77 constexpr auto kTracingPaths = FtraceController::kTracingPaths;
78 while (!ftrace_procfs_ && kTracingPaths[index]) {
79 ftrace_procfs_ = FtraceProcfs::Create(kTracingPaths[index++]);
80 }
81 if (!ftrace_procfs_)
82 return;
83 ftrace_procfs_->SetTracingOn(false);
84 }
85
TearDown()86 void TearDown() override {
87 if (ftrace_procfs_)
88 ftrace_procfs_->SetTracingOn(false);
89 }
90
91 std::unique_ptr<FtraceProcfs> ftrace_procfs_;
92 };
93
94 class PerfettoCmdlineTest : public ::testing::Test {
95 public:
SetUp()96 void SetUp() override {
97 test_helper_.StartServiceIfRequired();
98 }
99
TearDown()100 void TearDown() override {}
101
ExecPerfetto(std::initializer_list<std::string> args,std::string input="")102 int ExecPerfetto(std::initializer_list<std::string> args,
103 std::string input = "") {
104 return Exec("perfetto", args, input);
105 }
106
ExecTrigger(std::initializer_list<std::string> args,std::string input="")107 int ExecTrigger(std::initializer_list<std::string> args,
108 std::string input = "") {
109 return Exec("trigger_perfetto", args, input);
110 }
111
112 // Fork() + executes the perfetto cmdline client with the given args and
113 // returns the exit code.
Exec(const std::string & argv0,std::initializer_list<std::string> args,std::string input="")114 int Exec(const std::string& argv0,
115 std::initializer_list<std::string> args,
116 std::string input = "") {
117 std::vector<char> argv_buffer;
118 std::vector<size_t> argv_offsets;
119 std::vector<char*> argv;
120 argv_offsets.push_back(0);
121
122 argv_buffer.insert(argv_buffer.end(), argv0.begin(), argv0.end());
123 argv_buffer.push_back('\0');
124
125 for (const std::string& arg : args) {
126 argv_offsets.push_back(argv_buffer.size());
127 argv_buffer.insert(argv_buffer.end(), arg.begin(), arg.end());
128 argv_buffer.push_back('\0');
129 }
130
131 for (size_t off : argv_offsets)
132 argv.push_back(&argv_buffer[off]);
133 argv.push_back(nullptr);
134
135 // Create the pipe for the child process to return stderr.
136 base::Pipe err_pipe = base::Pipe::Create();
137 base::Pipe in_pipe = base::Pipe::Create();
138
139 pid_t pid = fork();
140 PERFETTO_CHECK(pid >= 0);
141 if (pid == 0) {
142 // Child process.
143 err_pipe.rd.reset();
144 in_pipe.wr.reset();
145
146 int devnull = open("/dev/null", O_RDWR);
147 PERFETTO_CHECK(devnull >= 0);
148 PERFETTO_CHECK(dup2(*in_pipe.rd, STDIN_FILENO) != -1);
149 PERFETTO_CHECK(dup2(devnull, STDOUT_FILENO) != -1);
150 PERFETTO_CHECK(dup2(*err_pipe.wr, STDERR_FILENO) != -1);
151 #if PERFETTO_BUILDFLAG(PERFETTO_START_DAEMONS)
152 setenv("PERFETTO_CONSUMER_SOCK_NAME", TestHelper::GetConsumerSocketName(),
153 1);
154 setenv("PERFETTO_PRODUCER_SOCK_NAME", TestHelper::GetProducerSocketName(),
155 1);
156 if (argv0 == "perfetto") {
157 _exit(PerfettoCmdMain(static_cast<int>(argv.size() - 1), argv.data()));
158 } else if (argv0 == "trigger_perfetto") {
159 _exit(TriggerPerfettoMain(static_cast<int>(argv.size() - 1),
160 argv.data()));
161 } else {
162 ADD_FAILURE() << "Unknown binary: " << argv0.c_str();
163 }
164 #else
165 execv((std::string("/system/bin/") + argv0).c_str(), &argv[0]);
166 _exit(3);
167 #endif
168 }
169
170 // Parent.
171 err_pipe.wr.reset();
172 stderr_ = std::string(1024 * 1024, '\0');
173
174 // This is generally an unsafe pattern because the child process might be
175 // blocked on stdout and stall the stdin reads. It's pragmatically okay for
176 // our test cases because stdin is not expected to exceed the pipe buffer.
177 PERFETTO_CHECK(input.size() <= base::kPageSize);
178 PERFETTO_CHECK(
179 PERFETTO_EINTR(write(*in_pipe.wr, input.data(), input.size())) ==
180 static_cast<ssize_t>(input.size()));
181 in_pipe.wr.reset();
182
183 // Close the input pipe only after the write so we don't get an EPIPE signal
184 // in the cases when the child process earlies out without reading stdin.
185 in_pipe.rd.reset();
186
187 ssize_t rsize = 0;
188 size_t stderr_pos = 0;
189 while (stderr_pos < stderr_.size()) {
190 rsize = PERFETTO_EINTR(read(*err_pipe.rd, &stderr_[stderr_pos],
191 stderr_.size() - stderr_pos - 1));
192 if (rsize <= 0)
193 break;
194 stderr_pos += static_cast<size_t>(rsize);
195 }
196 stderr_.resize(stderr_pos);
197 int status = 1;
198 PERFETTO_CHECK(PERFETTO_EINTR(waitpid(pid, &status, 0)) == pid);
199 int exit_code;
200 if (WIFEXITED(status)) {
201 exit_code = WEXITSTATUS(status);
202 } else if (WIFSIGNALED(status)) {
203 exit_code = -(WTERMSIG(status));
204 PERFETTO_CHECK(exit_code < 0);
205 } else {
206 PERFETTO_FATAL("Unexpected exit status: %d", status);
207 }
208 return exit_code;
209 }
210
211 std::string stderr_;
212 base::TestTaskRunner task_runner_;
213 TestHelper test_helper_{&task_runner_};
214 };
215
216 } // namespace
217
218 // If we're building on Android and starting the daemons ourselves,
219 // create the sockets in a world-writable location.
220 #if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) && \
221 PERFETTO_BUILDFLAG(PERFETTO_START_DAEMONS)
222 #define TEST_PRODUCER_SOCK_NAME "/data/local/tmp/traced_producer"
223 #else
224 #define TEST_PRODUCER_SOCK_NAME ::perfetto::GetProducerSocket()
225 #endif
226
227 // TODO(b/73453011): reenable on more platforms (including standalone Android).
228 #if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
229 #define TreeHuggerOnly(x) x
230 #else
231 #define TreeHuggerOnly(x) DISABLED_##x
232 #endif
233
TEST_F(PerfettoTest,TreeHuggerOnly (TestFtraceProducer))234 TEST_F(PerfettoTest, TreeHuggerOnly(TestFtraceProducer)) {
235 base::TestTaskRunner task_runner;
236
237 TestHelper helper(&task_runner);
238 helper.StartServiceIfRequired();
239
240 #if PERFETTO_BUILDFLAG(PERFETTO_START_DAEMONS)
241 TaskRunnerThread producer_thread("perfetto.prd");
242 producer_thread.Start(std::unique_ptr<ProbesProducerDelegate>(
243 new ProbesProducerDelegate(TEST_PRODUCER_SOCK_NAME)));
244 #endif
245
246 helper.ConnectConsumer();
247 helper.WaitForConsumerConnect();
248
249 TraceConfig trace_config;
250 trace_config.add_buffers()->set_size_kb(1024);
251 trace_config.set_duration_ms(3000);
252
253 auto* ds_config = trace_config.add_data_sources()->mutable_config();
254 ds_config->set_name("linux.ftrace");
255 ds_config->set_target_buffer(0);
256
257 auto* ftrace_config = ds_config->mutable_ftrace_config();
258 *ftrace_config->add_ftrace_events() = "sched_switch";
259 *ftrace_config->add_ftrace_events() = "bar";
260
261 helper.StartTracing(trace_config);
262 helper.WaitForTracingDisabled();
263
264 helper.ReadData();
265 helper.WaitForReadData();
266
267 const auto& packets = helper.trace();
268 ASSERT_GT(packets.size(), 0u);
269
270 for (const auto& packet : packets) {
271 for (int ev = 0; ev < packet.ftrace_events().event_size(); ev++) {
272 ASSERT_TRUE(packet.ftrace_events().event(ev).has_sched_switch());
273 }
274 }
275 }
276
TEST_F(PerfettoTest,TreeHuggerOnly (TestFtraceFlush))277 TEST_F(PerfettoTest, TreeHuggerOnly(TestFtraceFlush)) {
278 base::TestTaskRunner task_runner;
279
280 TestHelper helper(&task_runner);
281 helper.StartServiceIfRequired();
282
283 #if PERFETTO_BUILDFLAG(PERFETTO_START_DAEMONS)
284 TaskRunnerThread producer_thread("perfetto.prd");
285 producer_thread.Start(std::unique_ptr<ProbesProducerDelegate>(
286 new ProbesProducerDelegate(TEST_PRODUCER_SOCK_NAME)));
287 #endif
288
289 helper.ConnectConsumer();
290 helper.WaitForConsumerConnect();
291
292 const uint32_t kTestTimeoutMs = 30000;
293 TraceConfig trace_config;
294 trace_config.add_buffers()->set_size_kb(16);
295 trace_config.set_duration_ms(kTestTimeoutMs);
296
297 auto* ds_config = trace_config.add_data_sources()->mutable_config();
298 ds_config->set_name("linux.ftrace");
299
300 auto* ftrace_config = ds_config->mutable_ftrace_config();
301 *ftrace_config->add_ftrace_events() = "print";
302
303 helper.StartTracing(trace_config);
304
305 // Do a first flush just to synchronize with the producer. The problem here
306 // is that, on a Linux workstation, the producer can take several seconds just
307 // to get to the point where ftrace is ready. We use the flush ack as a
308 // synchronization point.
309 helper.FlushAndWait(kTestTimeoutMs);
310
311 EXPECT_TRUE(ftrace_procfs_->IsTracingEnabled());
312 const char kMarker[] = "just_one_event";
313 EXPECT_TRUE(ftrace_procfs_->WriteTraceMarker(kMarker));
314
315 // This is the real flush we are testing.
316 helper.FlushAndWait(kTestTimeoutMs);
317
318 helper.DisableTracing();
319 helper.WaitForTracingDisabled(kTestTimeoutMs);
320
321 helper.ReadData();
322 helper.WaitForReadData();
323
324 int marker_found = 0;
325 for (const auto& packet : helper.trace()) {
326 for (int i = 0; i < packet.ftrace_events().event_size(); i++) {
327 const auto& ev = packet.ftrace_events().event(i);
328 if (ev.has_print() && ev.print().buf().find(kMarker) != std::string::npos)
329 marker_found++;
330 }
331 }
332 ASSERT_EQ(marker_found, 1);
333 }
334
TEST_F(PerfettoTest,TreeHuggerOnly (TestBatteryTracing))335 TEST_F(PerfettoTest, TreeHuggerOnly(TestBatteryTracing)) {
336 base::TestTaskRunner task_runner;
337
338 TestHelper helper(&task_runner);
339 helper.StartServiceIfRequired();
340
341 #if PERFETTO_BUILDFLAG(PERFETTO_START_DAEMONS)
342 TaskRunnerThread producer_thread("perfetto.prd");
343 producer_thread.Start(std::unique_ptr<ProbesProducerDelegate>(
344 new ProbesProducerDelegate(TEST_PRODUCER_SOCK_NAME)));
345 #else
346 base::ignore_result(TEST_PRODUCER_SOCK_NAME);
347 #endif
348
349 helper.ConnectConsumer();
350 helper.WaitForConsumerConnect();
351
352 TraceConfig trace_config;
353 trace_config.add_buffers()->set_size_kb(128);
354 trace_config.set_duration_ms(3000);
355
356 auto* ds_config = trace_config.add_data_sources()->mutable_config();
357 ds_config->set_name("android.power");
358 ds_config->set_target_buffer(0);
359 auto* power_config = ds_config->mutable_android_power_config();
360 power_config->set_battery_poll_ms(250);
361 *power_config->add_battery_counters() =
362 AndroidPowerConfig::BATTERY_COUNTER_CHARGE;
363 *power_config->add_battery_counters() =
364 AndroidPowerConfig::BATTERY_COUNTER_CAPACITY_PERCENT;
365
366 helper.StartTracing(trace_config);
367 helper.WaitForTracingDisabled();
368
369 helper.ReadData();
370 helper.WaitForReadData();
371
372 const auto& packets = helper.trace();
373 ASSERT_GT(packets.size(), 0u);
374
375 bool has_battery_packet = false;
376 for (const auto& packet : packets) {
377 if (!packet.has_battery())
378 continue;
379 has_battery_packet = true;
380 // Unfortunately we cannot make any assertions on the charge counter.
381 // On some devices it can reach negative values (b/64685329).
382 EXPECT_GE(packet.battery().capacity_percent(), 0);
383 EXPECT_LE(packet.battery().capacity_percent(), 100);
384 }
385
386 ASSERT_TRUE(has_battery_packet);
387 }
388
TEST_F(PerfettoTest,TestFakeProducer)389 TEST_F(PerfettoTest, TestFakeProducer) {
390 base::TestTaskRunner task_runner;
391
392 TestHelper helper(&task_runner);
393 helper.StartServiceIfRequired();
394 helper.ConnectFakeProducer();
395 helper.ConnectConsumer();
396 helper.WaitForConsumerConnect();
397
398 TraceConfig trace_config;
399 trace_config.add_buffers()->set_size_kb(1024);
400 trace_config.set_duration_ms(200);
401
402 auto* ds_config = trace_config.add_data_sources()->mutable_config();
403 ds_config->set_name("android.perfetto.FakeProducer");
404 ds_config->set_target_buffer(0);
405
406 static constexpr size_t kNumPackets = 11;
407 static constexpr uint32_t kRandomSeed = 42;
408 static constexpr uint32_t kMsgSize = 1024;
409 ds_config->mutable_for_testing()->set_seed(kRandomSeed);
410 ds_config->mutable_for_testing()->set_message_count(kNumPackets);
411 ds_config->mutable_for_testing()->set_message_size(kMsgSize);
412 ds_config->mutable_for_testing()->set_send_batch_on_register(true);
413
414 helper.StartTracing(trace_config);
415 helper.WaitForTracingDisabled();
416
417 helper.ReadData();
418 helper.WaitForReadData();
419
420 const auto& packets = helper.trace();
421 ASSERT_EQ(packets.size(), kNumPackets);
422
423 std::minstd_rand0 rnd_engine(kRandomSeed);
424 for (const auto& packet : packets) {
425 ASSERT_TRUE(packet.has_for_testing());
426 ASSERT_EQ(packet.for_testing().seq_value(), rnd_engine());
427 }
428 }
429
TEST_F(PerfettoTest,VeryLargePackets)430 TEST_F(PerfettoTest, VeryLargePackets) {
431 base::TestTaskRunner task_runner;
432
433 TestHelper helper(&task_runner);
434 helper.StartServiceIfRequired();
435 helper.ConnectFakeProducer();
436 helper.ConnectConsumer();
437 helper.WaitForConsumerConnect();
438
439 TraceConfig trace_config;
440 trace_config.add_buffers()->set_size_kb(4096 * 10);
441 trace_config.set_duration_ms(500);
442
443 auto* ds_config = trace_config.add_data_sources()->mutable_config();
444 ds_config->set_name("android.perfetto.FakeProducer");
445 ds_config->set_target_buffer(0);
446
447 static constexpr size_t kNumPackets = 7;
448 static constexpr uint32_t kRandomSeed = 42;
449 static constexpr uint32_t kMsgSize = 1024 * 1024 - 42;
450 ds_config->mutable_for_testing()->set_seed(kRandomSeed);
451 ds_config->mutable_for_testing()->set_message_count(kNumPackets);
452 ds_config->mutable_for_testing()->set_message_size(kMsgSize);
453 ds_config->mutable_for_testing()->set_send_batch_on_register(true);
454
455 helper.StartTracing(trace_config);
456 helper.WaitForTracingDisabled();
457
458 helper.ReadData();
459 helper.WaitForReadData();
460
461 const auto& packets = helper.trace();
462 ASSERT_EQ(packets.size(), kNumPackets);
463
464 std::minstd_rand0 rnd_engine(kRandomSeed);
465 for (const auto& packet : packets) {
466 ASSERT_TRUE(packet.has_for_testing());
467 ASSERT_EQ(packet.for_testing().seq_value(), rnd_engine());
468 size_t msg_size = packet.for_testing().str().size();
469 ASSERT_EQ(kMsgSize, msg_size);
470 for (size_t i = 0; i < msg_size; i++)
471 ASSERT_EQ(i < msg_size - 1 ? '.' : 0, packet.for_testing().str()[i]);
472 }
473 }
474
TEST_F(PerfettoTest,DetachAndReattach)475 TEST_F(PerfettoTest, DetachAndReattach) {
476 base::TestTaskRunner task_runner;
477
478 TraceConfig trace_config;
479 trace_config.add_buffers()->set_size_kb(1024);
480 trace_config.set_duration_ms(10000); // Max timeout, session is ended before.
481 auto* ds_config = trace_config.add_data_sources()->mutable_config();
482 ds_config->set_name("android.perfetto.FakeProducer");
483 static constexpr size_t kNumPackets = 11;
484 ds_config->mutable_for_testing()->set_message_count(kNumPackets);
485 ds_config->mutable_for_testing()->set_message_size(32);
486
487 // Enable tracing and detach as soon as it gets started.
488 TestHelper helper(&task_runner);
489 helper.StartServiceIfRequired();
490 auto* fake_producer = helper.ConnectFakeProducer();
491 helper.ConnectConsumer();
492 helper.WaitForConsumerConnect();
493 helper.StartTracing(trace_config);
494
495 // Detach.
496 helper.DetachConsumer("key");
497
498 // Write data while detached.
499 helper.WaitForProducerEnabled();
500 auto on_data_written = task_runner.CreateCheckpoint("data_written");
501 fake_producer->ProduceEventBatch(helper.WrapTask(on_data_written));
502 task_runner.RunUntilCheckpoint("data_written");
503
504 // Then reattach the consumer.
505 helper.ConnectConsumer();
506 helper.WaitForConsumerConnect();
507 helper.AttachConsumer("key");
508
509 helper.DisableTracing();
510 helper.WaitForTracingDisabled();
511
512 helper.ReadData();
513 helper.WaitForReadData();
514 const auto& packets = helper.trace();
515 ASSERT_EQ(packets.size(), kNumPackets);
516 }
517
518 // Tests that a detached trace session is automatically cleaned up if the
519 // consumer doesn't re-attach before its expiration time.
TEST_F(PerfettoTest,ReattachFailsAfterTimeout)520 TEST_F(PerfettoTest, ReattachFailsAfterTimeout) {
521 base::TestTaskRunner task_runner;
522
523 TraceConfig trace_config;
524 trace_config.add_buffers()->set_size_kb(1024);
525 trace_config.set_duration_ms(250);
526 trace_config.set_write_into_file(true);
527 trace_config.set_file_write_period_ms(100000);
528 auto* ds_config = trace_config.add_data_sources()->mutable_config();
529 ds_config->set_name("android.perfetto.FakeProducer");
530 ds_config->mutable_for_testing()->set_message_count(1);
531 ds_config->mutable_for_testing()->set_message_size(32);
532 ds_config->mutable_for_testing()->set_send_batch_on_register(true);
533
534 // Enable tracing and detach as soon as it gets started.
535 TestHelper helper(&task_runner);
536 helper.StartServiceIfRequired();
537 helper.ConnectFakeProducer();
538 helper.ConnectConsumer();
539 helper.WaitForConsumerConnect();
540
541 auto pipe_pair = base::Pipe::Create();
542 helper.StartTracing(trace_config, std::move(pipe_pair.wr));
543
544 // Detach.
545 helper.DetachConsumer("key");
546
547 // Use the file EOF (write end closed) as a way to detect when the trace
548 // session is ended.
549 char buf[1024];
550 while (PERFETTO_EINTR(read(*pipe_pair.rd, buf, sizeof(buf))) > 0) {
551 }
552
553 // Give some margin for the tracing service to destroy the session.
554 usleep(250000);
555
556 // Reconnect and find out that it's too late and the session is gone.
557 helper.ConnectConsumer();
558 helper.WaitForConsumerConnect();
559 EXPECT_FALSE(helper.AttachConsumer("key"));
560 }
561
562 // Disable cmdline tests on sanitizets because they use fork() and that messes
563 // up leak / races detections, which has been fixed only recently (see
564 // https://github.com/google/sanitizers/issues/836 ).
565 #if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER) || \
566 defined(MEMORY_SANITIZER) || defined(LEAK_SANITIZER)
567 #define NoSanitizers(X) DISABLED_##X
568 #else
569 #define NoSanitizers(X) X
570 #endif
571
TEST_F(PerfettoCmdlineTest,NoSanitizers (InvalidCases))572 TEST_F(PerfettoCmdlineTest, NoSanitizers(InvalidCases)) {
573 std::string cfg("duration_ms: 100");
574
575 EXPECT_EQ(1, ExecPerfetto({"--invalid-arg"}));
576
577 EXPECT_EQ(1, ExecPerfetto({"-c", "-", "-o", "-"}, ""));
578 EXPECT_THAT(stderr_, HasSubstr("TraceConfig is empty"));
579
580 // Cannot make assertions on --dropbox because on standalone builds it fails
581 // prematurely due to lack of dropbox.
582 EXPECT_EQ(
583 1, ExecPerfetto({"-c", "-", "--txt", "-o", "-", "--dropbox=foo"}, cfg));
584
585 EXPECT_EQ(1, ExecPerfetto({"-c", "-", "--txt"}, cfg));
586 EXPECT_THAT(stderr_, HasSubstr("Either --out or --dropbox"));
587
588 // Disallow mixing simple and file config.
589 EXPECT_EQ(1, ExecPerfetto({"-o", "-", "-c", "-", "-t", "2s"}, cfg));
590 EXPECT_THAT(stderr_, HasSubstr("Cannot specify both -c"));
591
592 EXPECT_EQ(1, ExecPerfetto({"-o", "-", "-c", "-", "-b", "2m"}, cfg));
593 EXPECT_THAT(stderr_, HasSubstr("Cannot specify both -c"));
594
595 EXPECT_EQ(1, ExecPerfetto({"-o", "-", "-c", "-", "-s", "2m"}, cfg));
596 EXPECT_THAT(stderr_, HasSubstr("Cannot specify both -c"));
597
598 // Invalid --attach / --detach cases.
599 EXPECT_EQ(1, ExecPerfetto({"-c", "-", "--txt", "-o", "-", "--stop"}, cfg));
600 EXPECT_THAT(stderr_, HasSubstr("--stop is supported only in combination"));
601
602 EXPECT_EQ(1,
603 ExecPerfetto({"-c", "-", "--txt", "-o", "-", "--attach=foo"}, cfg));
604 EXPECT_THAT(stderr_, HasSubstr("trace config with --attach"));
605
606 EXPECT_EQ(1, ExecPerfetto({"-t", "2s", "-o", "-", "--attach=foo"}, cfg));
607 EXPECT_THAT(stderr_, HasSubstr("trace config with --attach"));
608
609 EXPECT_EQ(1, ExecPerfetto({"--attach"}, cfg));
610 EXPECT_THAT(stderr_, ContainsRegex("option.*--attach.*requires an argument"));
611
612 EXPECT_EQ(1, ExecPerfetto({"-t", "2s", "-o", "-", "--detach"}, cfg));
613 EXPECT_THAT(stderr_, ContainsRegex("option.*--detach.*requires an argument"));
614
615 EXPECT_EQ(1, ExecPerfetto({"-t", "2s", "--detach=foo"}, cfg));
616 EXPECT_THAT(stderr_, HasSubstr("--out or --dropbox is required"));
617 }
618
TEST_F(PerfettoCmdlineTest,NoSanitizers (TxtConfig))619 TEST_F(PerfettoCmdlineTest, NoSanitizers(TxtConfig)) {
620 std::string cfg("duration_ms: 100");
621 EXPECT_EQ(0, ExecPerfetto({"-c", "-", "--txt", "-o", "-"}, cfg)) << stderr_;
622 }
623
TEST_F(PerfettoCmdlineTest,NoSanitizers (SimpleConfig))624 TEST_F(PerfettoCmdlineTest, NoSanitizers(SimpleConfig)) {
625 EXPECT_EQ(0, ExecPerfetto({"-o", "-", "-c", "-", "-t", "100ms"}));
626 }
627
TEST_F(PerfettoCmdlineTest,NoSanitizers (DetachAndAttach))628 TEST_F(PerfettoCmdlineTest, NoSanitizers(DetachAndAttach)) {
629 EXPECT_NE(0, ExecPerfetto({"--attach=not_existent"}));
630 EXPECT_THAT(stderr_, HasSubstr("Session re-attach failed"));
631
632 std::string cfg("duration_ms: 10000; write_into_file: true");
633 EXPECT_EQ(0, ExecPerfetto(
634 {"-o", "-", "-c", "-", "--txt", "--detach=valid_stop"}, cfg))
635 << stderr_;
636 EXPECT_EQ(0, ExecPerfetto({"--attach=valid_stop", "--stop"}));
637 }
638
TEST_F(PerfettoCmdlineTest,NoSanitizers (StartTracingTrigger))639 TEST_F(PerfettoCmdlineTest, NoSanitizers(StartTracingTrigger)) {
640 // See |message_count| and |message_size| in the TraceConfig above.
641 constexpr size_t kMessageCount = 11;
642 constexpr size_t kMessageSize = 32;
643 protos::TraceConfig trace_config;
644 trace_config.add_buffers()->set_size_kb(1024);
645 auto* ds_config = trace_config.add_data_sources()->mutable_config();
646 ds_config->set_name("android.perfetto.FakeProducer");
647 ds_config->mutable_for_testing()->set_message_count(kMessageCount);
648 ds_config->mutable_for_testing()->set_message_size(kMessageSize);
649 auto* trigger_cfg = trace_config.mutable_trigger_config();
650 trigger_cfg->set_trigger_mode(
651 protos::TraceConfig::TriggerConfig::START_TRACING);
652 trigger_cfg->set_trigger_timeout_ms(15000);
653 auto* trigger = trigger_cfg->add_triggers();
654 trigger->set_name("trigger_name");
655 // |stop_delay_ms| must be long enough that we can write the packets in
656 // before the trace finishes. This has to be long enough for the slowest
657 // emulator. But as short as possible to prevent the test running a long
658 // time.
659 trigger->set_stop_delay_ms(500);
660
661 // We have 6 normal preamble packets (start clock, trace config, clock,
662 // system info, sync marker, stats) and then since this is a trace with a
663 // trigger config we have an additional ReceivedTriggers packet.
664 constexpr size_t kPreamblePackets = 7;
665
666 base::TestTaskRunner task_runner;
667
668 // Enable tracing and detach as soon as it gets started.
669 TestHelper helper(&task_runner);
670 helper.StartServiceIfRequired();
671 auto* fake_producer = helper.ConnectFakeProducer();
672 EXPECT_TRUE(fake_producer);
673 const std::string path = RandomTraceFileName();
674 std::thread background_trace([&path, &trace_config, this]() {
675 EXPECT_EQ(0, ExecPerfetto(
676 {
677 "-o", path, "-c", "-",
678 },
679 trace_config.SerializeAsString()));
680 });
681
682 helper.WaitForProducerSetup();
683 EXPECT_EQ(0, ExecTrigger({"trigger_name"})) << "stderr: " << stderr_;
684
685 // Wait for the producer to start, and then write out 11 packets.
686 helper.WaitForProducerEnabled();
687 auto on_data_written = task_runner.CreateCheckpoint("data_written");
688 fake_producer->ProduceEventBatch(helper.WrapTask(on_data_written));
689 task_runner.RunUntilCheckpoint("data_written");
690 background_trace.join();
691
692 std::string trace_str;
693 base::ReadFile(path, &trace_str);
694 protos::Trace trace;
695 ASSERT_TRUE(trace.ParseFromString(trace_str));
696 EXPECT_EQ(kPreamblePackets + kMessageCount, trace.packet_size());
697 for (const auto& packet : trace.packet()) {
698 if (packet.data_case() == protos::TracePacket::kTraceConfig) {
699 // Ensure the trace config properly includes the trigger mode we set.
700 EXPECT_EQ(protos::TraceConfig::TriggerConfig::START_TRACING,
701 packet.trace_config().trigger_config().trigger_mode());
702 } else if (packet.data_case() == protos::TracePacket::kTrigger) {
703 // validate that the triggers are properly added to the trace.
704 EXPECT_EQ("trigger_name", packet.trigger().trigger_name());
705 } else if (packet.data_case() == protos::TracePacket::kForTesting) {
706 // Make sure that the data size is correctly set based on what we
707 // requested.
708 EXPECT_EQ(kMessageSize, packet.for_testing().str().size());
709 }
710 }
711 }
712
TEST_F(PerfettoCmdlineTest,NoSanitizers (StopTracingTrigger))713 TEST_F(PerfettoCmdlineTest, NoSanitizers(StopTracingTrigger)) {
714 // See |message_count| and |message_size| in the TraceConfig above.
715 constexpr size_t kMessageCount = 11;
716 constexpr size_t kMessageSize = 32;
717 protos::TraceConfig trace_config;
718 trace_config.add_buffers()->set_size_kb(1024);
719 auto* ds_config = trace_config.add_data_sources()->mutable_config();
720 ds_config->set_name("android.perfetto.FakeProducer");
721 ds_config->mutable_for_testing()->set_message_count(kMessageCount);
722 ds_config->mutable_for_testing()->set_message_size(kMessageSize);
723 auto* trigger_cfg = trace_config.mutable_trigger_config();
724 trigger_cfg->set_trigger_mode(
725 protos::TraceConfig::TriggerConfig::STOP_TRACING);
726 trigger_cfg->set_trigger_timeout_ms(15000);
727 auto* trigger = trigger_cfg->add_triggers();
728 trigger->set_name("trigger_name");
729 // |stop_delay_ms| must be long enough that we can write the packets in
730 // before the trace finishes. This has to be long enough for the slowest
731 // emulator. But as short as possible to prevent the test running a long
732 // time.
733 trigger->set_stop_delay_ms(500);
734 trigger = trigger_cfg->add_triggers();
735 trigger->set_name("trigger_name_3");
736 trigger->set_stop_delay_ms(60000);
737
738 // We have 6 normal preamble packets (start clock, trace config, clock,
739 // system info, sync marker, stats) and then since this is a trace with a
740 // trigger config we have an additional ReceivedTriggers packet.
741 constexpr size_t kPreamblePackets = 8;
742
743 base::TestTaskRunner task_runner;
744
745 // Enable tracing and detach as soon as it gets started.
746 TestHelper helper(&task_runner);
747 helper.StartServiceIfRequired();
748 auto* fake_producer = helper.ConnectFakeProducer();
749 EXPECT_TRUE(fake_producer);
750
751 const std::string path = RandomTraceFileName();
752 std::thread background_trace([&path, &trace_config, this]() {
753 EXPECT_EQ(0, ExecPerfetto(
754 {
755 "-o", path, "-c", "-",
756 },
757 trace_config.SerializeAsString()));
758 });
759
760 helper.WaitForProducerEnabled();
761 // Wait for the producer to start, and then write out 11 packets, before the
762 // trace actually starts (the trigger is seen).
763 auto on_data_written = task_runner.CreateCheckpoint("data_written_1");
764 fake_producer->ProduceEventBatch(helper.WrapTask(on_data_written));
765 task_runner.RunUntilCheckpoint("data_written_1");
766
767 EXPECT_EQ(0,
768 ExecTrigger({"trigger_name_2", "trigger_name", "trigger_name_3"}))
769 << "stderr: " << stderr_;
770
771 background_trace.join();
772
773 std::string trace_str;
774 base::ReadFile(path, &trace_str);
775 protos::Trace trace;
776 ASSERT_TRUE(trace.ParseFromString(trace_str));
777 EXPECT_EQ(kPreamblePackets + kMessageCount, trace.packet_size());
778 bool seen_first_trigger = false;
779 for (const auto& packet : trace.packet()) {
780 if (packet.data_case() == protos::TracePacket::kTraceConfig) {
781 // Ensure the trace config properly includes the trigger mode we set.
782 EXPECT_EQ(protos::TraceConfig::TriggerConfig::STOP_TRACING,
783 packet.trace_config().trigger_config().trigger_mode());
784 } else if (packet.data_case() == protos::TracePacket::kTrigger) {
785 // validate that the triggers are properly added to the trace.
786 if (!seen_first_trigger) {
787 EXPECT_EQ("trigger_name", packet.trigger().trigger_name());
788 seen_first_trigger = true;
789 } else {
790 EXPECT_EQ("trigger_name_3", packet.trigger().trigger_name());
791 }
792 } else if (packet.data_case() == protos::TracePacket::kForTesting) {
793 // Make sure that the data size is correctly set based on what we
794 // requested.
795 EXPECT_EQ(kMessageSize, packet.for_testing().str().size());
796 }
797 }
798 }
799
800 // Dropbox on the commandline client only works on android builds. So disable
801 // this test on all other builds.
802 #if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
TEST_F(PerfettoCmdlineTest,NoSanitizers (NoDataNoFileWithoutTrigger))803 TEST_F(PerfettoCmdlineTest, NoSanitizers(NoDataNoFileWithoutTrigger)) {
804 #else
805 TEST_F(PerfettoCmdlineTest, DISABLED_NoDataNoFileWithoutTrigger) {
806 #endif
807 // See |message_count| and |message_size| in the TraceConfig above.
808 constexpr size_t kMessageCount = 11;
809 constexpr size_t kMessageSize = 32;
810 protos::TraceConfig trace_config;
811 trace_config.add_buffers()->set_size_kb(1024);
812 trace_config.set_allow_user_build_tracing(true);
813 auto* ds_config = trace_config.add_data_sources()->mutable_config();
814 ds_config->set_name("android.perfetto.FakeProducer");
815 ds_config->mutable_for_testing()->set_message_count(kMessageCount);
816 ds_config->mutable_for_testing()->set_message_size(kMessageSize);
817 auto* trigger_cfg = trace_config.mutable_trigger_config();
818 trigger_cfg->set_trigger_mode(
819 protos::TraceConfig::TriggerConfig::STOP_TRACING);
820 trigger_cfg->set_trigger_timeout_ms(1000);
821 auto* trigger = trigger_cfg->add_triggers();
822 trigger->set_name("trigger_name");
823 // |stop_delay_ms| must be long enough that we can write the packets in
824 // before the trace finishes. This has to be long enough for the slowest
825 // emulator. But as short as possible to prevent the test running a long
826 // time.
827 trigger->set_stop_delay_ms(500);
828 trigger = trigger_cfg->add_triggers();
829
830 // Enable tracing and detach as soon as it gets started.
831 base::TestTaskRunner task_runner;
832 TestHelper helper(&task_runner);
833 helper.StartServiceIfRequired();
834 auto* fake_producer = helper.ConnectFakeProducer();
835 EXPECT_TRUE(fake_producer);
836
837 std::thread background_trace([&trace_config, this]() {
838 EXPECT_EQ(0, ExecPerfetto(
839 {
840 "--dropbox", "TAG", "--no-guardrails", "-c", "-",
841 },
842 trace_config.SerializeAsString()));
843 });
844 background_trace.join();
845
846 EXPECT_THAT(stderr_,
847 ::testing::HasSubstr("Skipping write to dropbox. Empty trace."));
848 }
849
850 TEST_F(PerfettoCmdlineTest, NoSanitizers(StopTracingTriggerFromConfig)) {
851 // See |message_count| and |message_size| in the TraceConfig above.
852 constexpr size_t kMessageCount = 11;
853 constexpr size_t kMessageSize = 32;
854 protos::TraceConfig trace_config;
855 trace_config.add_buffers()->set_size_kb(1024);
856 auto* ds_config = trace_config.add_data_sources()->mutable_config();
857 ds_config->set_name("android.perfetto.FakeProducer");
858 ds_config->mutable_for_testing()->set_message_count(kMessageCount);
859 ds_config->mutable_for_testing()->set_message_size(kMessageSize);
860 auto* trigger_cfg = trace_config.mutable_trigger_config();
861 trigger_cfg->set_trigger_mode(
862 protos::TraceConfig::TriggerConfig::STOP_TRACING);
863 trigger_cfg->set_trigger_timeout_ms(15000);
864 auto* trigger = trigger_cfg->add_triggers();
865 trigger->set_name("trigger_name");
866 // |stop_delay_ms| must be long enough that we can write the packets in
867 // before the trace finishes. This has to be long enough for the slowest
868 // emulator. But as short as possible to prevent the test running a long
869 // time.
870 trigger->set_stop_delay_ms(500);
871 trigger = trigger_cfg->add_triggers();
872 trigger->set_name("trigger_name_3");
873 trigger->set_stop_delay_ms(60000);
874
875 // We have 5 normal preample packets (trace config, clock, system info, sync
876 // marker, stats) and then since this is a trace with a trigger config we have
877 // an additional ReceivedTriggers packet.
878 base::TestTaskRunner task_runner;
879
880 // Enable tracing and detach as soon as it gets started.
881 TestHelper helper(&task_runner);
882 helper.StartServiceIfRequired();
883 auto* fake_producer = helper.ConnectFakeProducer();
884 EXPECT_TRUE(fake_producer);
885
886 const std::string path = RandomTraceFileName();
887 std::thread background_trace([&path, &trace_config, this]() {
888 EXPECT_EQ(0, ExecPerfetto(
889 {
890 "-o", path, "-c", "-",
891 },
892 trace_config.SerializeAsString()));
893 });
894
895 helper.WaitForProducerEnabled();
896 // Wait for the producer to start, and then write out 11 packets, before the
897 // trace actually starts (the trigger is seen).
898 auto on_data_written = task_runner.CreateCheckpoint("data_written_1");
899 fake_producer->ProduceEventBatch(helper.WrapTask(on_data_written));
900 task_runner.RunUntilCheckpoint("data_written_1");
901
902 std::string triggers = R"(
903 activate_triggers: "trigger_name_2"
904 activate_triggers: "trigger_name"
905 activate_triggers: "trigger_name_3"
906 )";
907
908 EXPECT_EQ(0, ExecPerfetto(
909 {
910 "-o", path, "-c", "-", "--txt",
911 },
912 triggers))
913 << "stderr: " << stderr_;
914
915 background_trace.join();
916
917 std::string trace_str;
918 base::ReadFile(path, &trace_str);
919 protos::Trace trace;
920 ASSERT_TRUE(trace.ParseFromString(trace_str));
921 EXPECT_LT(kMessageCount, trace.packet_size());
922 bool seen_first_trigger = false;
923 for (const auto& packet : trace.packet()) {
924 if (packet.data_case() == protos::TracePacket::kTraceConfig) {
925 // Ensure the trace config properly includes the trigger mode we set.
926 EXPECT_EQ(protos::TraceConfig::TriggerConfig::STOP_TRACING,
927 packet.trace_config().trigger_config().trigger_mode());
928 } else if (packet.data_case() == protos::TracePacket::kTrigger) {
929 // validate that the triggers are properly added to the trace.
930 if (!seen_first_trigger) {
931 EXPECT_EQ("trigger_name", packet.trigger().trigger_name());
932 seen_first_trigger = true;
933 } else {
934 EXPECT_EQ("trigger_name_3", packet.trigger().trigger_name());
935 }
936 } else if (packet.data_case() == protos::TracePacket::kForTesting) {
937 // Make sure that the data size is correctly set based on what we
938 // requested.
939 EXPECT_EQ(kMessageSize, packet.for_testing().str().size());
940 }
941 }
942 }
943
944 TEST_F(PerfettoCmdlineTest, NoSanitizers(TriggerFromConfigStopsFileOpening)) {
945 // See |message_count| and |message_size| in the TraceConfig above.
946 constexpr size_t kMessageCount = 11;
947 constexpr size_t kMessageSize = 32;
948 protos::TraceConfig trace_config;
949 trace_config.add_buffers()->set_size_kb(1024);
950 auto* ds_config = trace_config.add_data_sources()->mutable_config();
951 ds_config->set_name("android.perfetto.FakeProducer");
952 ds_config->mutable_for_testing()->set_message_count(kMessageCount);
953 ds_config->mutable_for_testing()->set_message_size(kMessageSize);
954 auto* trigger_cfg = trace_config.mutable_trigger_config();
955 trigger_cfg->set_trigger_mode(
956 protos::TraceConfig::TriggerConfig::STOP_TRACING);
957 trigger_cfg->set_trigger_timeout_ms(15000);
958 auto* trigger = trigger_cfg->add_triggers();
959 trigger->set_name("trigger_name");
960 // |stop_delay_ms| must be long enough that we can write the packets in
961 // before the trace finishes. This has to be long enough for the slowest
962 // emulator. But as short as possible to prevent the test running a long
963 // time.
964 trigger->set_stop_delay_ms(500);
965 trigger = trigger_cfg->add_triggers();
966 trigger->set_name("trigger_name_3");
967 trigger->set_stop_delay_ms(60000);
968
969 // We have 5 normal preample packets (trace config, clock, system info, sync
970 // marker, stats) and then since this is a trace with a trigger config we have
971 // an additional ReceivedTriggers packet.
972 base::TestTaskRunner task_runner;
973
974 // Enable tracing and detach as soon as it gets started.
975 TestHelper helper(&task_runner);
976 helper.StartServiceIfRequired();
977 auto* fake_producer = helper.ConnectFakeProducer();
978 EXPECT_TRUE(fake_producer);
979
980 const std::string path = RandomTraceFileName();
981
982 std::string trace_str;
983 EXPECT_FALSE(base::ReadFile(path, &trace_str));
984
985 std::string triggers = R"(
986 activate_triggers: "trigger_name_2"
987 activate_triggers: "trigger_name"
988 activate_triggers: "trigger_name_3"
989 )";
990
991 EXPECT_EQ(0, ExecPerfetto(
992 {
993 "-o", path, "-c", "-", "--txt",
994 },
995 triggers))
996 << "stderr: " << stderr_;
997
998 EXPECT_FALSE(base::ReadFile(path, &trace_str));
999 }
1000
1001 } // namespace perfetto
1002