• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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