• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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 <fcntl.h>
18 
19 #include <chrono>
20 #include <condition_variable>
21 #include <functional>
22 #include <list>
23 #include <mutex>
24 #include <regex>
25 #include <thread>
26 #include <vector>
27 
28 // We also want to test legacy trace events.
29 #define PERFETTO_ENABLE_LEGACY_TRACE_EVENTS 1
30 
31 #include "perfetto/tracing.h"
32 #include "test/gtest_and_gmock.h"
33 
34 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
35 #include <Windows.h>  // For CreateFile().
36 #endif
37 
38 // Deliberately not pulling any non-public perfetto header to spot accidental
39 // header public -> non-public dependency while building this file.
40 
41 // These two are the only headers allowed here, see comments in
42 // api_test_support.h.
43 #include "src/tracing/test/api_test_support.h"
44 #include "src/tracing/test/tracing_module.h"
45 
46 #include "perfetto/tracing/core/data_source_descriptor.h"
47 #include "perfetto/tracing/core/trace_config.h"
48 
49 // xxx.pbzero.h includes are for the writing path (the code that pretends to be
50 // production code).
51 // yyy.gen.h includes are for the test readback path (the code in the test that
52 // checks that the results are valid).
53 #include "protos/perfetto/common/builtin_clock.pbzero.h"
54 #include "protos/perfetto/common/interceptor_descriptor.gen.h"
55 #include "protos/perfetto/common/trace_stats.gen.h"
56 #include "protos/perfetto/common/tracing_service_state.gen.h"
57 #include "protos/perfetto/common/track_event_descriptor.gen.h"
58 #include "protos/perfetto/config/interceptor_config.gen.h"
59 #include "protos/perfetto/config/track_event/track_event_config.gen.h"
60 #include "protos/perfetto/trace/clock_snapshot.pbzero.h"
61 #include "protos/perfetto/trace/gpu/gpu_render_stage_event.gen.h"
62 #include "protos/perfetto/trace/gpu/gpu_render_stage_event.pbzero.h"
63 #include "protos/perfetto/trace/interned_data/interned_data.gen.h"
64 #include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
65 #include "protos/perfetto/trace/profiling/profile_common.gen.h"
66 #include "protos/perfetto/trace/test_event.gen.h"
67 #include "protos/perfetto/trace/test_event.pbzero.h"
68 #include "protos/perfetto/trace/test_extensions.pbzero.h"
69 #include "protos/perfetto/trace/trace.gen.h"
70 #include "protos/perfetto/trace/trace.pbzero.h"
71 #include "protos/perfetto/trace/trace_packet.gen.h"
72 #include "protos/perfetto/trace/trace_packet.pbzero.h"
73 #include "protos/perfetto/trace/track_event/chrome_process_descriptor.gen.h"
74 #include "protos/perfetto/trace/track_event/chrome_process_descriptor.pbzero.h"
75 #include "protos/perfetto/trace/track_event/counter_descriptor.gen.h"
76 #include "protos/perfetto/trace/track_event/debug_annotation.gen.h"
77 #include "protos/perfetto/trace/track_event/debug_annotation.pbzero.h"
78 #include "protos/perfetto/trace/track_event/log_message.gen.h"
79 #include "protos/perfetto/trace/track_event/log_message.pbzero.h"
80 #include "protos/perfetto/trace/track_event/process_descriptor.gen.h"
81 #include "protos/perfetto/trace/track_event/process_descriptor.pbzero.h"
82 #include "protos/perfetto/trace/track_event/source_location.gen.h"
83 #include "protos/perfetto/trace/track_event/source_location.pbzero.h"
84 #include "protos/perfetto/trace/track_event/thread_descriptor.gen.h"
85 #include "protos/perfetto/trace/track_event/thread_descriptor.pbzero.h"
86 #include "protos/perfetto/trace/track_event/track_descriptor.gen.h"
87 #include "protos/perfetto/trace/track_event/track_event.gen.h"
88 
89 // Events in categories starting with "dynamic" will use dynamic category
90 // lookup.
91 PERFETTO_DEFINE_TEST_CATEGORY_PREFIXES("dynamic");
92 
93 // Trace categories used in the tests.
94 PERFETTO_DEFINE_CATEGORIES(
95     perfetto::Category("test")
96         .SetDescription("This is a test category")
97         .SetTags("tag"),
98     perfetto::Category("foo"),
99     perfetto::Category("bar"),
100     perfetto::Category("cat").SetTags("slow"),
101     perfetto::Category("cat.verbose").SetTags("debug"),
102     perfetto::Category("cat-with-dashes"),
103     perfetto::Category::Group("foo,bar"),
104     perfetto::Category::Group("baz,bar,quux"),
105     perfetto::Category::Group("red,green,blue,foo"),
106     perfetto::Category::Group("red,green,blue,yellow"),
107     perfetto::Category(TRACE_DISABLED_BY_DEFAULT("cat")));
108 PERFETTO_TRACK_EVENT_STATIC_STORAGE();
109 
110 // For testing interning of complex objects.
111 using SourceLocation = std::tuple<const char* /* file_name */,
112                                   const char* /* function_name */,
113                                   uint32_t /* line_number */>;
114 
115 template <>
116 struct std::hash<SourceLocation> {
operator ()std::hash117   size_t operator()(const SourceLocation& value) const {
118     auto hasher = hash<size_t>();
119     return hasher(reinterpret_cast<size_t>(get<0>(value))) ^
120            hasher(reinterpret_cast<size_t>(get<1>(value))) ^
121            hasher(get<2>(value));
122   }
123 };
124 
125 // Represents an opaque (from Perfetto's point of view) thread identifier (e.g.,
126 // base::PlatformThreadId in Chromium).
127 struct MyThreadId {
MyThreadIdMyThreadId128   explicit MyThreadId(int tid_) : tid(tid_) {}
129 
130   const int tid = 0;
131 };
132 
133 // Represents an opaque timestamp (e.g., base::TimeTicks in Chromium).
134 class MyTimestamp {
135  public:
MyTimestamp(uint64_t ts_)136   explicit MyTimestamp(uint64_t ts_) : ts(ts_) {}
137 
138   const uint64_t ts;
139 };
140 
141 namespace perfetto {
142 namespace legacy {
143 
144 template <>
ConvertThreadId(const MyThreadId & thread)145 ThreadTrack ConvertThreadId(const MyThreadId& thread) {
146   return perfetto::ThreadTrack::ForThread(
147       static_cast<base::PlatformThreadId>(thread.tid));
148 }
149 
150 }  // namespace legacy
151 
152 template <>
153 struct TraceTimestampTraits<MyTimestamp> {
ConvertTimestampToTraceTimeNsperfetto::TraceTimestampTraits154   static TraceTimestamp ConvertTimestampToTraceTimeNs(
155       const MyTimestamp& timestamp) {
156     return {TrackEvent::GetTraceClockId(), timestamp.ts};
157   }
158 };
159 
160 }  // namespace perfetto
161 
162 namespace {
163 
164 using perfetto::TracingInitArgs;
165 using ::testing::_;
166 using ::testing::ContainerEq;
167 using ::testing::ElementsAre;
168 using ::testing::HasSubstr;
169 using ::testing::Invoke;
170 using ::testing::InvokeWithoutArgs;
171 using ::testing::NiceMock;
172 using ::testing::Not;
173 using ::testing::Property;
174 using ::testing::StrEq;
175 
176 // ------------------------------
177 // Declarations of helper classes
178 // ------------------------------
179 
180 class WaitableTestEvent {
181  public:
notified()182   bool notified() {
183     std::unique_lock<std::mutex> lock(mutex_);
184     return notified_;
185   }
186 
Wait()187   void Wait() {
188     std::unique_lock<std::mutex> lock(mutex_);
189     // TSAN gets confused by wait_for, which we would use here in a perfect
190     // world.
191     cv_.wait(lock, [this] { return notified_; });
192   }
193 
Notify()194   void Notify() {
195     {
196       std::lock_guard<std::mutex> lock(mutex_);
197       notified_ = true;
198     }
199     // Do not notify while holding the lock, because then we wake up the other
200     // end, only for it to fail to acquire the lock.
201     cv_.notify_one();
202   }
203 
204  private:
205   std::mutex mutex_;
206   std::condition_variable cv_;
207   bool notified_ = false;
208 };
209 
210 class MockDataSource;
211 
212 // We can't easily use gmock here because instances of data sources are lazily
213 // created by the service and are not owned by the test fixture.
214 struct TestDataSourceHandle {
215   WaitableTestEvent on_create;
216   WaitableTestEvent on_setup;
217   WaitableTestEvent on_start;
218   WaitableTestEvent on_stop;
219   MockDataSource* instance;
220   perfetto::DataSourceConfig config;
221   bool handle_stop_asynchronously = false;
222   std::function<void()> on_start_callback;
223   std::function<void()> on_stop_callback;
224   std::function<void()> async_stop_closure;
225 };
226 
227 class MockDataSource : public perfetto::DataSource<MockDataSource> {
228  public:
229   void OnSetup(const SetupArgs&) override;
230   void OnStart(const StartArgs&) override;
231   void OnStop(const StopArgs&) override;
232   TestDataSourceHandle* handle_ = nullptr;
233 };
234 
235 constexpr int kTestDataSourceArg = 123;
236 
237 class MockDataSource2 : public perfetto::DataSource<MockDataSource2> {
238  public:
MockDataSource2(int arg)239   MockDataSource2(int arg) { EXPECT_EQ(arg, kTestDataSourceArg); }
OnSetup(const SetupArgs &)240   void OnSetup(const SetupArgs&) override {}
OnStart(const StartArgs &)241   void OnStart(const StartArgs&) override {}
OnStop(const StopArgs &)242   void OnStop(const StopArgs&) override {}
243 };
244 
245 // Used to verify that track event data sources in different namespaces register
246 // themselves correctly in the muxer.
247 class MockTracingMuxer : public perfetto::internal::TracingMuxer {
248  public:
249   struct DataSource {
250     const perfetto::DataSourceDescriptor dsd;
251     perfetto::internal::DataSourceStaticState* static_state;
252   };
253 
MockTracingMuxer()254   MockTracingMuxer() : TracingMuxer(nullptr), prev_instance_(instance_) {
255     instance_ = this;
256   }
~MockTracingMuxer()257   ~MockTracingMuxer() override { instance_ = prev_instance_; }
258 
RegisterDataSource(const perfetto::DataSourceDescriptor & dsd,DataSourceFactory,perfetto::internal::DataSourceStaticState * static_state)259   bool RegisterDataSource(
260       const perfetto::DataSourceDescriptor& dsd,
261       DataSourceFactory,
262       perfetto::internal::DataSourceStaticState* static_state) override {
263     data_sources.emplace_back(DataSource{dsd, static_state});
264     return true;
265   }
266 
CreateTraceWriter(perfetto::internal::DataSourceStaticState *,uint32_t,perfetto::internal::DataSourceState *,perfetto::BufferExhaustedPolicy)267   std::unique_ptr<perfetto::TraceWriterBase> CreateTraceWriter(
268       perfetto::internal::DataSourceStaticState*,
269       uint32_t,
270       perfetto::internal::DataSourceState*,
271       perfetto::BufferExhaustedPolicy) override {
272     return nullptr;
273   }
274 
DestroyStoppedTraceWritersForCurrentThread()275   void DestroyStoppedTraceWritersForCurrentThread() override {}
RegisterInterceptor(const perfetto::InterceptorDescriptor &,InterceptorFactory,perfetto::InterceptorBase::TLSFactory,perfetto::InterceptorBase::TracePacketCallback)276   void RegisterInterceptor(
277       const perfetto::InterceptorDescriptor&,
278       InterceptorFactory,
279       perfetto::InterceptorBase::TLSFactory,
280       perfetto::InterceptorBase::TracePacketCallback) override {}
281 
282   std::vector<DataSource> data_sources;
283 
284  private:
285   TracingMuxer* prev_instance_;
286 };
287 
288 struct TestIncrementalState {
TestIncrementalState__anone89577de0111::TestIncrementalState289   TestIncrementalState() { constructed = true; }
290   // Note: a virtual destructor is not required for incremental state.
~TestIncrementalState__anone89577de0111::TestIncrementalState291   ~TestIncrementalState() { destroyed = true; }
292 
293   int count = 100;
294   bool flag = false;
295   static bool constructed;
296   static bool destroyed;
297 };
298 
299 bool TestIncrementalState::constructed;
300 bool TestIncrementalState::destroyed;
301 
302 struct TestIncrementalDataSourceTraits
303     : public perfetto::DefaultDataSourceTraits {
304   using IncrementalStateType = TestIncrementalState;
305 };
306 
307 class TestIncrementalDataSource
308     : public perfetto::DataSource<TestIncrementalDataSource,
309                                   TestIncrementalDataSourceTraits> {
310  public:
OnSetup(const SetupArgs &)311   void OnSetup(const SetupArgs&) override {}
OnStart(const StartArgs &)312   void OnStart(const StartArgs&) override {}
OnStop(const StopArgs &)313   void OnStop(const StopArgs&) override {}
314 };
315 
316 // A convenience wrapper around TracingSession that allows to do block on
317 //
318 struct TestTracingSessionHandle {
get__anone89577de0111::TestTracingSessionHandle319   perfetto::TracingSession* get() { return session.get(); }
320   std::unique_ptr<perfetto::TracingSession> session;
321   WaitableTestEvent on_stop;
322 };
323 
324 class MyDebugAnnotation : public perfetto::DebugAnnotation {
325  public:
326   ~MyDebugAnnotation() override = default;
327 
Add(perfetto::protos::pbzero::DebugAnnotation * annotation) const328   void Add(
329       perfetto::protos::pbzero::DebugAnnotation* annotation) const override {
330     annotation->set_legacy_json_value(R"({"key": 123})");
331   }
332 };
333 
334 class TestTracingPolicy : public perfetto::TracingPolicy {
335  public:
ShouldAllowConsumerSession(const ShouldAllowConsumerSessionArgs & args)336   void ShouldAllowConsumerSession(
337       const ShouldAllowConsumerSessionArgs& args) override {
338     EXPECT_NE(args.backend_type, perfetto::BackendType::kUnspecifiedBackend);
339     args.result_callback(should_allow_consumer_connection);
340   }
341 
342   bool should_allow_consumer_connection = true;
343 };
344 
345 TestTracingPolicy* g_test_tracing_policy = new TestTracingPolicy();  // Leaked.
346 
347 // -------------------------
348 // Declaration of test class
349 // -------------------------
350 class PerfettoApiTest : public ::testing::TestWithParam<perfetto::BackendType> {
351  public:
352   static PerfettoApiTest* instance;
353 
SetUp()354   void SetUp() override {
355     instance = this;
356     g_test_tracing_policy->should_allow_consumer_connection = true;
357 
358     // Start a fresh system service for this test, tearing down any previous
359     // service that was running.
360     uint32_t supported_backends =
361         perfetto::kInProcessBackend | perfetto::kSystemBackend;
362     if (!perfetto::test::StartSystemService())
363       supported_backends &= ~perfetto::kSystemBackend;
364 
365     // If the system backend wasn't supported, skip all system backend tests.
366     auto backend = GetParam();
367     if (!(supported_backends & backend))
368       GTEST_SKIP();
369 
370     static bool was_initialized;
371     if (!was_initialized) {
372       EXPECT_FALSE(perfetto::Tracing::IsInitialized());
373       was_initialized = true;
374     } else {
375       EXPECT_TRUE(perfetto::Tracing::IsInitialized());
376     }
377 
378     // Since the client API can only be initialized once per process, initialize
379     // both the in-process and system backends for every test here. The actual
380     // service to be used is chosen by the test parameter.
381     TracingInitArgs args;
382     args.backends = supported_backends;
383     args.tracing_policy = g_test_tracing_policy;
384     perfetto::Tracing::Initialize(args);
385     RegisterDataSource<MockDataSource>("my_data_source");
386     perfetto::TrackEvent::Register();
387 
388     // Make sure our data source always has a valid handle.
389     data_sources_["my_data_source"];
390 
391     // If this wasn't the first test to run in this process, any producers
392     // connected to the old system service will have been disconnected by the
393     // service restarting above. Wait for all producers to connect again before
394     // proceeding with the test.
395     perfetto::test::SyncProducers();
396 
397     perfetto::test::DisableReconnectLimit();
398   }
399 
TearDown()400   void TearDown() override { instance = nullptr; }
401 
402   template <typename DataSourceType>
RegisterDataSource(std::string name)403   TestDataSourceHandle* RegisterDataSource(std::string name) {
404     EXPECT_EQ(data_sources_.count(name), 0u);
405     TestDataSourceHandle* handle = &data_sources_[name];
406     perfetto::DataSourceDescriptor dsd;
407     dsd.set_name(name);
408     DataSourceType::Register(dsd);
409     return handle;
410   }
411 
NewTrace(const perfetto::TraceConfig & cfg,int fd=-1)412   TestTracingSessionHandle* NewTrace(const perfetto::TraceConfig& cfg,
413                                      int fd = -1) {
414     return NewTrace(cfg, /*backend_type=*/GetParam(), fd);
415   }
416 
NewTrace(const perfetto::TraceConfig & cfg,perfetto::BackendType backend_type,int fd=-1)417   TestTracingSessionHandle* NewTrace(const perfetto::TraceConfig& cfg,
418                                      perfetto::BackendType backend_type,
419                                      int fd = -1) {
420     sessions_.emplace_back();
421     TestTracingSessionHandle* handle = &sessions_.back();
422     handle->session = perfetto::Tracing::NewTrace(backend_type);
423     handle->session->SetOnStopCallback([handle] { handle->on_stop.Notify(); });
424     handle->session->Setup(cfg, fd);
425     return handle;
426   }
427 
NewTraceWithCategories(std::vector<std::string> categories)428   TestTracingSessionHandle* NewTraceWithCategories(
429       std::vector<std::string> categories) {
430     perfetto::TraceConfig cfg;
431     cfg.set_duration_ms(500);
432     cfg.add_buffers()->set_size_kb(1024);
433     auto* ds_cfg = cfg.add_data_sources()->mutable_config();
434     ds_cfg->set_name("track_event");
435 
436     perfetto::protos::gen::TrackEventConfig te_cfg;
437     te_cfg.add_disabled_categories("*");
438     for (const auto& category : categories)
439       te_cfg.add_enabled_categories(category);
440     ds_cfg->set_track_event_config_raw(te_cfg.SerializeAsString());
441 
442     return NewTrace(cfg);
443   }
444 
ReadLogMessagesFromTrace(perfetto::TracingSession * tracing_session)445   std::vector<std::string> ReadLogMessagesFromTrace(
446       perfetto::TracingSession* tracing_session) {
447     std::vector<char> raw_trace = tracing_session->ReadTraceBlocking();
448     EXPECT_GE(raw_trace.size(), 0u);
449 
450     // Read back the trace, maintaining interning tables as we go.
451     std::vector<std::string> log_messages;
452     std::map<uint64_t, std::string> log_message_bodies;
453     std::map<uint64_t, perfetto::protos::gen::SourceLocation> source_locations;
454     perfetto::protos::gen::Trace parsed_trace;
455     EXPECT_TRUE(
456         parsed_trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
457 
458     for (const auto& packet : parsed_trace.packet()) {
459       if (!packet.has_track_event())
460         continue;
461 
462       if (packet.has_interned_data()) {
463         const auto& interned_data = packet.interned_data();
464         for (const auto& it : interned_data.log_message_body()) {
465           EXPECT_GE(it.iid(), 1u);
466           EXPECT_EQ(log_message_bodies.find(it.iid()),
467                     log_message_bodies.end());
468           log_message_bodies[it.iid()] = it.body();
469         }
470         for (const auto& it : interned_data.source_locations()) {
471           EXPECT_GE(it.iid(), 1u);
472           EXPECT_EQ(source_locations.find(it.iid()), source_locations.end());
473           source_locations[it.iid()] = it;
474         }
475       }
476       const auto& track_event = packet.track_event();
477       if (track_event.type() !=
478           perfetto::protos::gen::TrackEvent::TYPE_SLICE_BEGIN)
479         continue;
480 
481       EXPECT_TRUE(track_event.has_log_message());
482       const auto& log = track_event.log_message();
483       if (log.source_location_iid()) {
484         std::stringstream msg;
485         const auto& source_location =
486             source_locations[log.source_location_iid()];
487         msg << source_location.function_name() << "("
488             << source_location.file_name() << ":"
489             << source_location.line_number()
490             << "): " << log_message_bodies[log.body_iid()];
491         log_messages.emplace_back(msg.str());
492       } else {
493         log_messages.emplace_back(log_message_bodies[log.body_iid()]);
494       }
495     }
496     return log_messages;
497   }
498 
ReadSlicesFromTrace(perfetto::TracingSession * tracing_session)499   std::vector<std::string> ReadSlicesFromTrace(
500       perfetto::TracingSession* tracing_session) {
501     std::vector<char> raw_trace = tracing_session->ReadTraceBlocking();
502     EXPECT_GE(raw_trace.size(), 0u);
503 
504     // Read back the trace, maintaining interning tables as we go.
505     std::vector<std::string> slices;
506     std::map<uint64_t, std::string> categories;
507     std::map<uint64_t, std::string> event_names;
508     std::map<uint64_t, std::string> debug_annotation_names;
509     std::set<uint64_t> seen_tracks;
510     perfetto::protos::gen::Trace parsed_trace;
511     EXPECT_TRUE(
512         parsed_trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
513 
514     bool incremental_state_was_cleared = false;
515     uint32_t sequence_id = 0;
516     for (const auto& packet : parsed_trace.packet()) {
517       if (packet.sequence_flags() & perfetto::protos::pbzero::TracePacket::
518                                         SEQ_INCREMENTAL_STATE_CLEARED) {
519         incremental_state_was_cleared = true;
520         categories.clear();
521         event_names.clear();
522         debug_annotation_names.clear();
523         seen_tracks.clear();
524       }
525 
526       if (packet.has_track_descriptor()) {
527         // Make sure we haven't seen any events on this track before the
528         // descriptor was written.
529         EXPECT_EQ(seen_tracks.find(packet.track_descriptor().uuid()),
530                   seen_tracks.end());
531       }
532 
533       if (!packet.has_track_event())
534         continue;
535 
536       // Make sure we only see track events on one sequence.
537       if (packet.trusted_packet_sequence_id()) {
538         if (!sequence_id)
539           sequence_id = packet.trusted_packet_sequence_id();
540         EXPECT_EQ(sequence_id, packet.trusted_packet_sequence_id());
541       }
542 
543       // Update incremental state.
544       if (packet.has_interned_data()) {
545         const auto& interned_data = packet.interned_data();
546         for (const auto& it : interned_data.event_categories()) {
547           EXPECT_EQ(categories.find(it.iid()), categories.end());
548           categories[it.iid()] = it.name();
549         }
550         for (const auto& it : interned_data.event_names()) {
551           EXPECT_EQ(event_names.find(it.iid()), event_names.end());
552           event_names[it.iid()] = it.name();
553         }
554         for (const auto& it : interned_data.debug_annotation_names()) {
555           EXPECT_EQ(debug_annotation_names.find(it.iid()),
556                     debug_annotation_names.end());
557           debug_annotation_names[it.iid()] = it.name();
558         }
559       }
560       const auto& track_event = packet.track_event();
561       std::string slice;
562 
563       if (track_event.has_track_uuid()) {
564         seen_tracks.insert(track_event.track_uuid());
565         std::stringstream track;
566         track << "[track=" << track_event.track_uuid() << "]";
567         slice += track.str();
568       }
569 
570       switch (track_event.type()) {
571         case perfetto::protos::gen::TrackEvent::TYPE_SLICE_BEGIN:
572           slice += "B";
573           break;
574         case perfetto::protos::gen::TrackEvent::TYPE_SLICE_END:
575           slice += "E";
576           break;
577         case perfetto::protos::gen::TrackEvent::TYPE_INSTANT:
578           slice += "I";
579           break;
580         case perfetto::protos::gen::TrackEvent::TYPE_UNSPECIFIED: {
581           EXPECT_TRUE(track_event.has_legacy_event());
582           EXPECT_FALSE(track_event.type());
583           auto legacy_event = track_event.legacy_event();
584           slice += "Legacy_" +
585                    std::string(1, static_cast<char>(legacy_event.phase()));
586           break;
587         }
588         case perfetto::protos::gen::TrackEvent::TYPE_COUNTER:
589           slice += "C";
590           break;
591         default:
592           ADD_FAILURE();
593       }
594       if (track_event.has_legacy_event()) {
595         auto legacy_event = track_event.legacy_event();
596         std::stringstream id;
597         if (legacy_event.has_unscoped_id()) {
598           id << "(unscoped_id=" << legacy_event.unscoped_id() << ")";
599         } else if (legacy_event.has_local_id()) {
600           id << "(local_id=" << legacy_event.local_id() << ")";
601         } else if (legacy_event.has_global_id()) {
602           id << "(global_id=" << legacy_event.global_id() << ")";
603         } else if (legacy_event.has_bind_id()) {
604           id << "(bind_id=" << legacy_event.bind_id() << ")";
605         }
606         if (legacy_event.has_id_scope())
607           id << "(id_scope=\"" << legacy_event.id_scope() << "\")";
608         if (legacy_event.use_async_tts())
609           id << "(use_async_tts)";
610         if (legacy_event.bind_to_enclosing())
611           id << "(bind_to_enclosing)";
612         if (legacy_event.has_flow_direction())
613           id << "(flow_direction=" << legacy_event.flow_direction() << ")";
614         if (legacy_event.has_pid_override())
615           id << "(pid_override=" << legacy_event.pid_override() << ")";
616         if (legacy_event.has_tid_override())
617           id << "(tid_override=" << legacy_event.tid_override() << ")";
618         slice += id.str();
619       }
620       size_t category_count = 0;
621       for (const auto& it : track_event.category_iids())
622         slice += (category_count++ ? "," : ":") + categories[it];
623       for (const auto& it : track_event.categories())
624         slice += (category_count++ ? ",$" : ":$") + it;
625       if (track_event.has_name_iid())
626         slice += "." + event_names[track_event.name_iid()];
627 
628       if (track_event.debug_annotations_size()) {
629         slice += "(";
630         bool first_annotation = true;
631         for (const auto& it : track_event.debug_annotations()) {
632           if (!first_annotation) {
633             slice += ",";
634           }
635           slice += debug_annotation_names[it.name_iid()] + "=";
636           std::stringstream value;
637           if (it.has_bool_value()) {
638             value << "(bool)" << it.bool_value();
639           } else if (it.has_uint_value()) {
640             value << "(uint)" << it.uint_value();
641           } else if (it.has_int_value()) {
642             value << "(int)" << it.int_value();
643           } else if (it.has_double_value()) {
644             value << "(double)" << it.double_value();
645           } else if (it.has_string_value()) {
646             value << "(string)" << it.string_value();
647           } else if (it.has_pointer_value()) {
648             value << "(pointer)" << std::hex << it.pointer_value();
649           } else if (it.has_legacy_json_value()) {
650             value << "(json)" << it.legacy_json_value();
651           } else if (it.has_nested_value()) {
652             value << "(nested)" << it.nested_value().string_value();
653           }
654           slice += value.str();
655           first_annotation = false;
656         }
657         slice += ")";
658       }
659 
660       slices.push_back(slice);
661     }
662     EXPECT_TRUE(incremental_state_was_cleared);
663     return slices;
664   }
665 
GetMainThreadPacketSequenceId(const perfetto::protos::gen::Trace & trace)666   uint32_t GetMainThreadPacketSequenceId(
667       const perfetto::protos::gen::Trace& trace) {
668     for (const auto& packet : trace.packet()) {
669       if (packet.has_track_descriptor() &&
670           packet.track_descriptor().thread().tid() ==
671               static_cast<int32_t>(perfetto::base::GetThreadId())) {
672         return packet.trusted_packet_sequence_id();
673       }
674     }
675     ADD_FAILURE() << "Main thread not found";
676     return 0;
677   }
678 
679   std::map<std::string, TestDataSourceHandle> data_sources_;
680   std::list<TestTracingSessionHandle> sessions_;  // Needs stable pointers.
681 };
682 
683 // ---------------------------------------------
684 // Definitions for non-inlineable helper methods
685 // ---------------------------------------------
686 PerfettoApiTest* PerfettoApiTest::instance;
687 
OnSetup(const SetupArgs & args)688 void MockDataSource::OnSetup(const SetupArgs& args) {
689   EXPECT_EQ(handle_, nullptr);
690   auto it = PerfettoApiTest::instance->data_sources_.find(args.config->name());
691 
692   // We should not see an OnSetup for a data source that we didn't register
693   // before via PerfettoApiTest::RegisterDataSource().
694   EXPECT_NE(it, PerfettoApiTest::instance->data_sources_.end());
695   handle_ = &it->second;
696   handle_->config = *args.config;  // Deliberate copy.
697   handle_->on_setup.Notify();
698 }
699 
OnStart(const StartArgs &)700 void MockDataSource::OnStart(const StartArgs&) {
701   EXPECT_NE(handle_, nullptr);
702   if (handle_->on_start_callback)
703     handle_->on_start_callback();
704   handle_->on_start.Notify();
705 }
706 
OnStop(const StopArgs & args)707 void MockDataSource::OnStop(const StopArgs& args) {
708   EXPECT_NE(handle_, nullptr);
709   if (handle_->handle_stop_asynchronously)
710     handle_->async_stop_closure = args.HandleStopAsynchronously();
711   if (handle_->on_stop_callback)
712     handle_->on_stop_callback();
713   handle_->on_stop.Notify();
714 }
715 
716 // -------------
717 // Test fixtures
718 // -------------
719 
TEST_P(PerfettoApiTest,StartAndStopWithoutDataSources)720 TEST_P(PerfettoApiTest, StartAndStopWithoutDataSources) {
721   // Create a new trace session without any data sources configured.
722   perfetto::TraceConfig cfg;
723   cfg.add_buffers()->set_size_kb(1024);
724   auto* tracing_session = NewTrace(cfg);
725   // This should not timeout.
726   tracing_session->get()->StartBlocking();
727   tracing_session->get()->StopBlocking();
728 }
729 
730 // Disabled by default because it leaks tracing sessions into subsequent tests,
731 // which can result in the per-uid tracing session limit (5) to be hit in later
732 // tests.
TEST_P(PerfettoApiTest,DISABLED_TrackEventStartStopAndDestroy)733 TEST_P(PerfettoApiTest, DISABLED_TrackEventStartStopAndDestroy) {
734   // This test used to cause a use after free as the tracing session got
735   // destroyed. It needed to be run approximately 2000 times to catch it so test
736   // with --gtest_repeat=3000 (less if running under GDB).
737 
738   // Setup the trace config.
739   perfetto::TraceConfig cfg;
740   cfg.set_duration_ms(500);
741   cfg.add_buffers()->set_size_kb(1024);
742   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
743   ds_cfg->set_name("track_event");
744 
745   // Create five new trace sessions.
746   std::vector<std::unique_ptr<perfetto::TracingSession>> sessions;
747   for (size_t i = 0; i < 5; ++i) {
748     sessions.push_back(perfetto::Tracing::NewTrace(/*BackendType=*/GetParam()));
749     sessions[i]->Setup(cfg);
750     sessions[i]->Start();
751     sessions[i]->Stop();
752   }
753 }
754 
TEST_P(PerfettoApiTest,TrackEventStartStopAndStopBlocking)755 TEST_P(PerfettoApiTest, TrackEventStartStopAndStopBlocking) {
756   // This test used to cause a deadlock (due to StopBlocking() after the session
757   // already stopped). This usually occurred within 1 or 2 runs of the test so
758   // use --gtest_repeat=10
759 
760   // Setup the trace config.
761   perfetto::TraceConfig cfg;
762   cfg.set_duration_ms(500);
763   cfg.add_buffers()->set_size_kb(1024);
764   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
765   ds_cfg->set_name("track_event");
766 
767   // Create five new trace sessions.
768   std::vector<std::unique_ptr<perfetto::TracingSession>> sessions;
769   for (size_t i = 0; i < 5; ++i) {
770     sessions.push_back(perfetto::Tracing::NewTrace(/*BackendType=*/GetParam()));
771     sessions[i]->Setup(cfg);
772     sessions[i]->Start();
773     sessions[i]->Stop();
774   }
775   for (auto& session : sessions) {
776     session->StopBlocking();
777   }
778 }
779 
TEST_P(PerfettoApiTest,ChangeTraceConfiguration)780 TEST_P(PerfettoApiTest, ChangeTraceConfiguration) {
781   // Setup the trace config.
782   perfetto::TraceConfig trace_config;
783   trace_config.set_duration_ms(2000);
784   trace_config.add_buffers()->set_size_kb(1024);
785   auto* data_source = trace_config.add_data_sources();
786 
787   // Configure track events with category "foo".
788   auto* ds_cfg = data_source->mutable_config();
789   ds_cfg->set_name("track_event");
790   perfetto::protos::gen::TrackEventConfig te_cfg;
791   te_cfg.add_disabled_categories("*");
792   te_cfg.add_enabled_categories("foo");
793   ds_cfg->set_track_event_config_raw(te_cfg.SerializeAsString());
794 
795   // Initially, exclude all producers (the client library's producer is named
796   // after current process's name, which will not match
797   // "all_producers_excluded").
798   data_source->add_producer_name_filter("all_producers_excluded");
799 
800   auto* tracing_session = NewTrace(trace_config);
801 
802   tracing_session->get()->StartBlocking();
803 
804   // Emit a first trace event, this one should be filtered out due
805   // to the mismatching producer name filter.
806   TRACE_EVENT_BEGIN("foo", "EventFilteredOut");
807   TRACE_EVENT_END("foo");
808 
809   // Remove the producer name filter by changing configs.
810   data_source->clear_producer_name_filter();
811   tracing_session->get()->ChangeTraceConfig(trace_config);
812 
813   // We don't have a blocking version of ChangeTraceConfig, because there is
814   // currently no response to it from producers or the service. Instead, we sync
815   // the consumer and producer IPC streams for this test, to ensure that the
816   // producer_name_filter change has propagated.
817   tracing_session->get()->GetTraceStatsBlocking();  // sync consumer stream.
818   perfetto::test::SyncProducers();                  // sync producer stream.
819 
820   // Emit a second trace event, this one should be included because
821   // the producer name filter was cleared.
822   TRACE_EVENT_BEGIN("foo", "EventIncluded");
823   TRACE_EVENT_END("foo");
824   tracing_session->get()->StopBlocking();
825 
826   // Verify that only the second event is in the trace data.
827   std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
828   std::string trace(raw_trace.data(), raw_trace.size());
829   EXPECT_THAT(trace, Not(HasSubstr("EventFilteredOut")));
830   EXPECT_THAT(trace, HasSubstr("EventIncluded"));
831 }
832 
833 // This is a build-only regression test that checks you can have a track event
834 // inside a template.
835 template <typename T>
TestTrackEventInsideTemplate(T)836 void TestTrackEventInsideTemplate(T) {
837   TRACE_EVENT_BEGIN("cat", "Name");
838 }
839 
840 // This is a build-only regression test that checks you can specify the tracing
841 // category as a template argument.
842 constexpr const char kTestCategory[] = "foo";
843 template <const char* category>
TestCategoryAsTemplateParameter()844 void TestCategoryAsTemplateParameter() {
845   TRACE_EVENT_BEGIN(category, "Name");
846 }
847 
TEST_P(PerfettoApiTest,TrackEvent)848 TEST_P(PerfettoApiTest, TrackEvent) {
849   // Create a new trace session.
850   auto* tracing_session = NewTraceWithCategories({"test"});
851   tracing_session->get()->StartBlocking();
852 
853   // Emit one complete track event.
854   TRACE_EVENT_BEGIN("test", "TestEvent");
855   TRACE_EVENT_END("test");
856   perfetto::TrackEvent::Flush();
857 
858   tracing_session->on_stop.Wait();
859   std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
860   ASSERT_GE(raw_trace.size(), 0u);
861 
862   // Read back the trace, maintaining interning tables as we go.
863   perfetto::protos::gen::Trace trace;
864   std::map<uint64_t, std::string> categories;
865   std::map<uint64_t, std::string> event_names;
866   ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
867 
868   auto now = perfetto::TrackEvent::GetTraceTimeNs();
869 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE) && \
870     !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
871   auto clock_id = perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME;
872 #else
873   auto clock_id = perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC;
874 #endif
875   EXPECT_EQ(clock_id, perfetto::TrackEvent::GetTraceClockId());
876 
877   bool incremental_state_was_cleared = false;
878   bool begin_found = false;
879   bool end_found = false;
880   bool process_descriptor_found = false;
881   uint32_t sequence_id = 0;
882   int32_t cur_pid = perfetto::test::GetCurrentProcessId();
883   for (const auto& packet : trace.packet()) {
884     if (packet.has_track_descriptor()) {
885       const auto& desc = packet.track_descriptor();
886       if (desc.has_process()) {
887         EXPECT_FALSE(process_descriptor_found);
888         const auto& pd = desc.process();
889         EXPECT_EQ(cur_pid, pd.pid());
890         process_descriptor_found = true;
891       }
892     }
893     if (packet.sequence_flags() &
894         perfetto::protos::pbzero::TracePacket::SEQ_INCREMENTAL_STATE_CLEARED) {
895       EXPECT_TRUE(packet.has_trace_packet_defaults());
896       incremental_state_was_cleared = true;
897       categories.clear();
898       event_names.clear();
899     }
900 
901     if (!packet.has_track_event())
902       continue;
903     EXPECT_TRUE(
904         packet.sequence_flags() &
905         (perfetto::protos::pbzero::TracePacket::SEQ_INCREMENTAL_STATE_CLEARED |
906          perfetto::protos::pbzero::TracePacket::SEQ_NEEDS_INCREMENTAL_STATE));
907     const auto& track_event = packet.track_event();
908 
909     // Make sure we only see track events on one sequence.
910     if (packet.trusted_packet_sequence_id()) {
911       if (!sequence_id)
912         sequence_id = packet.trusted_packet_sequence_id();
913       EXPECT_EQ(sequence_id, packet.trusted_packet_sequence_id());
914     }
915 
916     // Update incremental state.
917     if (packet.has_interned_data()) {
918       const auto& interned_data = packet.interned_data();
919       for (const auto& it : interned_data.event_categories()) {
920         EXPECT_EQ(categories.find(it.iid()), categories.end());
921         categories[it.iid()] = it.name();
922       }
923       for (const auto& it : interned_data.event_names()) {
924         EXPECT_EQ(event_names.find(it.iid()), event_names.end());
925         event_names[it.iid()] = it.name();
926       }
927     }
928 
929     EXPECT_GT(packet.timestamp(), 0u);
930     EXPECT_LE(packet.timestamp(), now);
931 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE) && \
932     !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
933     EXPECT_FALSE(packet.has_timestamp_clock_id());
934 #else
935     constexpr auto kClockMonotonic =
936         perfetto::protos::pbzero::ClockSnapshot::Clock::MONOTONIC;
937     EXPECT_EQ(packet.timestamp_clock_id(),
938               static_cast<uint32_t>(kClockMonotonic));
939 #endif
940     if (track_event.type() ==
941         perfetto::protos::gen::TrackEvent::TYPE_SLICE_BEGIN) {
942       EXPECT_FALSE(begin_found);
943       EXPECT_EQ(track_event.category_iids().size(), 1u);
944       EXPECT_GE(track_event.category_iids()[0], 1u);
945       EXPECT_EQ("test", categories[track_event.category_iids()[0]]);
946       EXPECT_EQ("TestEvent", event_names[track_event.name_iid()]);
947       begin_found = true;
948     } else if (track_event.type() ==
949                perfetto::protos::gen::TrackEvent::TYPE_SLICE_END) {
950       EXPECT_FALSE(end_found);
951       EXPECT_EQ(track_event.category_iids().size(), 0u);
952       EXPECT_EQ(0u, track_event.name_iid());
953       end_found = true;
954     }
955   }
956   EXPECT_TRUE(incremental_state_was_cleared);
957   EXPECT_TRUE(process_descriptor_found);
958   EXPECT_TRUE(begin_found);
959   EXPECT_TRUE(end_found);
960 
961   // Dummy instantiation of test templates.
962   TestTrackEventInsideTemplate(true);
963   TestCategoryAsTemplateParameter<kTestCategory>();
964 }
965 
TEST_P(PerfettoApiTest,TrackEventCategories)966 TEST_P(PerfettoApiTest, TrackEventCategories) {
967   // Create a new trace session.
968   auto* tracing_session = NewTraceWithCategories({"bar"});
969   tracing_session->get()->StartBlocking();
970 
971   // Emit some track events.
972   TRACE_EVENT_BEGIN("foo", "NotEnabled");
973   TRACE_EVENT_END("foo");
974   TRACE_EVENT_BEGIN("bar", "Enabled");
975   TRACE_EVENT_END("bar");
976 
977   tracing_session->get()->StopBlocking();
978   std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
979   std::string trace(raw_trace.data(), raw_trace.size());
980   // TODO(skyostil): Come up with a nicer way to verify trace contents.
981   EXPECT_THAT(trace, HasSubstr("Enabled"));
982   EXPECT_THAT(trace, Not(HasSubstr("NotEnabled")));
983 }
984 
TEST_P(PerfettoApiTest,ClearIncrementalState)985 TEST_P(PerfettoApiTest, ClearIncrementalState) {
986   perfetto::DataSourceDescriptor dsd;
987   dsd.set_name("incr_data_source");
988   TestIncrementalDataSource::Register(dsd);
989   perfetto::test::SyncProducers();
990 
991   // Setup the trace config with an incremental state clearing period.
992   perfetto::TraceConfig cfg;
993   cfg.set_duration_ms(500);
994   cfg.add_buffers()->set_size_kb(1024);
995   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
996   ds_cfg->set_name("incr_data_source");
997   auto* is_cfg = cfg.mutable_incremental_state_config();
998   is_cfg->set_clear_period_ms(10);
999 
1000   // Create a new trace session.
1001   auto* tracing_session = NewTrace(cfg);
1002   tracing_session->get()->StartBlocking();
1003 
1004   // Observe at least 5 incremental state resets.
1005   constexpr size_t kMaxLoops = 100;
1006   size_t loops = 0;
1007   size_t times_cleared = 0;
1008   while (times_cleared < 5) {
1009     ASSERT_LT(loops++, kMaxLoops);
1010     TestIncrementalDataSource::Trace(
1011         [&](TestIncrementalDataSource::TraceContext ctx) {
1012           auto* incr_state = ctx.GetIncrementalState();
1013           if (!incr_state->flag) {
1014             incr_state->flag = true;
1015             times_cleared++;
1016           }
1017         });
1018     std::this_thread::sleep_for(std::chrono::milliseconds(10));
1019   }
1020   tracing_session->get()->StopBlocking();
1021 }
1022 
TEST_P(PerfettoApiTest,TrackEventRegistrationWithModule)1023 TEST_P(PerfettoApiTest, TrackEventRegistrationWithModule) {
1024   MockTracingMuxer muxer;
1025 
1026   // Each track event namespace registers its own data source.
1027   perfetto::TrackEvent::Register();
1028   EXPECT_EQ(1u, muxer.data_sources.size());
1029 
1030   tracing_module::InitializeCategories();
1031   EXPECT_EQ(2u, muxer.data_sources.size());
1032 
1033   // Both data sources have the same name but distinct static data (i.e.,
1034   // individual instance states).
1035   EXPECT_EQ("track_event", muxer.data_sources[0].dsd.name());
1036   EXPECT_EQ("track_event", muxer.data_sources[1].dsd.name());
1037   EXPECT_NE(muxer.data_sources[0].static_state,
1038             muxer.data_sources[1].static_state);
1039 }
1040 
TEST_P(PerfettoApiTest,TrackEventDescriptor)1041 TEST_P(PerfettoApiTest, TrackEventDescriptor) {
1042   MockTracingMuxer muxer;
1043 
1044   perfetto::TrackEvent::Register();
1045   EXPECT_EQ(1u, muxer.data_sources.size());
1046   EXPECT_EQ("track_event", muxer.data_sources[0].dsd.name());
1047 
1048   perfetto::protos::gen::TrackEventDescriptor desc;
1049   auto desc_raw = muxer.data_sources[0].dsd.track_event_descriptor_raw();
1050   EXPECT_TRUE(desc.ParseFromArray(desc_raw.data(), desc_raw.size()));
1051 
1052   // Check that the advertised categories match PERFETTO_DEFINE_CATEGORIES (see
1053   // above).
1054   EXPECT_EQ(7, desc.available_categories_size());
1055   EXPECT_EQ("test", desc.available_categories()[0].name());
1056   EXPECT_EQ("This is a test category",
1057             desc.available_categories()[0].description());
1058   EXPECT_EQ("tag", desc.available_categories()[0].tags()[0]);
1059   EXPECT_EQ("foo", desc.available_categories()[1].name());
1060   EXPECT_EQ("bar", desc.available_categories()[2].name());
1061   EXPECT_EQ("cat", desc.available_categories()[3].name());
1062   EXPECT_EQ("slow", desc.available_categories()[3].tags()[0]);
1063   EXPECT_EQ("cat.verbose", desc.available_categories()[4].name());
1064   EXPECT_EQ("debug", desc.available_categories()[4].tags()[0]);
1065   EXPECT_EQ("cat-with-dashes", desc.available_categories()[5].name());
1066   EXPECT_EQ("disabled-by-default-cat", desc.available_categories()[6].name());
1067   EXPECT_EQ("slow", desc.available_categories()[6].tags()[0]);
1068 }
1069 
TEST_P(PerfettoApiTest,TrackEventSharedIncrementalState)1070 TEST_P(PerfettoApiTest, TrackEventSharedIncrementalState) {
1071   tracing_module::InitializeCategories();
1072 
1073   // Setup the trace config.
1074   perfetto::TraceConfig cfg;
1075   cfg.set_duration_ms(500);
1076   cfg.add_buffers()->set_size_kb(1024);
1077   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
1078   ds_cfg->set_name("track_event");
1079   auto* tracing_session = NewTrace(cfg);
1080   tracing_session->get()->StartBlocking();
1081 
1082   perfetto::internal::TrackEventIncrementalState* main_state = nullptr;
1083   perfetto::TrackEvent::Trace(
1084       [&main_state](perfetto::TrackEvent::TraceContext ctx) {
1085         main_state = ctx.GetIncrementalState();
1086       });
1087   perfetto::internal::TrackEventIncrementalState* module_state =
1088       tracing_module::GetIncrementalState();
1089 
1090   // Both track event data sources should use the same incremental state (thanks
1091   // to sharing TLS).
1092   EXPECT_NE(nullptr, main_state);
1093   EXPECT_EQ(main_state, module_state);
1094   tracing_session->get()->StopBlocking();
1095 }
1096 
TEST_P(PerfettoApiTest,TrackEventCategoriesWithModule)1097 TEST_P(PerfettoApiTest, TrackEventCategoriesWithModule) {
1098   // Check that categories defined in two different category registries are
1099   // enabled and disabled correctly.
1100   tracing_module::InitializeCategories();
1101 
1102   // Create a new trace session. Only the "foo" category is enabled. It also
1103   // exists both locally and in the existing module.
1104   auto* tracing_session = NewTraceWithCategories({"foo"});
1105   tracing_session->get()->StartBlocking();
1106 
1107   // Emit some track events locally and from the test module.
1108   TRACE_EVENT_BEGIN("foo", "FooEventFromMain");
1109   TRACE_EVENT_END("foo");
1110   tracing_module::EmitTrackEvents();
1111   tracing_module::EmitTrackEvents2();
1112   TRACE_EVENT_BEGIN("bar", "DisabledEventFromMain");
1113   TRACE_EVENT_END("bar");
1114 
1115   tracing_session->get()->StopBlocking();
1116   std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
1117   std::string trace(raw_trace.data(), raw_trace.size());
1118   EXPECT_THAT(trace, HasSubstr("FooEventFromMain"));
1119   EXPECT_THAT(trace, Not(HasSubstr("DisabledEventFromMain")));
1120   EXPECT_THAT(trace, HasSubstr("FooEventFromModule"));
1121   EXPECT_THAT(trace, Not(HasSubstr("DisabledEventFromModule")));
1122   EXPECT_THAT(trace, HasSubstr("FooEventFromModule2"));
1123   EXPECT_THAT(trace, Not(HasSubstr("DisabledEventFromModule2")));
1124 
1125   perfetto::protos::gen::Trace parsed_trace;
1126   ASSERT_TRUE(parsed_trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
1127 
1128   uint32_t sequence_id = 0;
1129   for (const auto& packet : parsed_trace.packet()) {
1130     if (!packet.has_track_event())
1131       continue;
1132 
1133     // Make sure we only see track events on one sequence. This means all track
1134     // event modules are sharing the same trace writer (by using the same TLS
1135     // index).
1136     if (packet.trusted_packet_sequence_id()) {
1137       if (!sequence_id)
1138         sequence_id = packet.trusted_packet_sequence_id();
1139       EXPECT_EQ(sequence_id, packet.trusted_packet_sequence_id());
1140     }
1141   }
1142 }
1143 
TEST_P(PerfettoApiTest,TrackEventDynamicCategories)1144 TEST_P(PerfettoApiTest, TrackEventDynamicCategories) {
1145   // Setup the trace config.
1146   perfetto::TraceConfig cfg;
1147   cfg.set_duration_ms(500);
1148   cfg.add_buffers()->set_size_kb(1024);
1149   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
1150   ds_cfg->set_name("track_event");
1151 
1152   // Session #1 enabled the "dynamic" category.
1153   auto* tracing_session = NewTraceWithCategories({"dynamic"});
1154   tracing_session->get()->StartBlocking();
1155 
1156   // Session #2 enables "dynamic_2".
1157   auto* tracing_session2 = NewTraceWithCategories({"dynamic_2"});
1158   tracing_session2->get()->StartBlocking();
1159 
1160   // Test naming dynamic categories with std::string.
1161   perfetto::DynamicCategory dynamic{"dynamic"};
1162   TRACE_EVENT_BEGIN(dynamic, "EventInDynamicCategory");
1163   perfetto::DynamicCategory dynamic_disabled{"dynamic_disabled"};
1164   TRACE_EVENT_BEGIN(dynamic_disabled, "EventInDisabledDynamicCategory");
1165 
1166   // Test naming dynamic categories statically.
1167   TRACE_EVENT_BEGIN("dynamic", "EventInStaticallyNamedDynamicCategory");
1168 
1169   perfetto::DynamicCategory dynamic_2{"dynamic_2"};
1170   TRACE_EVENT_BEGIN(dynamic_2, "EventInSecondDynamicCategory");
1171   TRACE_EVENT_BEGIN("dynamic_2", "EventInSecondStaticallyNamedDynamicCategory");
1172 
1173   std::thread thread([] {
1174     // Make sure the category name can actually be computed at runtime.
1175     std::string name = "dyn";
1176     if (perfetto::base::GetThreadId())
1177       name += "amic";
1178     perfetto::DynamicCategory cat{name};
1179     TRACE_EVENT_BEGIN(cat, "DynamicFromOtherThread");
1180     perfetto::DynamicCategory cat2{"dynamic_disabled"};
1181     TRACE_EVENT_BEGIN(cat2, "EventInDisabledDynamicCategory");
1182   });
1183   thread.join();
1184 
1185   perfetto::TrackEvent::Flush();
1186   tracing_session->get()->StopBlocking();
1187   std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
1188   std::string trace(raw_trace.data(), raw_trace.size());
1189   EXPECT_THAT(trace, HasSubstr("EventInDynamicCategory"));
1190   EXPECT_THAT(trace, Not(HasSubstr("EventInDisabledDynamicCategory")));
1191   EXPECT_THAT(trace, HasSubstr("DynamicFromOtherThread"));
1192   EXPECT_THAT(trace, Not(HasSubstr("EventInSecondDynamicCategory")));
1193   EXPECT_THAT(trace, HasSubstr("EventInStaticallyNamedDynamicCategory"));
1194   EXPECT_THAT(trace,
1195               Not(HasSubstr("EventInSecondStaticallyNamedDynamicCategory")));
1196 
1197   tracing_session2->get()->StopBlocking();
1198   raw_trace = tracing_session2->get()->ReadTraceBlocking();
1199   trace = std::string(raw_trace.data(), raw_trace.size());
1200   EXPECT_THAT(trace, Not(HasSubstr("EventInDynamicCategory")));
1201   EXPECT_THAT(trace, Not(HasSubstr("EventInDisabledDynamicCategory")));
1202   EXPECT_THAT(trace, Not(HasSubstr("DynamicFromOtherThread")));
1203   EXPECT_THAT(trace, HasSubstr("EventInSecondDynamicCategory"));
1204   EXPECT_THAT(trace, Not(HasSubstr("EventInStaticallyNamedDynamicCategory")));
1205   EXPECT_THAT(trace, HasSubstr("EventInSecondStaticallyNamedDynamicCategory"));
1206 }
1207 
TEST_P(PerfettoApiTest,TrackEventConcurrentSessions)1208 TEST_P(PerfettoApiTest, TrackEventConcurrentSessions) {
1209   // Check that categories that are enabled and disabled in two parallel tracing
1210   // sessions don't interfere.
1211 
1212   // Session #1 enables the "foo" category.
1213   auto* tracing_session = NewTraceWithCategories({"foo"});
1214   tracing_session->get()->StartBlocking();
1215 
1216   // Session #2 enables the "bar" category.
1217   auto* tracing_session2 = NewTraceWithCategories({"bar"});
1218   tracing_session2->get()->StartBlocking();
1219 
1220   // Emit some track events under both categories.
1221   TRACE_EVENT_BEGIN("foo", "Session1_First");
1222   TRACE_EVENT_END("foo");
1223   TRACE_EVENT_BEGIN("bar", "Session2_First");
1224   TRACE_EVENT_END("bar");
1225 
1226   tracing_session->get()->StopBlocking();
1227   TRACE_EVENT_BEGIN("foo", "Session1_Second");
1228   TRACE_EVENT_END("foo");
1229   TRACE_EVENT_BEGIN("bar", "Session2_Second");
1230   TRACE_EVENT_END("bar");
1231 
1232   tracing_session2->get()->StopBlocking();
1233   TRACE_EVENT_BEGIN("foo", "Session1_Third");
1234   TRACE_EVENT_END("foo");
1235   TRACE_EVENT_BEGIN("bar", "Session2_Third");
1236   TRACE_EVENT_END("bar");
1237 
1238   std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
1239   std::string trace(raw_trace.data(), raw_trace.size());
1240   EXPECT_THAT(trace, HasSubstr("Session1_First"));
1241   EXPECT_THAT(trace, Not(HasSubstr("Session1_Second")));
1242   EXPECT_THAT(trace, Not(HasSubstr("Session1_Third")));
1243   EXPECT_THAT(trace, Not(HasSubstr("Session2_First")));
1244   EXPECT_THAT(trace, Not(HasSubstr("Session2_Second")));
1245   EXPECT_THAT(trace, Not(HasSubstr("Session2_Third")));
1246 
1247   std::vector<char> raw_trace2 = tracing_session2->get()->ReadTraceBlocking();
1248   std::string trace2(raw_trace2.data(), raw_trace2.size());
1249   EXPECT_THAT(trace2, Not(HasSubstr("Session1_First")));
1250   EXPECT_THAT(trace2, Not(HasSubstr("Session1_Second")));
1251   EXPECT_THAT(trace2, Not(HasSubstr("Session1_Third")));
1252   EXPECT_THAT(trace2, HasSubstr("Session2_First"));
1253   EXPECT_THAT(trace2, HasSubstr("Session2_Second"));
1254   EXPECT_THAT(trace2, Not(HasSubstr("Session2_Third")));
1255 }
1256 
TEST_P(PerfettoApiTest,TrackEventProcessAndThreadDescriptors)1257 TEST_P(PerfettoApiTest, TrackEventProcessAndThreadDescriptors) {
1258   // Thread and process descriptors can be set before tracing is enabled.
1259   perfetto::TrackEvent::SetProcessDescriptor(
1260       [](perfetto::protos::pbzero::TrackDescriptor* desc) {
1261         desc->set_name("hello.exe");
1262         desc->set_chrome_process()->set_process_priority(1);
1263       });
1264 
1265   // Erased tracks shouldn't show up anywhere.
1266   perfetto::Track erased(1234u);
1267   perfetto::TrackEvent::SetTrackDescriptor(
1268       erased, [](perfetto::protos::pbzero::TrackDescriptor* desc) {
1269         desc->set_name("ErasedTrack");
1270       });
1271   perfetto::TrackEvent::EraseTrackDescriptor(erased);
1272 
1273   // Setup the trace config.
1274   perfetto::TraceConfig cfg;
1275   cfg.set_duration_ms(500);
1276   cfg.add_buffers()->set_size_kb(1024);
1277   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
1278   ds_cfg->set_name("track_event");
1279 
1280   // Create a new trace session.
1281   auto* tracing_session = NewTrace(cfg);
1282   tracing_session->get()->StartBlocking();
1283   TRACE_EVENT_INSTANT("test", "MainThreadEvent");
1284 
1285   std::thread thread([&] {
1286     perfetto::TrackEvent::SetThreadDescriptor(
1287         [](perfetto::protos::pbzero::TrackDescriptor* desc) {
1288           desc->set_name("TestThread");
1289         });
1290     TRACE_EVENT_INSTANT("test", "ThreadEvent");
1291   });
1292   thread.join();
1293 
1294   // Update the process descriptor while tracing is enabled. It should be
1295   // immediately reflected in the trace.
1296   perfetto::TrackEvent::SetProcessDescriptor(
1297       [](perfetto::protos::pbzero::TrackDescriptor* desc) {
1298         desc->set_name("goodbye.exe");
1299       });
1300   perfetto::TrackEvent::Flush();
1301 
1302   tracing_session->get()->StopBlocking();
1303 
1304   // After tracing ends, setting the descriptor has no immediate effect.
1305   perfetto::TrackEvent::SetProcessDescriptor(
1306       [](perfetto::protos::pbzero::TrackDescriptor* desc) {
1307         desc->set_name("noop.exe");
1308       });
1309 
1310   std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
1311   perfetto::protos::gen::Trace trace;
1312   ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
1313 
1314   std::vector<perfetto::protos::gen::TrackDescriptor> descs;
1315   std::vector<perfetto::protos::gen::TrackDescriptor> thread_descs;
1316   uint32_t main_thread_sequence = GetMainThreadPacketSequenceId(trace);
1317   for (const auto& packet : trace.packet()) {
1318     if (packet.has_track_descriptor()) {
1319       if (packet.trusted_packet_sequence_id() == main_thread_sequence) {
1320         descs.push_back(packet.track_descriptor());
1321       } else {
1322         thread_descs.push_back(packet.track_descriptor());
1323       }
1324     }
1325   }
1326 
1327   // The main thread records the initial process name as well as the one that's
1328   // set during tracing. Additionally it records a thread descriptor for the
1329   // main thread.
1330 
1331   EXPECT_EQ(3u, descs.size());
1332 
1333   // Default track for the main thread.
1334   EXPECT_EQ(0, descs[0].process().pid());
1335   EXPECT_NE(0, descs[0].thread().pid());
1336 
1337   // First process descriptor.
1338   EXPECT_NE(0, descs[1].process().pid());
1339   EXPECT_EQ("hello.exe", descs[1].name());
1340 
1341   // Second process descriptor.
1342   EXPECT_NE(0, descs[2].process().pid());
1343   EXPECT_EQ("goodbye.exe", descs[2].name());
1344 
1345   // The child thread records only its own thread descriptor (twice, since it
1346   // was mutated).
1347   EXPECT_EQ(2u, thread_descs.size());
1348   EXPECT_EQ("TestThread", thread_descs[0].name());
1349   EXPECT_NE(0, thread_descs[0].thread().pid());
1350   EXPECT_NE(0, thread_descs[0].thread().tid());
1351   EXPECT_EQ("TestThread", thread_descs[1].name());
1352   EXPECT_NE(0, thread_descs[1].thread().pid());
1353   EXPECT_NE(0, thread_descs[1].thread().tid());
1354 }
1355 
TEST_P(PerfettoApiTest,CustomTrackDescriptor)1356 TEST_P(PerfettoApiTest, CustomTrackDescriptor) {
1357   // Setup the trace config.
1358   perfetto::TraceConfig cfg;
1359   cfg.set_duration_ms(500);
1360   cfg.add_buffers()->set_size_kb(1024);
1361   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
1362   ds_cfg->set_name("track_event");
1363 
1364   // Create a new trace session.
1365   auto* tracing_session = NewTrace(cfg);
1366   tracing_session->get()->StartBlocking();
1367 
1368   auto track = perfetto::ProcessTrack::Current();
1369   auto desc = track.Serialize();
1370   desc.mutable_process()->set_process_name("testing.exe");
1371   desc.mutable_thread()->set_tid(
1372       static_cast<int32_t>(perfetto::base::GetThreadId()));
1373   desc.mutable_chrome_process()->set_process_priority(123);
1374   perfetto::TrackEvent::SetTrackDescriptor(track, std::move(desc));
1375   perfetto::TrackEvent::Flush();
1376 
1377   tracing_session->get()->StopBlocking();
1378 
1379   std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
1380   perfetto::protos::gen::Trace trace;
1381   ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
1382 
1383   uint32_t main_thread_sequence = GetMainThreadPacketSequenceId(trace);
1384   bool found_desc = false;
1385   for (const auto& packet : trace.packet()) {
1386     if (packet.trusted_packet_sequence_id() != main_thread_sequence)
1387       continue;
1388     if (packet.has_track_descriptor()) {
1389       auto td = packet.track_descriptor();
1390       EXPECT_TRUE(td.has_process());
1391       EXPECT_NE(0, td.process().pid());
1392       EXPECT_TRUE(td.has_chrome_process());
1393       EXPECT_EQ("testing.exe", td.process().process_name());
1394       EXPECT_EQ(123, td.chrome_process().process_priority());
1395       found_desc = true;
1396     }
1397   }
1398   EXPECT_TRUE(found_desc);
1399 }
1400 
TEST_P(PerfettoApiTest,TrackEventCustomTrack)1401 TEST_P(PerfettoApiTest, TrackEventCustomTrack) {
1402   // Create a new trace session.
1403   auto* tracing_session = NewTraceWithCategories({"bar"});
1404   tracing_session->get()->StartBlocking();
1405 
1406   // Declare a custom track and give it a name.
1407   uint64_t async_id = 123;
1408   perfetto::TrackEvent::SetTrackDescriptor(
1409       perfetto::Track(async_id),
1410       [](perfetto::protos::pbzero::TrackDescriptor* desc) {
1411         desc->set_name("MyCustomTrack");
1412       });
1413 
1414   // Start events on one thread and end them on another.
1415   TRACE_EVENT_BEGIN("bar", "AsyncEvent", perfetto::Track(async_id), "debug_arg",
1416                     123);
1417 
1418   TRACE_EVENT_BEGIN("bar", "SubEvent", perfetto::Track(async_id),
1419                     [](perfetto::EventContext) {});
1420   const auto main_thread_track =
1421       perfetto::Track(async_id, perfetto::ThreadTrack::Current());
1422   std::thread thread([&] {
1423     TRACE_EVENT_END("bar", perfetto::Track(async_id));
1424     TRACE_EVENT_END("bar", perfetto::Track(async_id), "arg1", false, "arg2",
1425                     true);
1426     const auto thread_track =
1427         perfetto::Track(async_id, perfetto::ThreadTrack::Current());
1428     // Thread-scoped tracks will have different uuids on different thread even
1429     // if the id matches.
1430     ASSERT_NE(main_thread_track.uuid, thread_track.uuid);
1431   });
1432   thread.join();
1433 
1434   perfetto::TrackEvent::Flush();
1435   tracing_session->get()->StopBlocking();
1436 
1437   std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
1438   perfetto::protos::gen::Trace trace;
1439   ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
1440 
1441   // Check that the track uuids match on the begin and end events.
1442   const auto track = perfetto::Track(async_id);
1443   uint32_t main_thread_sequence = GetMainThreadPacketSequenceId(trace);
1444   int event_count = 0;
1445   bool found_descriptor = false;
1446   for (const auto& packet : trace.packet()) {
1447     if (packet.has_track_descriptor() &&
1448         !packet.track_descriptor().has_process() &&
1449         !packet.track_descriptor().has_thread()) {
1450       auto td = packet.track_descriptor();
1451       EXPECT_EQ("MyCustomTrack", td.name());
1452       EXPECT_EQ(track.uuid, td.uuid());
1453       EXPECT_EQ(perfetto::ProcessTrack::Current().uuid, td.parent_uuid());
1454       found_descriptor = true;
1455       continue;
1456     }
1457 
1458     if (!packet.has_track_event())
1459       continue;
1460     auto track_event = packet.track_event();
1461     if (track_event.type() ==
1462         perfetto::protos::gen::TrackEvent::TYPE_SLICE_BEGIN) {
1463       EXPECT_EQ(main_thread_sequence, packet.trusted_packet_sequence_id());
1464       EXPECT_EQ(track.uuid, track_event.track_uuid());
1465     } else {
1466       EXPECT_NE(main_thread_sequence, packet.trusted_packet_sequence_id());
1467       EXPECT_EQ(track.uuid, track_event.track_uuid());
1468     }
1469     event_count++;
1470   }
1471   EXPECT_TRUE(found_descriptor);
1472   EXPECT_EQ(4, event_count);
1473   perfetto::TrackEvent::EraseTrackDescriptor(track);
1474 }
1475 
TEST_P(PerfettoApiTest,LegacyEventWithThreadOverride)1476 TEST_P(PerfettoApiTest, LegacyEventWithThreadOverride) {
1477   // Create a new trace session.
1478   auto* tracing_session = NewTraceWithCategories({"cat"});
1479   tracing_session->get()->StartBlocking();
1480 
1481   TRACE_EVENT_BEGIN_WITH_ID_TID_AND_TIMESTAMP0("cat", "Name", 1,
1482                                                MyThreadId(456), MyTimestamp{0});
1483   perfetto::TrackEvent::Flush();
1484   tracing_session->get()->StopBlocking();
1485 
1486   std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
1487   perfetto::protos::gen::Trace trace;
1488   ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
1489 
1490   // Check that we wrote a track descriptor for the custom thread track, and
1491   // that the event was associated with that track.
1492   const auto track = perfetto::ThreadTrack::ForThread(456);
1493   bool found_descriptor = false;
1494   bool found_event = false;
1495   for (const auto& packet : trace.packet()) {
1496     if (packet.has_track_descriptor() &&
1497         packet.track_descriptor().has_thread()) {
1498       auto td = packet.track_descriptor().thread();
1499       if (td.tid() == 456) {
1500         EXPECT_EQ(track.uuid, packet.track_descriptor().uuid());
1501         found_descriptor = true;
1502       }
1503     }
1504 
1505     if (!packet.has_track_event())
1506       continue;
1507     auto track_event = packet.track_event();
1508     if (track_event.legacy_event().phase() == TRACE_EVENT_PHASE_ASYNC_BEGIN) {
1509       EXPECT_EQ(track.uuid, track_event.track_uuid());
1510       found_event = true;
1511     }
1512   }
1513   EXPECT_TRUE(found_descriptor);
1514   EXPECT_TRUE(found_event);
1515   perfetto::TrackEvent::EraseTrackDescriptor(track);
1516 }
1517 
TEST_P(PerfettoApiTest,LegacyEventWithProcessOverride)1518 TEST_P(PerfettoApiTest, LegacyEventWithProcessOverride) {
1519   // Create a new trace session.
1520   auto* tracing_session = NewTraceWithCategories({"cat"});
1521   tracing_session->get()->StartBlocking();
1522 
1523   // Note: there's no direct entrypoint for adding trace events for another
1524   // process, so we're using the internal support macro here.
1525   INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP(
1526       TRACE_EVENT_PHASE_INSTANT, "cat", "Name", 0, MyThreadId{789},
1527       MyTimestamp{0}, TRACE_EVENT_FLAG_HAS_PROCESS_ID);
1528   perfetto::TrackEvent::Flush();
1529   tracing_session->get()->StopBlocking();
1530 
1531   std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
1532   perfetto::protos::gen::Trace trace;
1533   ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
1534 
1535   // Check that the event has a pid_override matching MyThread above.
1536   bool found_event = false;
1537   for (const auto& packet : trace.packet()) {
1538     if (!packet.has_track_event())
1539       continue;
1540     auto track_event = packet.track_event();
1541     if (track_event.type() == perfetto::protos::gen::TrackEvent::TYPE_INSTANT) {
1542       EXPECT_EQ(789, track_event.legacy_event().pid_override());
1543       EXPECT_EQ(-1, track_event.legacy_event().tid_override());
1544       found_event = true;
1545     }
1546   }
1547   EXPECT_TRUE(found_event);
1548 }
1549 
TEST_P(PerfettoApiTest,TrackDescriptorWrittenBeforeEvent)1550 TEST_P(PerfettoApiTest, TrackDescriptorWrittenBeforeEvent) {
1551   // Create a new trace session.
1552   auto* tracing_session = NewTraceWithCategories({"bar"});
1553   tracing_session->get()->StartBlocking();
1554 
1555   // Emit an event on a custom track.
1556   TRACE_EVENT_INSTANT("bar", "Event", perfetto::Track(8086));
1557   perfetto::TrackEvent::Flush();
1558   tracing_session->get()->StopBlocking();
1559 
1560   std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
1561   perfetto::protos::gen::Trace trace;
1562   ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
1563 
1564   // Check that the descriptor was written before the event.
1565   std::set<uint64_t> seen_descriptors;
1566   for (const auto& packet : trace.packet()) {
1567     if (packet.has_track_descriptor())
1568       seen_descriptors.insert(packet.track_descriptor().uuid());
1569 
1570     if (!packet.has_track_event())
1571       continue;
1572     auto track_event = packet.track_event();
1573     EXPECT_TRUE(seen_descriptors.find(track_event.track_uuid()) !=
1574                 seen_descriptors.end());
1575   }
1576 }
1577 
TEST_P(PerfettoApiTest,TrackEventCustomTrackAndTimestamp)1578 TEST_P(PerfettoApiTest, TrackEventCustomTrackAndTimestamp) {
1579   // Create a new trace session.
1580   auto* tracing_session = NewTraceWithCategories({"bar"});
1581   tracing_session->get()->StartBlocking();
1582 
1583   // Custom track.
1584   perfetto::Track track(789);
1585 
1586   auto empty_lambda = [](perfetto::EventContext) {};
1587   constexpr uint64_t kBeginEventTime = 10;
1588   const MyTimestamp kEndEventTime{15};
1589   TRACE_EVENT_BEGIN("bar", "Event", track, kBeginEventTime, empty_lambda);
1590   TRACE_EVENT_END("bar", track, kEndEventTime, empty_lambda);
1591 
1592   constexpr uint64_t kInstantEventTime = 1;
1593   TRACE_EVENT_INSTANT("bar", "InstantEvent", track, kInstantEventTime,
1594                       empty_lambda);
1595 
1596   perfetto::TrackEvent::Flush();
1597   tracing_session->get()->StopBlocking();
1598 
1599   std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
1600   perfetto::protos::gen::Trace trace;
1601   ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
1602 
1603   int event_count = 0;
1604   for (const auto& packet : trace.packet()) {
1605     if (!packet.has_track_event())
1606       continue;
1607     event_count++;
1608     switch (packet.track_event().type()) {
1609       case perfetto::protos::gen::TrackEvent::TYPE_SLICE_BEGIN:
1610         EXPECT_EQ(packet.timestamp(), kBeginEventTime);
1611         break;
1612       case perfetto::protos::gen::TrackEvent::TYPE_SLICE_END:
1613         EXPECT_EQ(packet.timestamp(), kEndEventTime.ts);
1614         break;
1615       case perfetto::protos::gen::TrackEvent::TYPE_INSTANT:
1616         EXPECT_EQ(packet.timestamp(), kInstantEventTime);
1617         break;
1618       case perfetto::protos::gen::TrackEvent::TYPE_COUNTER:
1619       case perfetto::protos::gen::TrackEvent::TYPE_UNSPECIFIED:
1620         ADD_FAILURE();
1621     }
1622   }
1623   EXPECT_EQ(event_count, 3);
1624   perfetto::TrackEvent::EraseTrackDescriptor(track);
1625 }
1626 
TEST_P(PerfettoApiTest,TrackEventCustomTrackAndTimestampNoLambda)1627 TEST_P(PerfettoApiTest, TrackEventCustomTrackAndTimestampNoLambda) {
1628   auto* tracing_session = NewTraceWithCategories({"bar"});
1629   tracing_session->get()->StartBlocking();
1630 
1631   perfetto::Track track(789);
1632 
1633   constexpr uint64_t kBeginEventTime = 10;
1634   constexpr uint64_t kEndEventTime = 15;
1635   TRACE_EVENT_BEGIN("bar", "Event", track, kBeginEventTime);
1636   TRACE_EVENT_END("bar", track, kEndEventTime);
1637 
1638   perfetto::TrackEvent::Flush();
1639   tracing_session->get()->StopBlocking();
1640 
1641   std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
1642   perfetto::protos::gen::Trace trace;
1643   ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
1644 
1645   int event_count = 0;
1646   for (const auto& packet : trace.packet()) {
1647     if (!packet.has_track_event())
1648       continue;
1649     event_count++;
1650     switch (packet.track_event().type()) {
1651       case perfetto::protos::gen::TrackEvent::TYPE_SLICE_BEGIN:
1652         EXPECT_EQ(packet.timestamp(), kBeginEventTime);
1653         break;
1654       case perfetto::protos::gen::TrackEvent::TYPE_SLICE_END:
1655         EXPECT_EQ(packet.timestamp(), kEndEventTime);
1656         break;
1657       case perfetto::protos::gen::TrackEvent::TYPE_INSTANT:
1658       case perfetto::protos::gen::TrackEvent::TYPE_COUNTER:
1659       case perfetto::protos::gen::TrackEvent::TYPE_UNSPECIFIED:
1660         ADD_FAILURE();
1661     }
1662   }
1663 
1664   EXPECT_EQ(event_count, 2);
1665 }
1666 
TEST_P(PerfettoApiTest,TrackEventAnonymousCustomTrack)1667 TEST_P(PerfettoApiTest, TrackEventAnonymousCustomTrack) {
1668   // Create a new trace session.
1669   auto* tracing_session = NewTraceWithCategories({"bar"});
1670   tracing_session->get()->StartBlocking();
1671 
1672   // Emit an async event without giving it an explicit descriptor.
1673   uint64_t async_id = 4004;
1674   auto track = perfetto::Track(async_id, perfetto::ThreadTrack::Current());
1675   TRACE_EVENT_BEGIN("bar", "AsyncEvent", track);
1676   std::thread thread([&] { TRACE_EVENT_END("bar", track); });
1677   thread.join();
1678 
1679   perfetto::TrackEvent::Flush();
1680   tracing_session->get()->StopBlocking();
1681 
1682   std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
1683   perfetto::protos::gen::Trace trace;
1684   ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
1685 
1686   // Check that a descriptor for the track was emitted.
1687   bool found_descriptor = false;
1688   for (const auto& packet : trace.packet()) {
1689     if (packet.has_track_descriptor() &&
1690         !packet.track_descriptor().has_process() &&
1691         !packet.track_descriptor().has_thread()) {
1692       auto td = packet.track_descriptor();
1693       EXPECT_EQ(track.uuid, td.uuid());
1694       EXPECT_EQ(perfetto::ThreadTrack::Current().uuid, td.parent_uuid());
1695       found_descriptor = true;
1696     }
1697   }
1698   EXPECT_TRUE(found_descriptor);
1699 }
1700 
TEST_P(PerfettoApiTest,TrackEventTypedArgs)1701 TEST_P(PerfettoApiTest, TrackEventTypedArgs) {
1702   // Create a new trace session.
1703   auto* tracing_session = NewTraceWithCategories({"foo"});
1704   tracing_session->get()->StartBlocking();
1705 
1706   auto random_value = rand();
1707   TRACE_EVENT_BEGIN("foo", "EventWithTypedArg",
1708                     [random_value](perfetto::EventContext ctx) {
1709                       auto* log = ctx.event()->set_log_message();
1710                       log->set_source_location_iid(1);
1711                       log->set_body_iid(2);
1712                       auto* dbg = ctx.event()->add_debug_annotations();
1713                       dbg->set_name("random");
1714                       dbg->set_int_value(random_value);
1715                     });
1716   TRACE_EVENT_END("foo");
1717 
1718   tracing_session->get()->StopBlocking();
1719   std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
1720   std::string trace(raw_trace.data(), raw_trace.size());
1721 
1722   perfetto::protos::gen::Trace parsed_trace;
1723   ASSERT_TRUE(parsed_trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
1724 
1725   bool found_args = false;
1726   for (const auto& packet : parsed_trace.packet()) {
1727     if (!packet.has_track_event())
1728       continue;
1729     const auto& track_event = packet.track_event();
1730     if (track_event.type() !=
1731         perfetto::protos::gen::TrackEvent::TYPE_SLICE_BEGIN)
1732       continue;
1733 
1734     EXPECT_TRUE(track_event.has_log_message());
1735     const auto& log = track_event.log_message();
1736     EXPECT_EQ(1u, log.source_location_iid());
1737     EXPECT_EQ(2u, log.body_iid());
1738 
1739     const auto& dbg = track_event.debug_annotations()[0];
1740     EXPECT_EQ("random", dbg.name());
1741     EXPECT_EQ(random_value, dbg.int_value());
1742 
1743     found_args = true;
1744   }
1745   EXPECT_TRUE(found_args);
1746 }
1747 
TEST_P(PerfettoApiTest,InlineTrackEventTypedArgs_SimpleRepeated)1748 TEST_P(PerfettoApiTest, InlineTrackEventTypedArgs_SimpleRepeated) {
1749   // Create a new trace session.
1750   auto* tracing_session = NewTraceWithCategories({"foo"});
1751   tracing_session->get()->StartBlocking();
1752 
1753   std::vector<uint64_t> flow_ids{1, 2, 3};
1754   TRACE_EVENT_BEGIN("foo", "EventWithTypedArg",
1755                     perfetto::protos::pbzero::TrackEvent::kFlowIds, flow_ids);
1756   TRACE_EVENT_END("foo");
1757 
1758   tracing_session->get()->StopBlocking();
1759   std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
1760   std::string trace(raw_trace.data(), raw_trace.size());
1761 
1762   perfetto::protos::gen::Trace parsed_trace;
1763   ASSERT_TRUE(parsed_trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
1764 
1765   bool found_args = false;
1766   for (const auto& packet : parsed_trace.packet()) {
1767     if (!packet.has_track_event())
1768       continue;
1769     const auto& track_event = packet.track_event();
1770     if (track_event.type() !=
1771         perfetto::protos::gen::TrackEvent::TYPE_SLICE_BEGIN) {
1772       continue;
1773     }
1774 
1775     EXPECT_THAT(track_event.flow_ids(), testing::ElementsAre(1, 2, 3));
1776     found_args = true;
1777   }
1778   EXPECT_TRUE(found_args);
1779 }
1780 
TEST_P(PerfettoApiTest,InlineTrackEventTypedArgs_NestedSingle)1781 TEST_P(PerfettoApiTest, InlineTrackEventTypedArgs_NestedSingle) {
1782   struct LogMessage {
1783     void WriteIntoTrace(
1784         perfetto::TracedProto<perfetto::protos::pbzero::LogMessage> context)
1785         const {
1786       context->set_source_location_iid(1);
1787       context->set_body_iid(2);
1788     }
1789   };
1790 
1791   // Create a new trace session.
1792   auto* tracing_session = NewTraceWithCategories({"foo"});
1793   tracing_session->get()->StartBlocking();
1794 
1795   TRACE_EVENT_BEGIN("foo", "EventWithTypedArg",
1796                     perfetto::protos::pbzero::TrackEvent::kLogMessage,
1797                     LogMessage());
1798   TRACE_EVENT_END("foo");
1799 
1800   tracing_session->get()->StopBlocking();
1801   std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
1802   std::string trace(raw_trace.data(), raw_trace.size());
1803 
1804   perfetto::protos::gen::Trace parsed_trace;
1805   ASSERT_TRUE(parsed_trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
1806 
1807   bool found_args = false;
1808   for (const auto& packet : parsed_trace.packet()) {
1809     if (!packet.has_track_event())
1810       continue;
1811     const auto& track_event = packet.track_event();
1812     if (track_event.type() !=
1813         perfetto::protos::gen::TrackEvent::TYPE_SLICE_BEGIN) {
1814       continue;
1815     }
1816 
1817     EXPECT_TRUE(track_event.has_log_message());
1818     const auto& log = track_event.log_message();
1819     EXPECT_EQ(1u, log.source_location_iid());
1820     EXPECT_EQ(2u, log.body_iid());
1821     found_args = true;
1822   }
1823   EXPECT_TRUE(found_args);
1824 }
1825 
1826 struct InternedLogMessageBody
1827     : public perfetto::TrackEventInternedDataIndex<
1828           InternedLogMessageBody,
1829           perfetto::protos::pbzero::InternedData::kLogMessageBodyFieldNumber,
1830           std::string> {
Add__anone89577de0111::InternedLogMessageBody1831   static void Add(perfetto::protos::pbzero::InternedData* interned_data,
1832                   size_t iid,
1833                   const std::string& value) {
1834     auto l = interned_data->add_log_message_body();
1835     l->set_iid(iid);
1836     l->set_body(value.data(), value.size());
1837     commit_count++;
1838   }
1839 
1840   static int commit_count;
1841 };
1842 
1843 int InternedLogMessageBody::commit_count = 0;
1844 
TEST_P(PerfettoApiTest,TrackEventTypedArgsWithInterning)1845 TEST_P(PerfettoApiTest, TrackEventTypedArgsWithInterning) {
1846   // Create a new trace session.
1847   auto* tracing_session = NewTraceWithCategories({"foo"});
1848   tracing_session->get()->StartBlocking();
1849 
1850   std::stringstream large_message;
1851   for (size_t i = 0; i < 512; i++)
1852     large_message << i << ". Something wicked this way comes. ";
1853 
1854   size_t body_iid;
1855   InternedLogMessageBody::commit_count = 0;
1856   TRACE_EVENT_BEGIN("foo", "EventWithState", [&](perfetto::EventContext ctx) {
1857     EXPECT_EQ(0, InternedLogMessageBody::commit_count);
1858     body_iid = InternedLogMessageBody::Get(&ctx, "Alas, poor Yorick!");
1859     auto log = ctx.event()->set_log_message();
1860     log->set_body_iid(body_iid);
1861     EXPECT_EQ(1, InternedLogMessageBody::commit_count);
1862 
1863     auto body_iid2 = InternedLogMessageBody::Get(&ctx, "Alas, poor Yorick!");
1864     EXPECT_EQ(body_iid, body_iid2);
1865     EXPECT_EQ(1, InternedLogMessageBody::commit_count);
1866   });
1867   TRACE_EVENT_END("foo");
1868 
1869   TRACE_EVENT_BEGIN("foo", "EventWithState", [&](perfetto::EventContext ctx) {
1870     // Check that very large amounts of interned data works.
1871     auto log = ctx.event()->set_log_message();
1872     log->set_body_iid(InternedLogMessageBody::Get(&ctx, large_message.str()));
1873     EXPECT_EQ(2, InternedLogMessageBody::commit_count);
1874   });
1875   TRACE_EVENT_END("foo");
1876 
1877   // Make sure interned data persists across trace points.
1878   TRACE_EVENT_BEGIN("foo", "EventWithState", [&](perfetto::EventContext ctx) {
1879     auto body_iid2 = InternedLogMessageBody::Get(&ctx, "Alas, poor Yorick!");
1880     EXPECT_EQ(body_iid, body_iid2);
1881 
1882     auto body_iid3 = InternedLogMessageBody::Get(&ctx, "I knew him, Horatio");
1883     EXPECT_NE(body_iid, body_iid3);
1884     auto log = ctx.event()->set_log_message();
1885     log->set_body_iid(body_iid3);
1886     EXPECT_EQ(3, InternedLogMessageBody::commit_count);
1887   });
1888   TRACE_EVENT_END("foo");
1889 
1890   tracing_session->get()->StopBlocking();
1891   auto log_messages = ReadLogMessagesFromTrace(tracing_session->get());
1892   EXPECT_THAT(log_messages,
1893               ElementsAre("Alas, poor Yorick!", large_message.str(),
1894                           "I knew him, Horatio"));
1895 }
1896 
1897 struct InternedLogMessageBodySmall
1898     : public perfetto::TrackEventInternedDataIndex<
1899           InternedLogMessageBodySmall,
1900           perfetto::protos::pbzero::InternedData::kLogMessageBodyFieldNumber,
1901           const char*,
1902           perfetto::SmallInternedDataTraits> {
Add__anone89577de0111::InternedLogMessageBodySmall1903   static void Add(perfetto::protos::pbzero::InternedData* interned_data,
1904                   size_t iid,
1905                   const char* value) {
1906     auto l = interned_data->add_log_message_body();
1907     l->set_iid(iid);
1908     l->set_body(value);
1909   }
1910 };
1911 
TEST_P(PerfettoApiTest,TrackEventTypedArgsWithInterningByValue)1912 TEST_P(PerfettoApiTest, TrackEventTypedArgsWithInterningByValue) {
1913   // Create a new trace session.
1914   auto* tracing_session = NewTraceWithCategories({"foo"});
1915   tracing_session->get()->StartBlocking();
1916 
1917   size_t body_iid;
1918   TRACE_EVENT_BEGIN("foo", "EventWithState", [&](perfetto::EventContext ctx) {
1919     body_iid = InternedLogMessageBodySmall::Get(&ctx, "This above all:");
1920     auto log = ctx.event()->set_log_message();
1921     log->set_body_iid(body_iid);
1922 
1923     auto body_iid2 = InternedLogMessageBodySmall::Get(&ctx, "This above all:");
1924     EXPECT_EQ(body_iid, body_iid2);
1925 
1926     auto body_iid3 =
1927         InternedLogMessageBodySmall::Get(&ctx, "to thine own self be true");
1928     EXPECT_NE(body_iid, body_iid3);
1929   });
1930   TRACE_EVENT_END("foo");
1931 
1932   tracing_session->get()->StopBlocking();
1933   auto log_messages = ReadLogMessagesFromTrace(tracing_session->get());
1934   EXPECT_THAT(log_messages, ElementsAre("This above all:"));
1935 }
1936 
1937 struct InternedLogMessageBodyHashed
1938     : public perfetto::TrackEventInternedDataIndex<
1939           InternedLogMessageBodyHashed,
1940           perfetto::protos::pbzero::InternedData::kLogMessageBodyFieldNumber,
1941           std::string,
1942           perfetto::HashedInternedDataTraits> {
Add__anone89577de0111::InternedLogMessageBodyHashed1943   static void Add(perfetto::protos::pbzero::InternedData* interned_data,
1944                   size_t iid,
1945                   const std::string& value) {
1946     auto l = interned_data->add_log_message_body();
1947     l->set_iid(iid);
1948     l->set_body(value.data(), value.size());
1949   }
1950 };
1951 
TEST_P(PerfettoApiTest,TrackEventTypedArgsWithInterningByHashing)1952 TEST_P(PerfettoApiTest, TrackEventTypedArgsWithInterningByHashing) {
1953   // Create a new trace session.
1954   auto* tracing_session = NewTraceWithCategories({"foo"});
1955   tracing_session->get()->StartBlocking();
1956 
1957   size_t body_iid;
1958   TRACE_EVENT_BEGIN("foo", "EventWithState", [&](perfetto::EventContext ctx) {
1959     // Test using a dynamically created interned value.
1960     body_iid = InternedLogMessageBodyHashed::Get(
1961         &ctx, std::string("Though this ") + "be madness,");
1962     auto log = ctx.event()->set_log_message();
1963     log->set_body_iid(body_iid);
1964 
1965     auto body_iid2 =
1966         InternedLogMessageBodyHashed::Get(&ctx, "Though this be madness,");
1967     EXPECT_EQ(body_iid, body_iid2);
1968 
1969     auto body_iid3 =
1970         InternedLogMessageBodyHashed::Get(&ctx, "yet there is method in’t");
1971     EXPECT_NE(body_iid, body_iid3);
1972   });
1973   TRACE_EVENT_END("foo");
1974 
1975   tracing_session->get()->StopBlocking();
1976   auto log_messages = ReadLogMessagesFromTrace(tracing_session->get());
1977   EXPECT_THAT(log_messages, ElementsAre("Though this be madness,"));
1978 }
1979 
1980 struct InternedSourceLocation
1981     : public perfetto::TrackEventInternedDataIndex<
1982           InternedSourceLocation,
1983           perfetto::protos::pbzero::InternedData::kSourceLocationsFieldNumber,
1984           SourceLocation> {
Add__anone89577de0111::InternedSourceLocation1985   static void Add(perfetto::protos::pbzero::InternedData* interned_data,
1986                   size_t iid,
1987                   const SourceLocation& value) {
1988     auto l = interned_data->add_source_locations();
1989     auto file_name = std::get<0>(value);
1990     auto function_name = std::get<1>(value);
1991     auto line_number = std::get<2>(value);
1992     l->set_iid(iid);
1993     l->set_file_name(file_name);
1994     l->set_function_name(function_name);
1995     l->set_line_number(line_number);
1996   }
1997 };
1998 
TEST_P(PerfettoApiTest,TrackEventTypedArgsWithInterningComplexValue)1999 TEST_P(PerfettoApiTest, TrackEventTypedArgsWithInterningComplexValue) {
2000   // Create a new trace session.
2001   auto* tracing_session = NewTraceWithCategories({"foo"});
2002   tracing_session->get()->StartBlocking();
2003 
2004   TRACE_EVENT_BEGIN("foo", "EventWithState", [&](perfetto::EventContext ctx) {
2005     const SourceLocation location{"file.cc", "SomeFunction", 123};
2006     auto location_iid = InternedSourceLocation::Get(&ctx, location);
2007     auto body_iid = InternedLogMessageBody::Get(&ctx, "To be, or not to be");
2008     auto log = ctx.event()->set_log_message();
2009     log->set_source_location_iid(location_iid);
2010     log->set_body_iid(body_iid);
2011 
2012     auto location_iid2 = InternedSourceLocation::Get(&ctx, location);
2013     EXPECT_EQ(location_iid, location_iid2);
2014 
2015     const SourceLocation location2{"file.cc", "SomeFunction", 456};
2016     auto location_iid3 = InternedSourceLocation::Get(&ctx, location2);
2017     EXPECT_NE(location_iid, location_iid3);
2018   });
2019   TRACE_EVENT_END("foo");
2020 
2021   tracing_session->get()->StopBlocking();
2022   auto log_messages = ReadLogMessagesFromTrace(tracing_session->get());
2023   EXPECT_THAT(log_messages,
2024               ElementsAre("SomeFunction(file.cc:123): To be, or not to be"));
2025 }
2026 
TEST_P(PerfettoApiTest,TrackEventScoped)2027 TEST_P(PerfettoApiTest, TrackEventScoped) {
2028   // Create a new trace session.
2029   auto* tracing_session = NewTraceWithCategories({"test"});
2030   tracing_session->get()->StartBlocking();
2031 
2032   {
2033     uint64_t arg = 123;
2034     TRACE_EVENT("test", "TestEventWithArgs", [&](perfetto::EventContext ctx) {
2035       ctx.event()->set_log_message()->set_body_iid(arg);
2036     });
2037   }
2038 
2039   // Ensure a single line if statement counts as a valid scope for the macro.
2040   if (true)
2041     TRACE_EVENT("test", "SingleLineTestEvent");
2042 
2043   {
2044     // Make sure you can have multiple scoped events in the same scope.
2045     TRACE_EVENT("test", "TestEvent");
2046     TRACE_EVENT("test", "AnotherEvent");
2047     TRACE_EVENT("foo", "DisabledEvent");
2048   }
2049   perfetto::TrackEvent::Flush();
2050 
2051   tracing_session->get()->StopBlocking();
2052   auto slices = ReadSlicesFromTrace(tracing_session->get());
2053   EXPECT_THAT(
2054       slices,
2055       ElementsAre("B:test.TestEventWithArgs", "E", "B:test.SingleLineTestEvent",
2056                   "E", "B:test.TestEvent", "B:test.AnotherEvent", "E", "E"));
2057 }
2058 
2059 // A class similar to what Protozero generates for extended message.
2060 class TestTrackEvent : public perfetto::protos::pbzero::TrackEvent {
2061  public:
2062   static const int field_number = 9901;
2063 
set_extension_value(int value)2064   void set_extension_value(int value) {
2065     // 9900-10000 is the range of extension field numbers reserved for testing.
2066     AppendTinyVarInt(field_number, value);
2067   }
2068 };
2069 
TEST_P(PerfettoApiTest,ExtensionClass)2070 TEST_P(PerfettoApiTest, ExtensionClass) {
2071   auto* tracing_session = NewTraceWithCategories({"test"});
2072   tracing_session->get()->StartBlocking();
2073 
2074   {
2075     TRACE_EVENT("test", "TestEventWithExtensionArgs",
2076                 [&](perfetto::EventContext ctx) {
2077                   ctx.event<perfetto::protos::pbzero::TestExtension>()
2078                       ->add_int_extension_for_testing(42);
2079                 });
2080   }
2081 
2082   perfetto::TrackEvent::Flush();
2083   tracing_session->get()->StopBlocking();
2084 
2085   std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
2086   EXPECT_GE(raw_trace.size(), 0u);
2087 
2088   bool found_extension = false;
2089   perfetto::protos::pbzero::Trace_Decoder trace(
2090       reinterpret_cast<uint8_t*>(raw_trace.data()), raw_trace.size());
2091 
2092   for (auto it = trace.packet(); it; ++it) {
2093     perfetto::protos::pbzero::TracePacket_Decoder packet(it->data(),
2094                                                          it->size());
2095 
2096     if (!packet.has_track_event())
2097       continue;
2098 
2099     auto track_event = packet.track_event();
2100     protozero::ProtoDecoder decoder(track_event.data, track_event.size);
2101 
2102     for (protozero::Field f = decoder.ReadField(); f.valid();
2103          f = decoder.ReadField()) {
2104       if (f.id() == perfetto::protos::pbzero::TestExtension::
2105                         FieldMetadata_IntExtensionForTesting::kFieldId) {
2106         found_extension = true;
2107       }
2108     }
2109   }
2110 
2111   EXPECT_TRUE(found_extension);
2112 }
2113 
TEST_P(PerfettoApiTest,InlineTypedExtensionField)2114 TEST_P(PerfettoApiTest, InlineTypedExtensionField) {
2115   auto* tracing_session = NewTraceWithCategories({"test"});
2116   tracing_session->get()->StartBlocking();
2117 
2118   {
2119     TRACE_EVENT(
2120         "test", "TestEventWithExtensionArgs",
2121         perfetto::protos::pbzero::TestExtension::kIntExtensionForTesting,
2122         std::vector<int>{42});
2123   }
2124 
2125   perfetto::TrackEvent::Flush();
2126   tracing_session->get()->StopBlocking();
2127 
2128   std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
2129   EXPECT_GE(raw_trace.size(), 0u);
2130 
2131   bool found_extension = false;
2132   perfetto::protos::pbzero::Trace_Decoder trace(
2133       reinterpret_cast<uint8_t*>(raw_trace.data()), raw_trace.size());
2134 
2135   for (auto it = trace.packet(); it; ++it) {
2136     perfetto::protos::pbzero::TracePacket_Decoder packet(it->data(),
2137                                                          it->size());
2138 
2139     if (!packet.has_track_event())
2140       continue;
2141 
2142     auto track_event = packet.track_event();
2143     protozero::ProtoDecoder decoder(track_event.data, track_event.size);
2144 
2145     for (protozero::Field f = decoder.ReadField(); f.valid();
2146          f = decoder.ReadField()) {
2147       if (f.id() == perfetto::protos::pbzero::TestExtension::
2148                         FieldMetadata_IntExtensionForTesting::kFieldId) {
2149         found_extension = true;
2150       }
2151     }
2152   }
2153 
2154   EXPECT_TRUE(found_extension);
2155 }
2156 
TEST_P(PerfettoApiTest,TrackEventInstant)2157 TEST_P(PerfettoApiTest, TrackEventInstant) {
2158   // Create a new trace session.
2159   auto* tracing_session = NewTraceWithCategories({"test"});
2160   tracing_session->get()->StartBlocking();
2161 
2162   TRACE_EVENT_INSTANT("test", "TestEvent");
2163   TRACE_EVENT_INSTANT("test", "AnotherEvent");
2164   perfetto::TrackEvent::Flush();
2165 
2166   tracing_session->get()->StopBlocking();
2167   auto slices = ReadSlicesFromTrace(tracing_session->get());
2168   EXPECT_THAT(slices, ElementsAre("I:test.TestEvent", "I:test.AnotherEvent"));
2169 }
2170 
TEST_P(PerfettoApiTest,TrackEventDefaultGlobalTrack)2171 TEST_P(PerfettoApiTest, TrackEventDefaultGlobalTrack) {
2172   // Create a new trace session.
2173   auto* tracing_session = NewTraceWithCategories({"test"});
2174   tracing_session->get()->StartBlocking();
2175 
2176   TRACE_EVENT_INSTANT("test", "ThreadEvent");
2177   TRACE_EVENT_INSTANT("test", "GlobalEvent", perfetto::Track::Global(0u));
2178   perfetto::TrackEvent::Flush();
2179 
2180   tracing_session->get()->StopBlocking();
2181   auto slices = ReadSlicesFromTrace(tracing_session->get());
2182   EXPECT_THAT(slices,
2183               ElementsAre("I:test.ThreadEvent", "[track=0]I:test.GlobalEvent"));
2184 }
2185 
TEST_P(PerfettoApiTest,TrackEventTrackFromPointer)2186 TEST_P(PerfettoApiTest, TrackEventTrackFromPointer) {
2187   // Create a new trace session.
2188   auto* tracing_session = NewTraceWithCategories({"test"});
2189   tracing_session->get()->StartBlocking();
2190 
2191   perfetto::Track parent_track(1);
2192   int* ptr = reinterpret_cast<int*>(2);
2193   TRACE_EVENT_INSTANT("test", "Event",
2194                       perfetto::Track::FromPointer(ptr, parent_track));
2195   perfetto::TrackEvent::Flush();
2196 
2197   perfetto::Track track(reinterpret_cast<uintptr_t>(ptr), parent_track);
2198 
2199   tracing_session->get()->StopBlocking();
2200   auto slices = ReadSlicesFromTrace(tracing_session->get());
2201   EXPECT_THAT(slices, ElementsAre("[track=" + std::to_string(track.uuid) +
2202                                   "]I:test.Event"));
2203 }
2204 
TEST_P(PerfettoApiTest,TrackEventDebugAnnotations)2205 TEST_P(PerfettoApiTest, TrackEventDebugAnnotations) {
2206   // Create a new trace session.
2207   auto* tracing_session = NewTraceWithCategories({"test"});
2208   tracing_session->get()->StartBlocking();
2209 
2210   enum MyEnum : uint32_t { ENUM_FOO, ENUM_BAR };
2211   enum MySignedEnum : int32_t { SIGNED_ENUM_FOO = -1, SIGNED_ENUM_BAR };
2212   enum class MyClassEnum { VALUE };
2213 
2214   TRACE_EVENT_BEGIN("test", "E", "bool_arg", false);
2215   TRACE_EVENT_BEGIN("test", "E", "int_arg", -123);
2216   TRACE_EVENT_BEGIN("test", "E", "uint_arg", 456u);
2217   TRACE_EVENT_BEGIN("test", "E", "float_arg", 3.14159262f);
2218   TRACE_EVENT_BEGIN("test", "E", "double_arg", 6.22);
2219   TRACE_EVENT_BEGIN("test", "E", "str_arg", "hello", "str_arg2",
2220                     std::string("tracing"));
2221   TRACE_EVENT_BEGIN("test", "E", "ptr_arg",
2222                     reinterpret_cast<void*>(static_cast<intptr_t>(0xbaadf00d)));
2223   TRACE_EVENT_BEGIN("test", "E", "size_t_arg", size_t{42});
2224   TRACE_EVENT_BEGIN("test", "E", "ptrdiff_t_arg", ptrdiff_t{-7});
2225   TRACE_EVENT_BEGIN("test", "E", "enum_arg", ENUM_BAR);
2226   TRACE_EVENT_BEGIN("test", "E", "signed_enum_arg", SIGNED_ENUM_FOO);
2227   TRACE_EVENT_BEGIN("test", "E", "class_enum_arg", MyClassEnum::VALUE);
2228   TRACE_EVENT_BEGIN("test", "E", "traced_value",
2229                     [&](perfetto::TracedValue context) {
2230                       std::move(context).WriteInt64(42);
2231                     });
2232   perfetto::TrackEvent::Flush();
2233 
2234   tracing_session->get()->StopBlocking();
2235   auto slices = ReadSlicesFromTrace(tracing_session->get());
2236   EXPECT_THAT(
2237       slices,
2238       ElementsAre(
2239           "B:test.E(bool_arg=(bool)0)", "B:test.E(int_arg=(int)-123)",
2240           "B:test.E(uint_arg=(uint)456)", "B:test.E(float_arg=(double)3.14159)",
2241           "B:test.E(double_arg=(double)6.22)",
2242           "B:test.E(str_arg=(string)hello,str_arg2=(string)tracing)",
2243           "B:test.E(ptr_arg=(pointer)baadf00d)",
2244           "B:test.E(size_t_arg=(uint)42)", "B:test.E(ptrdiff_t_arg=(int)-7)",
2245           "B:test.E(enum_arg=(uint)1)", "B:test.E(signed_enum_arg=(int)-1)",
2246           "B:test.E(class_enum_arg=(int)0)", "B:test.E(traced_value=(int)42)"));
2247 }
2248 
TEST_P(PerfettoApiTest,TrackEventCustomDebugAnnotations)2249 TEST_P(PerfettoApiTest, TrackEventCustomDebugAnnotations) {
2250   // Create a new trace session.
2251   auto* tracing_session = NewTraceWithCategories({"test"});
2252   tracing_session->get()->StartBlocking();
2253 
2254   std::unique_ptr<MyDebugAnnotation> owned_annotation(new MyDebugAnnotation());
2255 
2256   TRACE_EVENT_BEGIN("test", "E", "custom_arg", MyDebugAnnotation());
2257   TRACE_EVENT_BEGIN("test", "E", "normal_arg", "x", "custom_arg",
2258                     std::move(owned_annotation));
2259   perfetto::TrackEvent::Flush();
2260 
2261   tracing_session->get()->StopBlocking();
2262   auto slices = ReadSlicesFromTrace(tracing_session->get());
2263   EXPECT_THAT(
2264       slices,
2265       ElementsAre(
2266           R"(B:test.E(custom_arg=(json){"key": 123}))",
2267           R"(B:test.E(normal_arg=(string)x,custom_arg=(json){"key": 123}))"));
2268 }
2269 
TEST_P(PerfettoApiTest,TrackEventCustomRawDebugAnnotations)2270 TEST_P(PerfettoApiTest, TrackEventCustomRawDebugAnnotations) {
2271   // Note: this class is also testing a non-moveable and non-copiable argument.
2272   class MyRawDebugAnnotation : public perfetto::DebugAnnotation {
2273    public:
2274     MyRawDebugAnnotation() { msg_->set_string_value("nested_value"); }
2275     ~MyRawDebugAnnotation() = default;
2276 
2277     // |msg_| already deletes these implicitly, but let's be explicit for safety
2278     // against future changes.
2279     MyRawDebugAnnotation(const MyRawDebugAnnotation&) = delete;
2280     MyRawDebugAnnotation(MyRawDebugAnnotation&&) = delete;
2281 
2282     void Add(perfetto::protos::pbzero::DebugAnnotation* annotation) const {
2283       auto ranges = msg_.GetRanges();
2284       annotation->AppendScatteredBytes(
2285           perfetto::protos::pbzero::DebugAnnotation::kNestedValueFieldNumber,
2286           &ranges[0], ranges.size());
2287     }
2288 
2289    private:
2290     mutable protozero::HeapBuffered<
2291         perfetto::protos::pbzero::DebugAnnotation::NestedValue>
2292         msg_;
2293   };
2294 
2295   // Create a new trace session.
2296   auto* tracing_session = NewTraceWithCategories({"test"});
2297   tracing_session->get()->StartBlocking();
2298 
2299   TRACE_EVENT_BEGIN("test", "E", "raw_arg", MyRawDebugAnnotation());
2300   TRACE_EVENT_BEGIN("test", "E", "plain_arg", 42, "raw_arg",
2301                     MyRawDebugAnnotation());
2302   perfetto::TrackEvent::Flush();
2303 
2304   tracing_session->get()->StopBlocking();
2305   auto slices = ReadSlicesFromTrace(tracing_session->get());
2306   EXPECT_THAT(
2307       slices,
2308       ElementsAre("B:test.E(raw_arg=(nested)nested_value)",
2309                   "B:test.E(plain_arg=(int)42,raw_arg=(nested)nested_value)"));
2310 }
2311 
TEST_P(PerfettoApiTest,ManyDebugAnnotations)2312 TEST_P(PerfettoApiTest, ManyDebugAnnotations) {
2313   // Create a new trace session.
2314   auto* tracing_session = NewTraceWithCategories({"test"});
2315   tracing_session->get()->StartBlocking();
2316 
2317   TRACE_EVENT_BEGIN("test", "E", "arg1", 1, "arg2", 2, "arg3", 3);
2318   perfetto::TrackEvent::Flush();
2319 
2320   tracing_session->get()->StopBlocking();
2321   auto slices = ReadSlicesFromTrace(tracing_session->get());
2322   EXPECT_THAT(slices,
2323               ElementsAre("B:test.E(arg1=(int)1,arg2=(int)2,arg3=(int)3)"));
2324 }
2325 
TEST_P(PerfettoApiTest,DebugAnnotationAndLambda)2326 TEST_P(PerfettoApiTest, DebugAnnotationAndLambda) {
2327   // Create a new trace session.
2328   auto* tracing_session = NewTraceWithCategories({"test"});
2329   tracing_session->get()->StartBlocking();
2330 
2331   enum MyEnum : uint32_t { ENUM_FOO, ENUM_BAR };
2332   enum MySignedEnum : int32_t { SIGNED_ENUM_FOO = -1, SIGNED_ENUM_BAR };
2333   enum class MyClassEnum { VALUE };
2334 
2335   TRACE_EVENT_BEGIN(
2336       "test", "E", "key", "value", [](perfetto::EventContext ctx) {
2337         ctx.event()->set_log_message()->set_source_location_iid(42);
2338       });
2339   perfetto::TrackEvent::Flush();
2340 
2341   tracing_session->get()->StopBlocking();
2342   std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
2343   std::string trace(raw_trace.data(), raw_trace.size());
2344 
2345   perfetto::protos::gen::Trace parsed_trace;
2346   ASSERT_TRUE(parsed_trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
2347 
2348   bool found_args = false;
2349   for (const auto& packet : parsed_trace.packet()) {
2350     if (!packet.has_track_event())
2351       continue;
2352     const auto& track_event = packet.track_event();
2353     if (track_event.type() !=
2354         perfetto::protos::gen::TrackEvent::TYPE_SLICE_BEGIN)
2355       continue;
2356 
2357     EXPECT_TRUE(track_event.has_log_message());
2358     const auto& log = track_event.log_message();
2359     EXPECT_EQ(42u, log.source_location_iid());
2360 
2361     const auto& dbg = track_event.debug_annotations()[0];
2362     EXPECT_EQ("value", dbg.string_value());
2363 
2364     found_args = true;
2365   }
2366   EXPECT_TRUE(found_args);
2367 }
2368 
TEST_P(PerfettoApiTest,TrackEventComputedName)2369 TEST_P(PerfettoApiTest, TrackEventComputedName) {
2370   // Setup the trace config.
2371   perfetto::TraceConfig cfg;
2372   cfg.set_duration_ms(500);
2373   cfg.add_buffers()->set_size_kb(1024);
2374   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
2375   ds_cfg->set_name("track_event");
2376 
2377   // Create a new trace session.
2378   auto* tracing_session = NewTrace(cfg);
2379   tracing_session->get()->StartBlocking();
2380 
2381   // New macros require perfetto::StaticString{} annotation.
2382   for (int i = 0; i < 3; i++)
2383     TRACE_EVENT_BEGIN("test", perfetto::StaticString{i % 2 ? "Odd" : "Even"});
2384 
2385   // Legacy macros assume all arguments are static strings.
2386   for (int i = 0; i < 3; i++)
2387     TRACE_EVENT_BEGIN0("test", i % 2 ? "Odd" : "Even");
2388 
2389   perfetto::TrackEvent::Flush();
2390 
2391   tracing_session->get()->StopBlocking();
2392   auto slices = ReadSlicesFromTrace(tracing_session->get());
2393   EXPECT_THAT(slices, ElementsAre("B:test.Even", "B:test.Odd", "B:test.Even",
2394                                   "B:test.Even", "B:test.Odd", "B:test.Even"));
2395 }
2396 
TEST_P(PerfettoApiTest,TrackEventArgumentsNotEvaluatedWhenDisabled)2397 TEST_P(PerfettoApiTest, TrackEventArgumentsNotEvaluatedWhenDisabled) {
2398   // Create a new trace session.
2399   auto* tracing_session = NewTraceWithCategories({"foo"});
2400   tracing_session->get()->StartBlocking();
2401 
2402   bool called = false;
2403   auto ArgumentFunction = [&] {
2404     called = true;
2405     return 123;
2406   };
2407 
2408   TRACE_EVENT_BEGIN("test", "DisabledEvent", "arg", ArgumentFunction());
2409   { TRACE_EVENT("test", "DisabledScopedEvent", "arg", ArgumentFunction()); }
2410   perfetto::TrackEvent::Flush();
2411 
2412   tracing_session->get()->StopBlocking();
2413   EXPECT_FALSE(called);
2414 
2415   ArgumentFunction();
2416   EXPECT_TRUE(called);
2417 }
2418 
TEST_P(PerfettoApiTest,TrackEventConfig)2419 TEST_P(PerfettoApiTest, TrackEventConfig) {
2420   auto check_config = [&](perfetto::protos::gen::TrackEventConfig te_cfg) {
2421     perfetto::TraceConfig cfg;
2422     cfg.set_duration_ms(500);
2423     cfg.add_buffers()->set_size_kb(1024);
2424     auto* ds_cfg = cfg.add_data_sources()->mutable_config();
2425     ds_cfg->set_name("track_event");
2426     ds_cfg->set_track_event_config_raw(te_cfg.SerializeAsString());
2427 
2428     auto* tracing_session = NewTrace(cfg);
2429     tracing_session->get()->StartBlocking();
2430 
2431     TRACE_EVENT_BEGIN("foo", "FooEvent");
2432     TRACE_EVENT_BEGIN("bar", "BarEvent");
2433     TRACE_EVENT_BEGIN("foo,bar", "MultiFooBar");
2434     TRACE_EVENT_BEGIN("baz,bar,quux", "MultiBar");
2435     TRACE_EVENT_BEGIN("red,green,blue,foo", "MultiFoo");
2436     TRACE_EVENT_BEGIN("red,green,blue,yellow", "MultiNone");
2437     TRACE_EVENT_BEGIN("cat", "SlowEvent");
2438     TRACE_EVENT_BEGIN("cat.verbose", "DebugEvent");
2439     TRACE_EVENT_BEGIN("test", "TagEvent");
2440     TRACE_EVENT_BEGIN(TRACE_DISABLED_BY_DEFAULT("cat"), "SlowDisabledEvent");
2441     TRACE_EVENT_BEGIN("dynamic,foo", "DynamicGroupFooEvent");
2442     perfetto::DynamicCategory dyn{"dynamic,bar"};
2443     TRACE_EVENT_BEGIN(dyn, "DynamicGroupBarEvent");
2444 
2445     perfetto::TrackEvent::Flush();
2446     tracing_session->get()->StopBlocking();
2447     auto slices = ReadSlicesFromTrace(tracing_session->get());
2448     tracing_session->session.reset();
2449     return slices;
2450   };
2451 
2452   // Empty config should enable all categories except slow ones.
2453   {
2454     perfetto::protos::gen::TrackEventConfig te_cfg;
2455     auto slices = check_config(te_cfg);
2456     EXPECT_THAT(
2457         slices,
2458         ElementsAre("B:foo.FooEvent", "B:bar.BarEvent", "B:foo,bar.MultiFooBar",
2459                     "B:baz,bar,quux.MultiBar", "B:red,green,blue,foo.MultiFoo",
2460                     "B:red,green,blue,yellow.MultiNone", "B:test.TagEvent",
2461                     "B:$dynamic,$foo.DynamicGroupFooEvent",
2462                     "B:$dynamic,$bar.DynamicGroupBarEvent"));
2463   }
2464 
2465   // Enable exactly one category.
2466   {
2467     perfetto::protos::gen::TrackEventConfig te_cfg;
2468     te_cfg.add_disabled_categories("*");
2469     te_cfg.add_enabled_categories("foo");
2470     auto slices = check_config(te_cfg);
2471     EXPECT_THAT(slices, ElementsAre("B:foo.FooEvent", "B:foo,bar.MultiFooBar",
2472                                     "B:red,green,blue,foo.MultiFoo",
2473                                     "B:$dynamic,$foo.DynamicGroupFooEvent"));
2474   }
2475 
2476   // Enable exactly one dynamic category.
2477   {
2478     perfetto::protos::gen::TrackEventConfig te_cfg;
2479     te_cfg.add_disabled_categories("*");
2480     te_cfg.add_enabled_categories("dynamic");
2481     auto slices = check_config(te_cfg);
2482     EXPECT_THAT(slices, ElementsAre("B:$dynamic,$foo.DynamicGroupFooEvent",
2483                                     "B:$dynamic,$bar.DynamicGroupBarEvent"));
2484   }
2485 
2486   // Enable two categories.
2487   {
2488     perfetto::protos::gen::TrackEventConfig te_cfg;
2489     te_cfg.add_disabled_categories("*");
2490     te_cfg.add_enabled_categories("foo");
2491     te_cfg.add_enabled_categories("baz");
2492     te_cfg.add_enabled_categories("bar");
2493     auto slices = check_config(te_cfg);
2494     EXPECT_THAT(
2495         slices,
2496         ElementsAre("B:foo.FooEvent", "B:bar.BarEvent", "B:foo,bar.MultiFooBar",
2497                     "B:baz,bar,quux.MultiBar", "B:red,green,blue,foo.MultiFoo",
2498                     "B:$dynamic,$foo.DynamicGroupFooEvent",
2499                     "B:$dynamic,$bar.DynamicGroupBarEvent"));
2500   }
2501 
2502   // Enabling all categories with a pattern doesn't enable slow ones.
2503   {
2504     perfetto::protos::gen::TrackEventConfig te_cfg;
2505     te_cfg.add_enabled_categories("*");
2506     auto slices = check_config(te_cfg);
2507     EXPECT_THAT(
2508         slices,
2509         ElementsAre("B:foo.FooEvent", "B:bar.BarEvent", "B:foo,bar.MultiFooBar",
2510                     "B:baz,bar,quux.MultiBar", "B:red,green,blue,foo.MultiFoo",
2511                     "B:red,green,blue,yellow.MultiNone", "B:test.TagEvent",
2512                     "B:$dynamic,$foo.DynamicGroupFooEvent",
2513                     "B:$dynamic,$bar.DynamicGroupBarEvent"));
2514   }
2515 
2516   // Enable with a pattern.
2517   {
2518     perfetto::protos::gen::TrackEventConfig te_cfg;
2519     te_cfg.add_disabled_categories("*");
2520     te_cfg.add_enabled_categories("fo*");
2521     auto slices = check_config(te_cfg);
2522     EXPECT_THAT(slices, ElementsAre("B:foo.FooEvent", "B:foo,bar.MultiFooBar",
2523                                     "B:red,green,blue,foo.MultiFoo",
2524                                     "B:$dynamic,$foo.DynamicGroupFooEvent"));
2525   }
2526 
2527   // Enable with a tag.
2528   {
2529     perfetto::protos::gen::TrackEventConfig te_cfg;
2530     te_cfg.add_disabled_categories("*");
2531     te_cfg.add_enabled_tags("tag");
2532     auto slices = check_config(te_cfg);
2533     EXPECT_THAT(slices, ElementsAre("B:test.TagEvent"));
2534   }
2535 
2536   // Enable just slow categories.
2537   {
2538     perfetto::protos::gen::TrackEventConfig te_cfg;
2539     te_cfg.add_disabled_categories("*");
2540     te_cfg.add_enabled_tags("slow");
2541     auto slices = check_config(te_cfg);
2542     EXPECT_THAT(slices,
2543                 ElementsAre("B:cat.SlowEvent",
2544                             "B:disabled-by-default-cat.SlowDisabledEvent"));
2545   }
2546 
2547   // Enable everything including slow/debug categories.
2548   {
2549     perfetto::protos::gen::TrackEventConfig te_cfg;
2550     te_cfg.add_enabled_categories("*");
2551     te_cfg.add_enabled_tags("slow");
2552     te_cfg.add_enabled_tags("debug");
2553     auto slices = check_config(te_cfg);
2554     EXPECT_THAT(
2555         slices,
2556         ElementsAre("B:foo.FooEvent", "B:bar.BarEvent", "B:foo,bar.MultiFooBar",
2557                     "B:baz,bar,quux.MultiBar", "B:red,green,blue,foo.MultiFoo",
2558                     "B:red,green,blue,yellow.MultiNone", "B:cat.SlowEvent",
2559                     "B:cat.verbose.DebugEvent", "B:test.TagEvent",
2560                     "B:disabled-by-default-cat.SlowDisabledEvent",
2561                     "B:$dynamic,$foo.DynamicGroupFooEvent",
2562                     "B:$dynamic,$bar.DynamicGroupBarEvent"));
2563   }
2564 }
2565 
TEST_P(PerfettoApiTest,OneDataSourceOneEvent)2566 TEST_P(PerfettoApiTest, OneDataSourceOneEvent) {
2567   auto* data_source = &data_sources_["my_data_source"];
2568 
2569   // Setup the trace config.
2570   perfetto::TraceConfig cfg;
2571   cfg.set_duration_ms(500);
2572   cfg.add_buffers()->set_size_kb(1024);
2573   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
2574   ds_cfg->set_name("my_data_source");
2575   ds_cfg->set_legacy_config("test config");
2576 
2577   // Create a new trace session.
2578   auto* tracing_session = NewTrace(cfg);
2579 
2580   MockDataSource::Trace([](MockDataSource::TraceContext) {
2581     FAIL() << "Should not be called because the trace was not started";
2582   });
2583   MockDataSource::CallIfEnabled([](uint32_t) {
2584     FAIL() << "Should not be called because the trace was not started";
2585   });
2586 
2587   tracing_session->get()->Start();
2588   data_source->on_setup.Wait();
2589   EXPECT_EQ(data_source->config.legacy_config(), "test config");
2590   data_source->on_start.Wait();
2591 
2592   // Emit one trace event.
2593   std::atomic<int> trace_lambda_calls{0};
2594   MockDataSource::Trace(
2595       [&trace_lambda_calls](MockDataSource::TraceContext ctx) {
2596         auto packet = ctx.NewTracePacket();
2597         packet->set_timestamp(42);
2598         packet->set_for_testing()->set_str("event 1");
2599         trace_lambda_calls++;
2600         packet->Finalize();
2601 
2602         // The SMB scraping logic will skip the last packet because it cannot
2603         // guarantee it's finalized. Create an empty packet so we get the
2604         // previous one and this empty one is ignored.
2605         packet = ctx.NewTracePacket();
2606       });
2607 
2608   uint32_t active_instances = 0;
2609   MockDataSource::CallIfEnabled([&active_instances](uint32_t instances) {
2610     active_instances = instances;
2611   });
2612   EXPECT_EQ(1u, active_instances);
2613 
2614   data_source->on_stop.Wait();
2615   tracing_session->on_stop.Wait();
2616   EXPECT_EQ(trace_lambda_calls, 1);
2617 
2618   MockDataSource::Trace([](MockDataSource::TraceContext) {
2619     FAIL() << "Should not be called because the trace is now stopped";
2620   });
2621   MockDataSource::CallIfEnabled([](uint32_t) {
2622     FAIL() << "Should not be called because the trace is now stopped";
2623   });
2624 
2625   std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
2626   ASSERT_GE(raw_trace.size(), 0u);
2627 
2628   perfetto::protos::gen::Trace trace;
2629   ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
2630   bool test_packet_found = false;
2631   for (const auto& packet : trace.packet()) {
2632     if (!packet.has_for_testing())
2633       continue;
2634     EXPECT_FALSE(test_packet_found);
2635     EXPECT_EQ(packet.timestamp(), 42U);
2636     EXPECT_EQ(packet.for_testing().str(), "event 1");
2637     test_packet_found = true;
2638   }
2639   EXPECT_TRUE(test_packet_found);
2640 }
2641 
TEST_P(PerfettoApiTest,ReentrantTracing)2642 TEST_P(PerfettoApiTest, ReentrantTracing) {
2643   auto* data_source = &data_sources_["my_data_source"];
2644 
2645   // Setup the trace config.
2646   perfetto::TraceConfig cfg;
2647   cfg.set_duration_ms(500);
2648   cfg.add_buffers()->set_size_kb(1024);
2649   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
2650   ds_cfg->set_name("my_data_source");
2651 
2652   // Create a new trace session.
2653   auto* tracing_session = NewTrace(cfg);
2654   tracing_session->get()->Start();
2655   data_source->on_start.Wait();
2656 
2657   // Check that only one level of trace lambda calls is allowed.
2658   std::atomic<int> trace_lambda_calls{0};
2659   MockDataSource::Trace([&trace_lambda_calls](MockDataSource::TraceContext) {
2660     trace_lambda_calls++;
2661     MockDataSource::Trace([&trace_lambda_calls](MockDataSource::TraceContext) {
2662       trace_lambda_calls++;
2663     });
2664   });
2665 
2666   tracing_session->get()->StopBlocking();
2667   EXPECT_EQ(trace_lambda_calls, 1);
2668 }
2669 
TEST_P(PerfettoApiTest,ConsumerFlush)2670 TEST_P(PerfettoApiTest, ConsumerFlush) {
2671   auto* data_source = &data_sources_["my_data_source"];
2672 
2673   // Setup the trace config.
2674   perfetto::TraceConfig cfg;
2675   cfg.add_buffers()->set_size_kb(1024);
2676   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
2677   ds_cfg->set_name("my_data_source");
2678   ds_cfg->set_legacy_config("test config");
2679 
2680   // Create a new trace session.
2681   auto* tracing_session = NewTrace(cfg);
2682 
2683   tracing_session->get()->Start();
2684   data_source->on_start.Wait();
2685 
2686   MockDataSource::Trace([&](MockDataSource::TraceContext ctx) {
2687     auto packet = ctx.NewTracePacket();
2688     packet->set_timestamp(42);
2689     packet->set_for_testing()->set_str("flushed event");
2690     packet->Finalize();
2691 
2692     // The SMB scraping logic will skip the last packet because it cannot
2693     // guarantee it's finalized. Create an empty packet so we get the
2694     // previous one and this empty one is ignored.
2695     packet = ctx.NewTracePacket();
2696   });
2697 
2698   EXPECT_TRUE(tracing_session->get()->FlushBlocking());
2699 
2700   // Deliberately doing ReadTraceBlocking() before StopBlocking() to avoid
2701   // hitting the auto scrape-on-stop behavior of the service.
2702   std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
2703   tracing_session->get()->StopBlocking();
2704 
2705   ASSERT_GE(raw_trace.size(), 0u);
2706   perfetto::protos::gen::Trace trace;
2707   ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
2708   bool test_packet_found = false;
2709   for (const auto& packet : trace.packet()) {
2710     if (!packet.has_for_testing())
2711       continue;
2712     EXPECT_FALSE(test_packet_found);
2713     EXPECT_EQ(packet.timestamp(), 42U);
2714     EXPECT_EQ(packet.for_testing().str(), "flushed event");
2715     test_packet_found = true;
2716   }
2717   EXPECT_TRUE(test_packet_found);
2718 }
2719 
TEST_P(PerfettoApiTest,WithBatching)2720 TEST_P(PerfettoApiTest, WithBatching) {
2721   auto* data_source = &data_sources_["my_data_source"];
2722 
2723   // Setup the trace config.
2724   perfetto::TraceConfig cfg;
2725   cfg.set_duration_ms(500);
2726   cfg.add_buffers()->set_size_kb(1024);
2727   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
2728   ds_cfg->set_name("my_data_source");
2729   ds_cfg->set_legacy_config("test config");
2730 
2731   // Create a new trace session.
2732   auto* tracing_session = NewTrace(cfg);
2733 
2734   tracing_session->get()->Start();
2735   data_source->on_setup.Wait();
2736   data_source->on_start.Wait();
2737 
2738   std::stringstream first_large_message;
2739   for (size_t i = 0; i < 512; i++)
2740     first_large_message << i << ". Something wicked this way comes. ";
2741   auto first_large_message_str = first_large_message.str();
2742 
2743   // Emit one trace event before we begin batching.
2744   MockDataSource::Trace(
2745       [&first_large_message_str](MockDataSource::TraceContext ctx) {
2746         auto packet = ctx.NewTracePacket();
2747         packet->set_timestamp(42);
2748         packet->set_for_testing()->set_str(first_large_message_str);
2749         packet->Finalize();
2750       });
2751 
2752   // Simulate the start of a batching cycle by first setting the batching period
2753   // to a very large value and then force-flushing when we are done writing
2754   // data.
2755   ASSERT_TRUE(
2756       perfetto::test::EnableDirectSMBPatching(/*BackendType=*/GetParam()));
2757   perfetto::test::SetBatchCommitsDuration(UINT32_MAX,
2758                                           /*BackendType=*/GetParam());
2759 
2760   std::stringstream second_large_message;
2761   for (size_t i = 0; i < 512; i++)
2762     second_large_message << i << ". Something else wicked this way comes. ";
2763   auto second_large_message_str = second_large_message.str();
2764 
2765   // Emit another trace event.
2766   MockDataSource::Trace(
2767       [&second_large_message_str](MockDataSource::TraceContext ctx) {
2768         auto packet = ctx.NewTracePacket();
2769         packet->set_timestamp(43);
2770         packet->set_for_testing()->set_str(second_large_message_str);
2771         packet->Finalize();
2772 
2773         // Simulate the end of the batching cycle.
2774         ctx.Flush();
2775       });
2776 
2777   data_source->on_stop.Wait();
2778   tracing_session->on_stop.Wait();
2779 
2780   std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
2781   ASSERT_GE(raw_trace.size(), 0u);
2782 
2783   perfetto::protos::gen::Trace trace;
2784   ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
2785   bool test_packet_1_found = false;
2786   bool test_packet_2_found = false;
2787   for (const auto& packet : trace.packet()) {
2788     if (!packet.has_for_testing())
2789       continue;
2790     EXPECT_TRUE(packet.timestamp() == 42U || packet.timestamp() == 43U);
2791     if (packet.timestamp() == 42U) {
2792       EXPECT_FALSE(test_packet_1_found);
2793       EXPECT_EQ(packet.for_testing().str(), first_large_message_str);
2794       test_packet_1_found = true;
2795     } else {
2796       EXPECT_FALSE(test_packet_2_found);
2797       EXPECT_EQ(packet.for_testing().str(), second_large_message_str);
2798       test_packet_2_found = true;
2799     }
2800   }
2801   EXPECT_TRUE(test_packet_1_found && test_packet_2_found);
2802 }
2803 
TEST_P(PerfettoApiTest,BlockingStartAndStop)2804 TEST_P(PerfettoApiTest, BlockingStartAndStop) {
2805   auto* data_source = &data_sources_["my_data_source"];
2806 
2807   // Register a second data source to get a bit more coverage.
2808   perfetto::DataSourceDescriptor dsd;
2809   dsd.set_name("my_data_source2");
2810   MockDataSource2::Register(dsd, kTestDataSourceArg);
2811   perfetto::test::SyncProducers();
2812 
2813   // Setup the trace config.
2814   perfetto::TraceConfig cfg;
2815   cfg.set_duration_ms(500);
2816   cfg.add_buffers()->set_size_kb(1024);
2817   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
2818   ds_cfg->set_name("my_data_source");
2819   ds_cfg = cfg.add_data_sources()->mutable_config();
2820   ds_cfg->set_name("my_data_source2");
2821 
2822   // Create a new trace session.
2823   auto* tracing_session = NewTrace(cfg);
2824 
2825   tracing_session->get()->StartBlocking();
2826   EXPECT_TRUE(data_source->on_setup.notified());
2827   EXPECT_TRUE(data_source->on_start.notified());
2828 
2829   tracing_session->get()->StopBlocking();
2830   EXPECT_TRUE(data_source->on_stop.notified());
2831   EXPECT_TRUE(tracing_session->on_stop.notified());
2832 }
2833 
TEST_P(PerfettoApiTest,BlockingStartAndStopOnEmptySession)2834 TEST_P(PerfettoApiTest, BlockingStartAndStopOnEmptySession) {
2835   // Setup the trace config.
2836   perfetto::TraceConfig cfg;
2837   cfg.set_duration_ms(500);
2838   cfg.add_buffers()->set_size_kb(1024);
2839   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
2840   ds_cfg->set_name("non_existent_data_source");
2841 
2842   // Create a new trace session.
2843   auto* tracing_session = NewTrace(cfg);
2844   tracing_session->get()->StartBlocking();
2845   tracing_session->get()->StopBlocking();
2846   EXPECT_TRUE(tracing_session->on_stop.notified());
2847 }
2848 
TEST_P(PerfettoApiTest,WriteEventsAfterDeferredStop)2849 TEST_P(PerfettoApiTest, WriteEventsAfterDeferredStop) {
2850   auto* data_source = &data_sources_["my_data_source"];
2851   data_source->handle_stop_asynchronously = true;
2852 
2853   // Setup the trace config and start the tracing session.
2854   perfetto::TraceConfig cfg;
2855   cfg.set_duration_ms(500);
2856   cfg.add_buffers()->set_size_kb(1024);
2857   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
2858   ds_cfg->set_name("my_data_source");
2859   auto* tracing_session = NewTrace(cfg);
2860   tracing_session->get()->StartBlocking();
2861 
2862   // Stop and wait for the producer to have seen the stop event.
2863   WaitableTestEvent consumer_stop_signal;
2864   tracing_session->get()->SetOnStopCallback(
2865       [&consumer_stop_signal] { consumer_stop_signal.Notify(); });
2866   tracing_session->get()->Stop();
2867   data_source->on_stop.Wait();
2868 
2869   // At this point tracing should be still allowed because of the
2870   // HandleStopAsynchronously() call.
2871   bool lambda_called = false;
2872 
2873   // This usleep is here just to prevent that we accidentally pass the test
2874   // just by virtue of hitting some race. We should be able to trace up until
2875   // 5 seconds after seeing the stop when using the deferred stop mechanism.
2876   std::this_thread::sleep_for(std::chrono::milliseconds(250));
2877 
2878   MockDataSource::Trace([&lambda_called](MockDataSource::TraceContext ctx) {
2879     auto packet = ctx.NewTracePacket();
2880     packet->set_for_testing()->set_str("event written after OnStop");
2881     packet->Finalize();
2882     ctx.Flush();
2883     lambda_called = true;
2884   });
2885   ASSERT_TRUE(lambda_called);
2886 
2887   // Now call the async stop closure. This acks the stop to the service and
2888   // disallows further Trace() calls.
2889   EXPECT_TRUE(data_source->async_stop_closure);
2890   data_source->async_stop_closure();
2891 
2892   // Wait that the stop is propagated to the consumer.
2893   consumer_stop_signal.Wait();
2894 
2895   MockDataSource::Trace([](MockDataSource::TraceContext) {
2896     FAIL() << "Should not be called after the stop is acked";
2897   });
2898 
2899   // Check the contents of the trace.
2900   std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
2901   ASSERT_GE(raw_trace.size(), 0u);
2902   perfetto::protos::gen::Trace trace;
2903   ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
2904   int test_packet_found = 0;
2905   for (const auto& packet : trace.packet()) {
2906     if (!packet.has_for_testing())
2907       continue;
2908     EXPECT_EQ(packet.for_testing().str(), "event written after OnStop");
2909     test_packet_found++;
2910   }
2911   EXPECT_EQ(test_packet_found, 1);
2912 }
2913 
TEST_P(PerfettoApiTest,RepeatedStartAndStop)2914 TEST_P(PerfettoApiTest, RepeatedStartAndStop) {
2915   perfetto::TraceConfig cfg;
2916   cfg.set_duration_ms(500);
2917   cfg.add_buffers()->set_size_kb(1024);
2918   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
2919   ds_cfg->set_name("my_data_source");
2920 
2921   for (int i = 0; i < 5; i++) {
2922     auto* tracing_session = NewTrace(cfg);
2923     tracing_session->get()->Start();
2924     std::atomic<bool> stop_called{false};
2925     tracing_session->get()->SetOnStopCallback(
2926         [&stop_called] { stop_called = true; });
2927     tracing_session->get()->StopBlocking();
2928     EXPECT_TRUE(stop_called);
2929   }
2930 }
2931 
TEST_P(PerfettoApiTest,SetupWithFile)2932 TEST_P(PerfettoApiTest, SetupWithFile) {
2933 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
2934   if (GetParam() == perfetto::kSystemBackend)
2935     GTEST_SKIP() << "write_into_file + system mode is not supported on Windows";
2936 #endif
2937   auto temp_file = perfetto::test::CreateTempFile();
2938   perfetto::TraceConfig cfg;
2939   cfg.set_duration_ms(500);
2940   cfg.add_buffers()->set_size_kb(1024);
2941   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
2942   ds_cfg->set_name("my_data_source");
2943   // Write a trace into |fd|.
2944   auto* tracing_session = NewTrace(cfg, temp_file.fd);
2945   tracing_session->get()->StartBlocking();
2946   tracing_session->get()->StopBlocking();
2947 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
2948   // Check that |fd| didn't get closed.
2949   EXPECT_EQ(0, fcntl(temp_file.fd, F_GETFD, 0));
2950 #endif
2951   // Check that the trace got written.
2952   EXPECT_GT(lseek(temp_file.fd, 0, SEEK_END), 0);
2953   EXPECT_EQ(0, close(temp_file.fd));
2954   // Clean up.
2955   EXPECT_EQ(0, remove(temp_file.path.c_str()));
2956 }
2957 
TEST_P(PerfettoApiTest,MultipleRegistrations)2958 TEST_P(PerfettoApiTest, MultipleRegistrations) {
2959   // Attempt to register the same data source again.
2960   perfetto::DataSourceDescriptor dsd;
2961   dsd.set_name("my_data_source");
2962   EXPECT_TRUE(MockDataSource::Register(dsd));
2963   perfetto::test::SyncProducers();
2964 
2965   // Setup the trace config.
2966   perfetto::TraceConfig cfg;
2967   cfg.set_duration_ms(500);
2968   cfg.add_buffers()->set_size_kb(1024);
2969   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
2970   ds_cfg->set_name("my_data_source");
2971 
2972   // Create a new trace session.
2973   auto* tracing_session = NewTrace(cfg);
2974   tracing_session->get()->StartBlocking();
2975 
2976   // Emit one trace event.
2977   std::atomic<int> trace_lambda_calls{0};
2978   MockDataSource::Trace([&trace_lambda_calls](MockDataSource::TraceContext) {
2979     trace_lambda_calls++;
2980   });
2981 
2982   // Make sure the data source got called only once.
2983   tracing_session->get()->StopBlocking();
2984   EXPECT_EQ(trace_lambda_calls, 1);
2985 }
2986 
TEST_P(PerfettoApiTest,CustomIncrementalState)2987 TEST_P(PerfettoApiTest, CustomIncrementalState) {
2988   perfetto::DataSourceDescriptor dsd;
2989   dsd.set_name("incr_data_source");
2990   TestIncrementalDataSource::Register(dsd);
2991   perfetto::test::SyncProducers();
2992 
2993   // Setup the trace config.
2994   perfetto::TraceConfig cfg;
2995   cfg.set_duration_ms(500);
2996   cfg.add_buffers()->set_size_kb(1024);
2997   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
2998   ds_cfg->set_name("incr_data_source");
2999 
3000   // Create a new trace session.
3001   auto* tracing_session = NewTrace(cfg);
3002   tracing_session->get()->StartBlocking();
3003 
3004   // First emit a no-op trace event that initializes the incremental state as a
3005   // side effect.
3006   TestIncrementalDataSource::Trace(
3007       [](TestIncrementalDataSource::TraceContext) {});
3008   EXPECT_TRUE(TestIncrementalState::constructed);
3009 
3010   // Check that the incremental state is carried across trace events.
3011   TestIncrementalDataSource::Trace(
3012       [](TestIncrementalDataSource::TraceContext ctx) {
3013         auto* state = ctx.GetIncrementalState();
3014         EXPECT_TRUE(state);
3015         EXPECT_EQ(100, state->count);
3016         state->count++;
3017       });
3018 
3019   TestIncrementalDataSource::Trace(
3020       [](TestIncrementalDataSource::TraceContext ctx) {
3021         auto* state = ctx.GetIncrementalState();
3022         EXPECT_EQ(101, state->count);
3023       });
3024 
3025   // Make sure the incremental state gets cleaned up between sessions.
3026   tracing_session->get()->StopBlocking();
3027   tracing_session = NewTrace(cfg);
3028   tracing_session->get()->StartBlocking();
3029   TestIncrementalDataSource::Trace(
3030       [](TestIncrementalDataSource::TraceContext ctx) {
3031         auto* state = ctx.GetIncrementalState();
3032         EXPECT_TRUE(TestIncrementalState::destroyed);
3033         EXPECT_TRUE(state);
3034         EXPECT_EQ(100, state->count);
3035       });
3036   tracing_session->get()->StopBlocking();
3037 }
3038 
3039 // Regression test for b/139110180. Checks that GetDataSourceLocked() can be
3040 // called from OnStart() and OnStop() callbacks without deadlocking.
TEST_P(PerfettoApiTest,GetDataSourceLockedFromCallbacks)3041 TEST_P(PerfettoApiTest, GetDataSourceLockedFromCallbacks) {
3042   auto* data_source = &data_sources_["my_data_source"];
3043 
3044   // Setup the trace config.
3045   perfetto::TraceConfig cfg;
3046   cfg.set_duration_ms(1);
3047   cfg.add_buffers()->set_size_kb(1024);
3048   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
3049   ds_cfg->set_name("my_data_source");
3050 
3051   // Create a new trace session.
3052   auto* tracing_session = NewTrace(cfg);
3053 
3054   data_source->on_start_callback = [] {
3055     MockDataSource::Trace([](MockDataSource::TraceContext ctx) {
3056       ctx.NewTracePacket()->set_for_testing()->set_str("on-start");
3057       auto ds = ctx.GetDataSourceLocked();
3058       ASSERT_TRUE(!!ds);
3059       ctx.NewTracePacket()->set_for_testing()->set_str("on-start-locked");
3060     });
3061   };
3062 
3063   data_source->on_stop_callback = [] {
3064     MockDataSource::Trace([](MockDataSource::TraceContext ctx) {
3065       ctx.NewTracePacket()->set_for_testing()->set_str("on-stop");
3066       auto ds = ctx.GetDataSourceLocked();
3067       ASSERT_TRUE(!!ds);
3068       ctx.NewTracePacket()->set_for_testing()->set_str("on-stop-locked");
3069       ctx.Flush();
3070     });
3071   };
3072 
3073   tracing_session->get()->Start();
3074   data_source->on_stop.Wait();
3075   tracing_session->on_stop.Wait();
3076 
3077   std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
3078   ASSERT_GE(raw_trace.size(), 0u);
3079 
3080   perfetto::protos::gen::Trace trace;
3081   ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
3082   int packets_found = 0;
3083   for (const auto& packet : trace.packet()) {
3084     if (!packet.has_for_testing())
3085       continue;
3086     packets_found |= packet.for_testing().str() == "on-start" ? 1 : 0;
3087     packets_found |= packet.for_testing().str() == "on-start-locked" ? 2 : 0;
3088     packets_found |= packet.for_testing().str() == "on-stop" ? 4 : 0;
3089     packets_found |= packet.for_testing().str() == "on-stop-locked" ? 8 : 0;
3090   }
3091   EXPECT_EQ(packets_found, 1 | 2 | 4 | 8);
3092 }
3093 
TEST_P(PerfettoApiTest,OnStartCallback)3094 TEST_P(PerfettoApiTest, OnStartCallback) {
3095   perfetto::TraceConfig cfg;
3096   cfg.set_duration_ms(60000);
3097   cfg.add_buffers()->set_size_kb(1024);
3098   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
3099   ds_cfg->set_name("track_event");
3100   auto* tracing_session = NewTrace(cfg);
3101 
3102   WaitableTestEvent got_start;
3103   tracing_session->get()->SetOnStartCallback([&] { got_start.Notify(); });
3104   tracing_session->get()->Start();
3105   got_start.Wait();
3106 
3107   tracing_session->get()->StopBlocking();
3108 }
3109 
TEST_P(PerfettoApiTest,OnErrorCallback)3110 TEST_P(PerfettoApiTest, OnErrorCallback) {
3111   perfetto::TraceConfig cfg;
3112 
3113   // Requesting too long |duration_ms| will cause EnableTracing() to fail.
3114   cfg.set_duration_ms(static_cast<uint32_t>(-1));
3115   cfg.add_buffers()->set_size_kb(1024);
3116   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
3117   ds_cfg->set_name("track_event");
3118   auto* tracing_session = NewTrace(cfg);
3119 
3120   WaitableTestEvent got_error;
3121   tracing_session->get()->SetOnErrorCallback([&](perfetto::TracingError error) {
3122     EXPECT_EQ(perfetto::TracingError::kTracingFailed, error.code);
3123     EXPECT_FALSE(error.message.empty());
3124     got_error.Notify();
3125   });
3126 
3127   tracing_session->get()->Start();
3128   got_error.Wait();
3129 
3130   // Registered error callback will be triggered also by OnDisconnect()
3131   // function. This may happen after exiting this test what would result in
3132   // system crash (|got_error| will not exist at that time). To prevent that
3133   // scenario, error callback has to be cleared.
3134   tracing_session->get()->SetOnErrorCallback(nullptr);
3135   tracing_session->get()->StopBlocking();
3136 }
3137 
TEST_P(PerfettoApiTest,UnsupportedBackend)3138 TEST_P(PerfettoApiTest, UnsupportedBackend) {
3139   // Create a new trace session with an invalid backend type specified.
3140   // Specifically, the custom backend isn't initialized for these tests.
3141   perfetto::TraceConfig cfg;
3142   cfg.add_buffers()->set_size_kb(1024);
3143   auto* tracing_session = NewTrace(cfg, perfetto::BackendType::kCustomBackend);
3144 
3145   // Creating the consumer should cause an asynchronous disconnect error.
3146   WaitableTestEvent got_error;
3147   tracing_session->get()->SetOnErrorCallback([&](perfetto::TracingError error) {
3148     EXPECT_EQ(perfetto::TracingError::kDisconnected, error.code);
3149     EXPECT_FALSE(error.message.empty());
3150     got_error.Notify();
3151   });
3152   got_error.Wait();
3153 
3154   // Clear the callback for test tear down.
3155   tracing_session->get()->SetOnErrorCallback(nullptr);
3156   // Synchronize the consumer channel to ensure the callback has propagated.
3157   tracing_session->get()->StopBlocking();
3158 }
3159 
TEST_P(PerfettoApiTest,ForbiddenConsumer)3160 TEST_P(PerfettoApiTest, ForbiddenConsumer) {
3161   g_test_tracing_policy->should_allow_consumer_connection = false;
3162 
3163   // Create a new trace session while consumer connections are forbidden.
3164   perfetto::TraceConfig cfg;
3165   cfg.add_buffers()->set_size_kb(1024);
3166   auto* tracing_session = NewTrace(cfg);
3167 
3168   // Creating the consumer should cause an asynchronous disconnect error.
3169   WaitableTestEvent got_error;
3170   tracing_session->get()->SetOnErrorCallback([&](perfetto::TracingError error) {
3171     EXPECT_EQ(perfetto::TracingError::kDisconnected, error.code);
3172     EXPECT_FALSE(error.message.empty());
3173     got_error.Notify();
3174   });
3175   got_error.Wait();
3176 
3177   // Clear the callback for test tear down.
3178   tracing_session->get()->SetOnErrorCallback(nullptr);
3179   // Synchronize the consumer channel to ensure the callback has propagated.
3180   tracing_session->get()->StopBlocking();
3181 
3182   g_test_tracing_policy->should_allow_consumer_connection = true;
3183 }
3184 
TEST_P(PerfettoApiTest,GetTraceStats)3185 TEST_P(PerfettoApiTest, GetTraceStats) {
3186   perfetto::TraceConfig cfg;
3187   cfg.set_duration_ms(500);
3188   cfg.add_buffers()->set_size_kb(1024);
3189   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
3190   ds_cfg->set_name("track_event");
3191   auto* tracing_session = NewTrace(cfg);
3192   tracing_session->get()->StartBlocking();
3193 
3194   // Asynchronous read.
3195   WaitableTestEvent got_stats;
3196   tracing_session->get()->GetTraceStats(
3197       [&got_stats](perfetto::TracingSession::GetTraceStatsCallbackArgs args) {
3198         perfetto::protos::gen::TraceStats trace_stats;
3199         EXPECT_TRUE(args.success);
3200         EXPECT_TRUE(trace_stats.ParseFromArray(args.trace_stats_data.data(),
3201                                                args.trace_stats_data.size()));
3202         EXPECT_EQ(1, trace_stats.buffer_stats_size());
3203         got_stats.Notify();
3204       });
3205   got_stats.Wait();
3206 
3207   // Blocking read.
3208   auto stats = tracing_session->get()->GetTraceStatsBlocking();
3209   perfetto::protos::gen::TraceStats trace_stats;
3210   EXPECT_TRUE(stats.success);
3211   EXPECT_TRUE(trace_stats.ParseFromArray(stats.trace_stats_data.data(),
3212                                          stats.trace_stats_data.size()));
3213   EXPECT_EQ(1, trace_stats.buffer_stats_size());
3214 
3215   tracing_session->get()->StopBlocking();
3216 }
3217 
TEST_P(PerfettoApiTest,QueryServiceState)3218 TEST_P(PerfettoApiTest, QueryServiceState) {
3219   class QueryTestDataSource : public perfetto::DataSource<QueryTestDataSource> {
3220   };
3221   RegisterDataSource<QueryTestDataSource>("query_test_data_source");
3222   perfetto::test::SyncProducers();
3223 
3224   auto tracing_session =
3225       perfetto::Tracing::NewTrace(/*BackendType=*/GetParam());
3226   // Asynchronous read.
3227   WaitableTestEvent got_state;
3228   tracing_session->QueryServiceState(
3229       [&got_state](
3230           perfetto::TracingSession::QueryServiceStateCallbackArgs result) {
3231         perfetto::protos::gen::TracingServiceState state;
3232         EXPECT_TRUE(result.success);
3233         EXPECT_TRUE(state.ParseFromArray(result.service_state_data.data(),
3234                                          result.service_state_data.size()));
3235         EXPECT_EQ(1, state.producers_size());
3236         EXPECT_NE(std::string::npos,
3237                   state.producers()[0].name().find("integrationtest"));
3238         bool found_ds = false;
3239         for (const auto& ds : state.data_sources())
3240           found_ds |= ds.ds_descriptor().name() == "query_test_data_source";
3241         EXPECT_TRUE(found_ds);
3242         got_state.Notify();
3243       });
3244   got_state.Wait();
3245 
3246   // Blocking read.
3247   auto result = tracing_session->QueryServiceStateBlocking();
3248   perfetto::protos::gen::TracingServiceState state;
3249   EXPECT_TRUE(result.success);
3250   EXPECT_TRUE(state.ParseFromArray(result.service_state_data.data(),
3251                                    result.service_state_data.size()));
3252   EXPECT_EQ(1, state.producers_size());
3253   EXPECT_NE(std::string::npos,
3254             state.producers()[0].name().find("integrationtest"));
3255   bool found_ds = false;
3256   for (const auto& ds : state.data_sources())
3257     found_ds |= ds.ds_descriptor().name() == "query_test_data_source";
3258   EXPECT_TRUE(found_ds);
3259 }
3260 
TEST_P(PerfettoApiTest,LegacyTraceEvents)3261 TEST_P(PerfettoApiTest, LegacyTraceEvents) {
3262   auto is_new_session = [] {
3263     bool result;
3264     TRACE_EVENT_IS_NEW_TRACE(&result);
3265     return result;
3266   };
3267 
3268   // Create a new trace session.
3269   EXPECT_FALSE(is_new_session());
3270   auto* tracing_session =
3271       NewTraceWithCategories({"cat", TRACE_DISABLED_BY_DEFAULT("cat")});
3272   tracing_session->get()->StartBlocking();
3273   EXPECT_TRUE(is_new_session());
3274   EXPECT_FALSE(is_new_session());
3275 
3276   // Basic events.
3277   TRACE_EVENT_INSTANT0("cat", "LegacyEvent", TRACE_EVENT_SCOPE_GLOBAL);
3278   TRACE_EVENT_BEGIN1("cat", "LegacyEvent", "arg", 123);
3279   TRACE_EVENT_END2("cat", "LegacyEvent", "arg", "string", "arg2", 0.123f);
3280 
3281   // Scoped event.
3282   { TRACE_EVENT0("cat", "ScopedLegacyEvent"); }
3283 
3284   // Event with flow (and disabled category).
3285   TRACE_EVENT_WITH_FLOW0(TRACE_DISABLED_BY_DEFAULT("cat"), "LegacyFlowEvent",
3286                          0xdadacafe, TRACE_EVENT_FLAG_FLOW_IN);
3287 
3288   // Event with timestamp.
3289   TRACE_EVENT_INSTANT_WITH_TIMESTAMP0("cat", "LegacyInstantEvent",
3290                                       TRACE_EVENT_SCOPE_GLOBAL,
3291                                       MyTimestamp{123456789ul});
3292 
3293   // Event with id, thread id and timestamp (and dynamic name).
3294   TRACE_EVENT_COPY_BEGIN_WITH_ID_TID_AND_TIMESTAMP0(
3295       "cat", std::string("LegacyWithIdTidAndTimestamp").c_str(), 1,
3296       MyThreadId(123), MyTimestamp{3});
3297 
3298   // Event with id.
3299   TRACE_COUNTER1("cat", "LegacyCounter", 1234);
3300   TRACE_COUNTER_ID1("cat", "LegacyCounterWithId", 1234, 9000);
3301 
3302   // Metadata event.
3303   TRACE_EVENT_METADATA1("cat", "LegacyMetadata", "obsolete", true);
3304 
3305   perfetto::TrackEvent::Flush();
3306   tracing_session->get()->StopBlocking();
3307   auto slices = ReadSlicesFromTrace(tracing_session->get());
3308   EXPECT_THAT(
3309       slices,
3310       ElementsAre(
3311           "[track=0]I:cat.LegacyEvent", "B:cat.LegacyEvent(arg=(int)123)",
3312           "E(arg=(string)string,arg2=(double)0.123)", "B:cat.ScopedLegacyEvent",
3313           "E",
3314           "B(bind_id=3671771902)(flow_direction=1):disabled-by-default-cat."
3315           "LegacyFlowEvent",
3316           "[track=0]I:cat.LegacyInstantEvent",
3317           std::string("[track=") +
3318               std::to_string(perfetto::ThreadTrack::ForThread(123).uuid) +
3319               "]Legacy_S(unscoped_id=1):cat.LegacyWithIdTidAndTimestamp",
3320           "Legacy_C:cat.LegacyCounter(value=(int)1234)",
3321           "Legacy_C(unscoped_id=1234):cat.LegacyCounterWithId(value=(int)9000)",
3322           "Legacy_M:cat.LegacyMetadata"));
3323 }
3324 
TEST_P(PerfettoApiTest,LegacyTraceEventsWithCustomAnnotation)3325 TEST_P(PerfettoApiTest, LegacyTraceEventsWithCustomAnnotation) {
3326   // Create a new trace session.
3327   auto* tracing_session = NewTraceWithCategories({"cat"});
3328   tracing_session->get()->StartBlocking();
3329 
3330   MyDebugAnnotation annotation;
3331   TRACE_EVENT_BEGIN1("cat", "LegacyEvent", "arg", annotation);
3332 
3333   std::unique_ptr<MyDebugAnnotation> owned_annotation(new MyDebugAnnotation());
3334   TRACE_EVENT_BEGIN1("cat", "LegacyEvent", "arg", std::move(owned_annotation));
3335 
3336   perfetto::TrackEvent::Flush();
3337   tracing_session->get()->StopBlocking();
3338   auto slices = ReadSlicesFromTrace(tracing_session->get());
3339   EXPECT_THAT(slices,
3340               ElementsAre("B:cat.LegacyEvent(arg=(json){\"key\": 123})",
3341                           "B:cat.LegacyEvent(arg=(json){\"key\": 123})"));
3342 }
3343 
TEST_P(PerfettoApiTest,LegacyTraceEventsWithConcurrentSessions)3344 TEST_P(PerfettoApiTest, LegacyTraceEventsWithConcurrentSessions) {
3345   // Make sure that a uniquely owned debug annotation can be written into
3346   // multiple concurrent tracing sessions.
3347 
3348   auto* tracing_session = NewTraceWithCategories({"cat"});
3349   tracing_session->get()->StartBlocking();
3350 
3351   auto* tracing_session2 = NewTraceWithCategories({"cat"});
3352   tracing_session2->get()->StartBlocking();
3353 
3354   std::unique_ptr<MyDebugAnnotation> owned_annotation(new MyDebugAnnotation());
3355   TRACE_EVENT_BEGIN1("cat", "LegacyEvent", "arg", std::move(owned_annotation));
3356 
3357   perfetto::TrackEvent::Flush();
3358   tracing_session->get()->StopBlocking();
3359   auto slices = ReadSlicesFromTrace(tracing_session->get());
3360   EXPECT_THAT(slices,
3361               ElementsAre("B:cat.LegacyEvent(arg=(json){\"key\": 123})"));
3362 
3363   tracing_session2->get()->StopBlocking();
3364   slices = ReadSlicesFromTrace(tracing_session2->get());
3365   EXPECT_THAT(slices,
3366               ElementsAre("B:cat.LegacyEvent(arg=(json){\"key\": 123})"));
3367 }
3368 
TEST_P(PerfettoApiTest,LegacyTraceEventsWithId)3369 TEST_P(PerfettoApiTest, LegacyTraceEventsWithId) {
3370   auto* tracing_session = NewTraceWithCategories({"cat"});
3371   tracing_session->get()->StartBlocking();
3372 
3373   TRACE_EVENT_ASYNC_BEGIN0("cat", "UnscopedId", 0x1000);
3374   TRACE_EVENT_ASYNC_BEGIN0("cat", "LocalId", TRACE_ID_LOCAL(0x2000));
3375   TRACE_EVENT_ASYNC_BEGIN0("cat", "GlobalId", TRACE_ID_GLOBAL(0x3000));
3376   TRACE_EVENT_ASYNC_BEGIN0(
3377       "cat", "WithScope",
3378       TRACE_ID_WITH_SCOPE("scope string", TRACE_ID_GLOBAL(0x4000)));
3379 
3380   perfetto::TrackEvent::Flush();
3381   tracing_session->get()->StopBlocking();
3382   auto slices = ReadSlicesFromTrace(tracing_session->get());
3383   EXPECT_THAT(slices, ElementsAre("Legacy_S(unscoped_id=4096):cat.UnscopedId",
3384                                   "Legacy_S(local_id=8192):cat.LocalId",
3385                                   "Legacy_S(global_id=12288):cat.GlobalId",
3386                                   "Legacy_S(global_id=16384)(id_scope=\"scope "
3387                                   "string\"):cat.WithScope"));
3388 }
3389 
TEST_P(PerfettoApiTest,LegacyTraceEventsWithFlow)3390 TEST_P(PerfettoApiTest, LegacyTraceEventsWithFlow) {
3391   auto* tracing_session = NewTraceWithCategories({"cat"});
3392   tracing_session->get()->StartBlocking();
3393 
3394   const uint64_t flow_id = 1234;
3395   {
3396     TRACE_EVENT_WITH_FLOW1("cat", "LatencyInfo.Flow", TRACE_ID_GLOBAL(flow_id),
3397                            TRACE_EVENT_FLAG_FLOW_OUT, "step", "Begin");
3398   }
3399 
3400   {
3401     TRACE_EVENT_WITH_FLOW2("cat", "LatencyInfo.Flow", TRACE_ID_GLOBAL(flow_id),
3402                            TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
3403                            "step", "Middle", "value", false);
3404   }
3405 
3406   {
3407     TRACE_EVENT_WITH_FLOW1("cat", "LatencyInfo.Flow", TRACE_ID_GLOBAL(flow_id),
3408                            TRACE_EVENT_FLAG_FLOW_IN, "step", "End");
3409   }
3410 
3411   perfetto::TrackEvent::Flush();
3412   tracing_session->get()->StopBlocking();
3413   auto slices = ReadSlicesFromTrace(tracing_session->get());
3414   EXPECT_THAT(slices,
3415               ElementsAre("B(bind_id=1234)(flow_direction=2):cat.LatencyInfo."
3416                           "Flow(step=(string)Begin)",
3417                           "E",
3418                           "B(bind_id=1234)(flow_direction=3):cat.LatencyInfo."
3419                           "Flow(step=(string)Middle,value=(bool)0)",
3420                           "E",
3421                           "B(bind_id=1234)(flow_direction=1):cat.LatencyInfo."
3422                           "Flow(step=(string)End)",
3423                           "E"));
3424 }
3425 
TEST_P(PerfettoApiTest,LegacyCategoryGroupEnabledState)3426 TEST_P(PerfettoApiTest, LegacyCategoryGroupEnabledState) {
3427   bool foo_status;
3428   bool bar_status;
3429   bool dynamic_status;
3430   TRACE_EVENT_CATEGORY_GROUP_ENABLED("foo", &foo_status);
3431   TRACE_EVENT_CATEGORY_GROUP_ENABLED("bar", &bar_status);
3432   TRACE_EVENT_CATEGORY_GROUP_ENABLED("dynamic", &dynamic_status);
3433   EXPECT_FALSE(foo_status);
3434   EXPECT_FALSE(bar_status);
3435   EXPECT_FALSE(dynamic_status);
3436 
3437   const uint8_t* foo_enabled =
3438       TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED("foo");
3439   const uint8_t* bar_enabled =
3440       TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED("bar");
3441   EXPECT_FALSE(*foo_enabled);
3442   EXPECT_FALSE(*bar_enabled);
3443 
3444   // The category group enabled pointer can also be retrieved with a
3445   // runtime-computed category name.
3446   std::string computed_cat("cat");
3447   const uint8_t* computed_enabled =
3448       TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(computed_cat.c_str());
3449   EXPECT_FALSE(*computed_enabled);
3450 
3451   // The enabled pointers can be converted back to category names.
3452   EXPECT_EQ("foo", TRACE_EVENT_API_GET_CATEGORY_GROUP_NAME(foo_enabled));
3453   EXPECT_EQ("bar", TRACE_EVENT_API_GET_CATEGORY_GROUP_NAME(bar_enabled));
3454   EXPECT_EQ("cat", TRACE_EVENT_API_GET_CATEGORY_GROUP_NAME(computed_enabled));
3455 
3456   auto* tracing_session = NewTraceWithCategories({"foo", "dynamic", "cat"});
3457   tracing_session->get()->StartBlocking();
3458   TRACE_EVENT_CATEGORY_GROUP_ENABLED("foo", &foo_status);
3459   TRACE_EVENT_CATEGORY_GROUP_ENABLED("bar", &bar_status);
3460   TRACE_EVENT_CATEGORY_GROUP_ENABLED("dynamic", &dynamic_status);
3461   EXPECT_TRUE(foo_status);
3462   EXPECT_FALSE(bar_status);
3463   EXPECT_TRUE(dynamic_status);
3464 
3465   EXPECT_TRUE(*foo_enabled);
3466   EXPECT_FALSE(*bar_enabled);
3467   EXPECT_TRUE(*computed_enabled);
3468 
3469   tracing_session->get()->StopBlocking();
3470   TRACE_EVENT_CATEGORY_GROUP_ENABLED("foo", &foo_status);
3471   TRACE_EVENT_CATEGORY_GROUP_ENABLED("bar", &bar_status);
3472   TRACE_EVENT_CATEGORY_GROUP_ENABLED("dynamic", &dynamic_status);
3473   EXPECT_FALSE(foo_status);
3474   EXPECT_FALSE(bar_status);
3475   EXPECT_FALSE(dynamic_status);
3476   EXPECT_FALSE(*foo_enabled);
3477   EXPECT_FALSE(*bar_enabled);
3478   EXPECT_FALSE(*computed_enabled);
3479 }
3480 
TEST_P(PerfettoApiTest,CategoryEnabledState)3481 TEST_P(PerfettoApiTest, CategoryEnabledState) {
3482   perfetto::DynamicCategory dynamic{"dynamic"};
3483   EXPECT_FALSE(TRACE_EVENT_CATEGORY_ENABLED("foo"));
3484   EXPECT_FALSE(TRACE_EVENT_CATEGORY_ENABLED("bar"));
3485   EXPECT_FALSE(TRACE_EVENT_CATEGORY_ENABLED("red,green,blue,foo"));
3486   EXPECT_FALSE(TRACE_EVENT_CATEGORY_ENABLED("dynamic"));
3487   EXPECT_FALSE(TRACE_EVENT_CATEGORY_ENABLED("dynamic_2"));
3488   EXPECT_FALSE(TRACE_EVENT_CATEGORY_ENABLED(dynamic));
3489 
3490   auto* tracing_session = NewTraceWithCategories({"foo", "dynamic"});
3491   tracing_session->get()->StartBlocking();
3492   EXPECT_TRUE(TRACE_EVENT_CATEGORY_ENABLED("foo"));
3493   EXPECT_FALSE(TRACE_EVENT_CATEGORY_ENABLED("bar"));
3494   EXPECT_TRUE(TRACE_EVENT_CATEGORY_ENABLED("red,green,blue,foo"));
3495   EXPECT_TRUE(TRACE_EVENT_CATEGORY_ENABLED("dynamic"));
3496   EXPECT_FALSE(TRACE_EVENT_CATEGORY_ENABLED("dynamic_2"));
3497   EXPECT_TRUE(TRACE_EVENT_CATEGORY_ENABLED(dynamic));
3498 
3499   tracing_session->get()->StopBlocking();
3500   EXPECT_FALSE(TRACE_EVENT_CATEGORY_ENABLED("foo"));
3501   EXPECT_FALSE(TRACE_EVENT_CATEGORY_ENABLED("bar"));
3502   EXPECT_FALSE(TRACE_EVENT_CATEGORY_ENABLED("red,green,blue,foo"));
3503   EXPECT_FALSE(TRACE_EVENT_CATEGORY_ENABLED("dynamic"));
3504   EXPECT_FALSE(TRACE_EVENT_CATEGORY_ENABLED("dynamic_2"));
3505   EXPECT_FALSE(TRACE_EVENT_CATEGORY_ENABLED(dynamic));
3506 }
3507 
3508 class TestInterceptor : public perfetto::Interceptor<TestInterceptor> {
3509  public:
3510   static TestInterceptor* instance;
3511 
3512   struct ThreadLocalState : public perfetto::InterceptorBase::ThreadLocalState {
ThreadLocalState__anone89577de0111::TestInterceptor::ThreadLocalState3513     ThreadLocalState(ThreadLocalStateArgs& args) {
3514       // Test accessing instance state from the TLS constructor.
3515       if (auto self = args.GetInterceptorLocked()) {
3516         self->tls_initialized = true;
3517       }
3518     }
3519 
3520     std::map<uint64_t, std::string> event_names;
3521   };
3522 
TestInterceptor(const std::string & constructor_arg)3523   TestInterceptor(const std::string& constructor_arg) {
3524     EXPECT_EQ(constructor_arg, "Constructor argument");
3525     // Note: some tests in this suite register multiple track event data
3526     // sources. We only track data for the first in this test.
3527     if (!instance)
3528       instance = this;
3529   }
3530 
~TestInterceptor()3531   ~TestInterceptor() override {
3532     if (instance != this)
3533       return;
3534     instance = nullptr;
3535     EXPECT_TRUE(setup_called);
3536     EXPECT_TRUE(start_called);
3537     EXPECT_TRUE(stop_called);
3538     EXPECT_TRUE(tls_initialized);
3539   }
3540 
OnSetup(const SetupArgs &)3541   void OnSetup(const SetupArgs&) override {
3542     EXPECT_FALSE(setup_called);
3543     EXPECT_FALSE(start_called);
3544     EXPECT_FALSE(stop_called);
3545     setup_called = true;
3546   }
3547 
OnStart(const StartArgs &)3548   void OnStart(const StartArgs&) override {
3549     EXPECT_TRUE(setup_called);
3550     EXPECT_FALSE(start_called);
3551     EXPECT_FALSE(stop_called);
3552     start_called = true;
3553   }
3554 
OnStop(const StopArgs &)3555   void OnStop(const StopArgs&) override {
3556     EXPECT_TRUE(setup_called);
3557     EXPECT_TRUE(start_called);
3558     EXPECT_FALSE(stop_called);
3559     stop_called = true;
3560   }
3561 
OnTracePacket(InterceptorContext context)3562   static void OnTracePacket(InterceptorContext context) {
3563     perfetto::protos::pbzero::TracePacket::Decoder packet(
3564         context.packet_data.data, context.packet_data.size);
3565     EXPECT_TRUE(packet.trusted_packet_sequence_id() > 0);
3566     {
3567       auto self = context.GetInterceptorLocked();
3568       ASSERT_TRUE(self);
3569       EXPECT_TRUE(self->setup_called);
3570       EXPECT_TRUE(self->start_called);
3571       EXPECT_FALSE(self->stop_called);
3572       EXPECT_TRUE(self->tls_initialized);
3573     }
3574 
3575     auto& tls = context.GetThreadLocalState();
3576     if (packet.sequence_flags() &
3577         perfetto::protos::pbzero::TracePacket::SEQ_INCREMENTAL_STATE_CLEARED) {
3578       tls.event_names.clear();
3579     }
3580     if (packet.has_interned_data()) {
3581       perfetto::protos::pbzero::InternedData::Decoder interned_data(
3582           packet.interned_data());
3583       for (auto it = interned_data.event_names(); it; it++) {
3584         perfetto::protos::pbzero::EventName::Decoder entry(*it);
3585         tls.event_names[entry.iid()] = entry.name().ToStdString();
3586       }
3587     }
3588     if (packet.has_track_event()) {
3589       perfetto::protos::pbzero::TrackEvent::Decoder track_event(
3590           packet.track_event());
3591       uint64_t name_iid = track_event.name_iid();
3592       auto self = context.GetInterceptorLocked();
3593       self->events.push_back(tls.event_names[name_iid].c_str());
3594     }
3595   }
3596 
3597   bool setup_called = false;
3598   bool start_called = false;
3599   bool stop_called = false;
3600   bool tls_initialized = false;
3601   std::vector<std::string> events;
3602 };
3603 
3604 TestInterceptor* TestInterceptor::instance;
3605 
TEST_P(PerfettoApiTest,TracePacketInterception)3606 TEST_P(PerfettoApiTest, TracePacketInterception) {
3607   perfetto::InterceptorDescriptor desc;
3608   desc.set_name("test_interceptor");
3609   TestInterceptor::Register(desc, std::string("Constructor argument"));
3610 
3611   perfetto::TraceConfig cfg;
3612   cfg.set_duration_ms(500);
3613   cfg.add_buffers()->set_size_kb(1024);
3614   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
3615   ds_cfg->set_name("track_event");
3616   ds_cfg->mutable_interceptor_config()->set_name("test_interceptor");
3617 
3618   auto* tracing_session = NewTrace(cfg);
3619   tracing_session->get()->StartBlocking();
3620   EXPECT_EQ(0u, TestInterceptor::instance->events.size());
3621 
3622   // The interceptor should see an event immediately without any explicit
3623   // flushing.
3624   TRACE_EVENT_BEGIN("foo", "Hip");
3625   EXPECT_THAT(TestInterceptor::instance->events, ElementsAre("Hip"));
3626 
3627   // Emit another event with the same title to test interning.
3628   TRACE_EVENT_BEGIN("foo", "Hip");
3629   EXPECT_THAT(TestInterceptor::instance->events, ElementsAre("Hip", "Hip"));
3630 
3631   // Emit an event from another thread. It should still reach the same
3632   // interceptor instance.
3633   std::thread thread([] { TRACE_EVENT_BEGIN("foo", "Hooray"); });
3634   thread.join();
3635   EXPECT_THAT(TestInterceptor::instance->events,
3636               ElementsAre("Hip", "Hip", "Hooray"));
3637 
3638   // Emit a packet that spans multiple segments and must be stitched together.
3639   TestInterceptor::instance->events.clear();
3640   static char long_title[8192];
3641   memset(long_title, 'a', sizeof(long_title) - 1);
3642   long_title[sizeof(long_title) - 1] = 0;
3643   TRACE_EVENT_BEGIN("foo", long_title);
3644   EXPECT_THAT(TestInterceptor::instance->events, ElementsAre(long_title));
3645 
3646   tracing_session->get()->StopBlocking();
3647 }
3648 
EmitConsoleEvents()3649 void EmitConsoleEvents() {
3650   TRACE_EVENT_INSTANT("foo", "Instant event");
3651   TRACE_EVENT("foo", "Scoped event");
3652   TRACE_EVENT_BEGIN("foo", "Nested event");
3653   TRACE_EVENT_INSTANT("foo", "Instant event");
3654   TRACE_EVENT_INSTANT("foo", "Annotated event", "foo", 1, "bar", "hello");
3655   TRACE_EVENT_END("foo");
3656   uint64_t async_id = 4004;
3657   auto track = perfetto::Track(async_id, perfetto::ThreadTrack::Current());
3658   perfetto::TrackEvent::SetTrackDescriptor(
3659       track, [](perfetto::protos::pbzero::TrackDescriptor* desc) {
3660         desc->set_name("AsyncTrack");
3661       });
3662   TRACE_EVENT_BEGIN("test", "AsyncEvent", track);
3663 
3664   std::thread thread([&] {
3665     TRACE_EVENT("foo", "EventFromAnotherThread");
3666     TRACE_EVENT_INSTANT("foo", "Instant event");
3667     TRACE_EVENT_END("test", track);
3668   });
3669   thread.join();
3670 
3671   TRACE_EVENT_INSTANT(
3672       "foo", "More annotations", "dict",
3673       [](perfetto::TracedValue context) {
3674         auto dict = std::move(context).WriteDictionary();
3675         dict.Add("key", 123);
3676       },
3677       "array",
3678       [](perfetto::TracedValue context) {
3679         auto array = std::move(context).WriteArray();
3680         array.Append("first");
3681         array.Append("second");
3682       });
3683 }
3684 
TEST_P(PerfettoApiTest,ConsoleInterceptorPrint)3685 TEST_P(PerfettoApiTest, ConsoleInterceptorPrint) {
3686   perfetto::ConsoleInterceptor::Register();
3687 
3688   perfetto::TraceConfig cfg;
3689   cfg.set_duration_ms(500);
3690   cfg.add_buffers()->set_size_kb(1024);
3691   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
3692   ds_cfg->set_name("track_event");
3693   ds_cfg->mutable_interceptor_config()->set_name("console");
3694 
3695   auto* tracing_session = NewTrace(cfg);
3696   tracing_session->get()->StartBlocking();
3697   EmitConsoleEvents();
3698   tracing_session->get()->StopBlocking();
3699 }
3700 
TEST_P(PerfettoApiTest,ConsoleInterceptorVerify)3701 TEST_P(PerfettoApiTest, ConsoleInterceptorVerify) {
3702   perfetto::ConsoleInterceptor::Register();
3703   auto temp_file = perfetto::test::CreateTempFile();
3704   perfetto::ConsoleInterceptor::SetOutputFdForTesting(temp_file.fd);
3705 
3706   perfetto::TraceConfig cfg;
3707   cfg.set_duration_ms(500);
3708   cfg.add_buffers()->set_size_kb(1024);
3709   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
3710   ds_cfg->set_name("track_event");
3711   ds_cfg->mutable_interceptor_config()->set_name("console");
3712 
3713   auto* tracing_session = NewTrace(cfg);
3714   tracing_session->get()->StartBlocking();
3715   EmitConsoleEvents();
3716   tracing_session->get()->StopBlocking();
3717   perfetto::ConsoleInterceptor::SetOutputFdForTesting(0);
3718 
3719   std::vector<std::string> lines;
3720   FILE* f = fdopen(temp_file.fd, "r");
3721   fseek(f, 0u, SEEK_SET);
3722   std::array<char, 128> line{};
3723   while (fgets(line.data(), line.size(), f)) {
3724     // Ignore timestamps and process/thread ids.
3725     std::string s(line.data() + 28);
3726     // Filter out durations.
3727     s = std::regex_replace(s, std::regex(" [+][0-9]*ms"), "");
3728     lines.push_back(std::move(s));
3729   }
3730   fclose(f);
3731   EXPECT_EQ(0, remove(temp_file.path.c_str()));
3732 
3733   // clang-format off
3734   std::vector<std::string> golden_lines = {
3735       "foo   Instant event\n",
3736       "foo   Scoped event {\n",
3737       "foo   -  Nested event {\n",
3738       "foo   -  -  Instant event\n",
3739       "foo   -  -  Annotated event(foo:1, bar:hello)\n",
3740       "foo   -  } Nested event\n",
3741       "test  AsyncEvent {\n",
3742       "foo   EventFromAnotherThread {\n",
3743       "foo   -  Instant event\n",
3744       "test  } AsyncEvent\n",
3745       "foo   } EventFromAnotherThread\n",
3746       "foo   -  More annotations(dict:{key:123}, array:[first, second])\n",
3747       "foo   } Scoped event\n",
3748   };
3749   // clang-format on
3750   EXPECT_THAT(lines, ContainerEq(golden_lines));
3751 }
3752 
TEST_P(PerfettoApiTest,TrackEventObserver)3753 TEST_P(PerfettoApiTest, TrackEventObserver) {
3754   class Observer : public perfetto::TrackEventSessionObserver {
3755    public:
3756     ~Observer() override = default;
3757 
3758     void OnSetup(const perfetto::DataSourceBase::SetupArgs&) {
3759       // Since other tests here register multiple track event data sources,
3760       // ignore all but the first notifications.
3761       if (setup_called)
3762         return;
3763       setup_called = true;
3764       if (unsubscribe_at_setup)
3765         perfetto::TrackEvent::RemoveSessionObserver(this);
3766       // This event isn't recorded in the trace because tracing isn't active yet
3767       // when OnSetup is called.
3768       TRACE_EVENT_INSTANT("foo", "OnSetup");
3769       // However the active tracing categories have already been updated at this
3770       // point.
3771       EXPECT_TRUE(perfetto::TrackEvent::IsEnabled());
3772       EXPECT_TRUE(TRACE_EVENT_CATEGORY_ENABLED("foo"));
3773     }
3774 
3775     void OnStart(const perfetto::DataSourceBase::StartArgs&) {
3776       if (start_called)
3777         return;
3778       start_called = true;
3779       EXPECT_TRUE(perfetto::TrackEvent::IsEnabled());
3780       EXPECT_TRUE(TRACE_EVENT_CATEGORY_ENABLED("foo"));
3781       TRACE_EVENT_INSTANT("foo", "OnStart");
3782     }
3783 
3784     void OnStop(const perfetto::DataSourceBase::StopArgs&) {
3785       if (stop_called)
3786         return;
3787       stop_called = true;
3788       EXPECT_TRUE(perfetto::TrackEvent::IsEnabled());
3789       EXPECT_TRUE(TRACE_EVENT_CATEGORY_ENABLED("foo"));
3790       TRACE_EVENT_INSTANT("foo", "OnStop");
3791       perfetto::TrackEvent::Flush();
3792     }
3793 
3794     bool setup_called{};
3795     bool start_called{};
3796     bool stop_called{};
3797     bool unsubscribe_at_setup{};
3798   };
3799 
3800   EXPECT_FALSE(perfetto::TrackEvent::IsEnabled());
3801   {
3802     Observer observer;
3803     perfetto::TrackEvent::AddSessionObserver(&observer);
3804 
3805     auto* tracing_session = NewTraceWithCategories({"foo"});
3806     tracing_session->get()->StartBlocking();
3807     EXPECT_TRUE(observer.setup_called);
3808     EXPECT_TRUE(observer.start_called);
3809     tracing_session->get()->StopBlocking();
3810     EXPECT_TRUE(observer.stop_called);
3811     perfetto::TrackEvent::RemoveSessionObserver(&observer);
3812     auto slices = ReadSlicesFromTrace(tracing_session->get());
3813     EXPECT_THAT(slices, ElementsAre("I:foo.OnStart", "I:foo.OnStop"));
3814   }
3815 
3816   // No notifications after removing observer.
3817   {
3818     Observer observer;
3819     perfetto::TrackEvent::AddSessionObserver(&observer);
3820     perfetto::TrackEvent::RemoveSessionObserver(&observer);
3821     auto* tracing_session = NewTraceWithCategories({"foo"});
3822     tracing_session->get()->StartBlocking();
3823     EXPECT_FALSE(observer.setup_called);
3824     EXPECT_FALSE(observer.start_called);
3825     tracing_session->get()->StopBlocking();
3826     EXPECT_FALSE(observer.stop_called);
3827   }
3828 
3829   // Removing observer in a callback.
3830   {
3831     Observer observer;
3832     observer.unsubscribe_at_setup = true;
3833     perfetto::TrackEvent::AddSessionObserver(&observer);
3834     auto* tracing_session = NewTraceWithCategories({"foo"});
3835     tracing_session->get()->StartBlocking();
3836     EXPECT_TRUE(observer.setup_called);
3837     EXPECT_FALSE(observer.start_called);
3838     tracing_session->get()->StopBlocking();
3839     EXPECT_FALSE(observer.stop_called);
3840     perfetto::TrackEvent::RemoveSessionObserver(&observer);
3841   }
3842 
3843   // Multiple observers.
3844   {
3845     Observer observer1;
3846     Observer observer2;
3847     perfetto::TrackEvent::AddSessionObserver(&observer1);
3848     perfetto::TrackEvent::AddSessionObserver(&observer2);
3849     auto* tracing_session = NewTraceWithCategories({"foo"});
3850     tracing_session->get()->StartBlocking();
3851     tracing_session->get()->StopBlocking();
3852     perfetto::TrackEvent::RemoveSessionObserver(&observer1);
3853     perfetto::TrackEvent::RemoveSessionObserver(&observer2);
3854     auto slices = ReadSlicesFromTrace(tracing_session->get());
3855     EXPECT_THAT(slices, ElementsAre("I:foo.OnStart", "I:foo.OnStart",
3856                                     "I:foo.OnStop", "I:foo.OnStop"));
3857   }
3858 
3859   // Multiple observers with one being removed midway.
3860   {
3861     Observer observer1;
3862     Observer observer2;
3863     perfetto::TrackEvent::AddSessionObserver(&observer1);
3864     perfetto::TrackEvent::AddSessionObserver(&observer2);
3865     auto* tracing_session = NewTraceWithCategories({"foo"});
3866     tracing_session->get()->StartBlocking();
3867     perfetto::TrackEvent::RemoveSessionObserver(&observer1);
3868     tracing_session->get()->StopBlocking();
3869     perfetto::TrackEvent::RemoveSessionObserver(&observer2);
3870     auto slices = ReadSlicesFromTrace(tracing_session->get());
3871     EXPECT_THAT(slices,
3872                 ElementsAre("I:foo.OnStart", "I:foo.OnStart", "I:foo.OnStop"));
3873   }
3874   EXPECT_FALSE(perfetto::TrackEvent::IsEnabled());
3875 }
3876 
3877 #if PERFETTO_BUILDFLAG(PERFETTO_COMPILER_CLANG)
3878 struct __attribute__((capability("mutex"))) MockMutex {
Lock__anone89577de0111::MockMutex3879   void Lock() __attribute__((acquire_capability())) {}
Unlock__anone89577de0111::MockMutex3880   void Unlock() __attribute__((release_capability())) {}
3881 };
3882 
3883 struct AnnotatedObject {
3884   MockMutex mutex;
3885   int value __attribute__((guarded_by(mutex))) = {};
3886 };
3887 
TEST_P(PerfettoApiTest,ThreadSafetyAnnotation)3888 TEST_P(PerfettoApiTest, ThreadSafetyAnnotation) {
3889   AnnotatedObject obj;
3890 
3891   // Access to the locked field is only allowed while holding the mutex.
3892   obj.mutex.Lock();
3893   obj.value = 1;
3894   obj.mutex.Unlock();
3895 
3896   auto* tracing_session = NewTraceWithCategories({"cat"});
3897   tracing_session->get()->StartBlocking();
3898 
3899   // It should be possible to trace the field while holding the lock.
3900   obj.mutex.Lock();
3901   TRACE_EVENT_INSTANT("cat", "Instant", "value", obj.value);
3902   TRACE_EVENT_INSTANT1("cat", "InstantLegacy", 0, "value", obj.value);
3903   { TRACE_EVENT("cat", "Scoped", "value", obj.value); }
3904   { TRACE_EVENT1("cat", "ScopedLegacy", "value", obj.value); }
3905   obj.mutex.Unlock();
3906 
3907   perfetto::TrackEvent::Flush();
3908   tracing_session->get()->StopBlocking();
3909   auto slices = ReadSlicesFromTrace(tracing_session->get());
3910   EXPECT_THAT(slices, ElementsAre("I:cat.Instant(value=(int)1)",
3911                                   "[track=0]I:cat.InstantLegacy(value=(int)1)",
3912                                   "B:cat.Scoped(value=(int)1)", "E",
3913                                   "B:cat.ScopedLegacy(value=(int)1)", "E"));
3914 }
3915 #endif  // PERFETTO_BUILDFLAG(PERFETTO_COMPILER_CLANG)
3916 
TEST_P(PerfettoApiTest,Counters)3917 TEST_P(PerfettoApiTest, Counters) {
3918   auto* tracing_session = NewTraceWithCategories({"cat"});
3919   tracing_session->get()->StartBlocking();
3920 
3921   // Describe a counter track.
3922   perfetto::CounterTrack fps_track = perfetto::CounterTrack("Framerate", "fps");
3923 
3924   // Emit an integer sample.
3925   TRACE_COUNTER("cat", fps_track, 120);
3926 
3927   // Global tracks can be constructed at build time.
3928   constexpr auto goats_track =
3929       perfetto::CounterTrack::Global("Goats teleported", "goats x 1000")
3930           .set_unit_multiplier(1000);
3931   static_assert(goats_track.uuid == 0x6072fc234f82df11,
3932                 "Counter track uuid mismatch");
3933 
3934   // Emit some floating point samples.
3935   TRACE_COUNTER("cat", goats_track, 0.25);
3936   TRACE_COUNTER("cat", goats_track, 0.5);
3937   TRACE_COUNTER("cat", goats_track, 0.75);
3938 
3939   // Emit a sample using an inline track name.
3940   TRACE_COUNTER("cat", "Voltage", 220);
3941 
3942   // Emit sample with a custom timestamp.
3943   TRACE_COUNTER("cat",
3944                 perfetto::CounterTrack("Power", "GW").set_category("dmc"),
3945                 MyTimestamp(1985u), 1.21f);
3946   perfetto::TrackEvent::Flush();
3947 
3948   tracing_session->get()->StopBlocking();
3949   std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
3950 
3951   perfetto::protos::gen::Trace trace;
3952   ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
3953   std::map<uint64_t, std::string> counter_names;
3954   std::vector<std::string> counter_samples;
3955   for (const auto& packet : trace.packet()) {
3956     if (packet.has_track_event()) {
3957       auto event = packet.track_event();
3958       EXPECT_EQ(perfetto::protos::gen::TrackEvent_Type_TYPE_COUNTER,
3959                 event.type());
3960       std::stringstream sample;
3961       std::string counter_name = counter_names[event.track_uuid()];
3962       sample << counter_name << " = ";
3963       if (event.has_counter_value()) {
3964         sample << event.counter_value();
3965       } else if (event.has_double_counter_value()) {
3966         sample << event.double_counter_value();
3967       }
3968       if (counter_name == "Power") {
3969         EXPECT_EQ(1985u, packet.timestamp());
3970       }
3971       counter_samples.push_back(sample.str());
3972     }
3973 
3974     if (!packet.has_track_descriptor() ||
3975         !packet.track_descriptor().has_counter()) {
3976       continue;
3977     }
3978     auto desc = packet.track_descriptor();
3979     counter_names[desc.uuid()] = desc.name();
3980     if (desc.name() == "Framerate") {
3981       EXPECT_EQ("fps", desc.counter().unit_name());
3982     } else if (desc.name() == "Goats teleported") {
3983       EXPECT_EQ("goats x 1000", desc.counter().unit_name());
3984       EXPECT_EQ(1000, desc.counter().unit_multiplier());
3985     } else if (desc.name() == "Power") {
3986       EXPECT_EQ("GW", desc.counter().unit_name());
3987       EXPECT_EQ("dmc", desc.counter().categories()[0]);
3988     }
3989   }
3990   EXPECT_EQ(4u, counter_names.size());
3991   EXPECT_THAT(counter_samples,
3992               ElementsAre("Framerate = 120", "Goats teleported = 0.25",
3993                           "Goats teleported = 0.5", "Goats teleported = 0.75",
3994                           "Voltage = 220", "Power = 1.21"));
3995 }
3996 
3997 struct BackendTypeAsString {
operator ()__anone89577de0111::BackendTypeAsString3998   std::string operator()(
3999       const ::testing::TestParamInfo<perfetto::BackendType>& info) const {
4000     switch (info.param) {
4001       case perfetto::kInProcessBackend:
4002         return "InProc";
4003       case perfetto::kSystemBackend:
4004         return "System";
4005       case perfetto::kCustomBackend:
4006         return "Custom";
4007       case perfetto::kUnspecifiedBackend:
4008         return "Unspec";
4009     }
4010     return nullptr;
4011   }
4012 };
4013 
4014 INSTANTIATE_TEST_SUITE_P(PerfettoApiTest,
4015                          PerfettoApiTest,
4016                          ::testing::Values(perfetto::kInProcessBackend,
4017                                            perfetto::kSystemBackend),
4018                          BackendTypeAsString());
4019 
4020 }  // namespace
4021 
4022 PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS(MockDataSource);
4023 PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS(MockDataSource2);
4024 PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS(TestIncrementalDataSource,
4025                                             TestIncrementalDataSourceTraits);
4026 
4027 PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(MockDataSource);
4028 PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(MockDataSource2);
4029 PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(TestIncrementalDataSource,
4030                                            TestIncrementalDataSourceTraits);
4031