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 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: 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 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: 96 void SetUp() override { 97 test_helper_.StartServiceIfRequired(); 98 } 99 100 void TearDown() override {} 101 102 int ExecPerfetto(std::initializer_list<std::string> args, 103 std::string input = "") { 104 return Exec("perfetto", args, input); 105 } 106 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. 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 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 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 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 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 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 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. 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 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 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 624 TEST_F(PerfettoCmdlineTest, NoSanitizers(SimpleConfig)) { 625 EXPECT_EQ(0, ExecPerfetto({"-o", "-", "-c", "-", "-t", "100ms"})); 626 } 627 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 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 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) 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