xref: /aosp_15_r20/external/perfetto/src/tracing/test/api_integrationtest.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
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 <fstream>
22 #include <functional>
23 #include <list>
24 #include <mutex>
25 #include <regex>
26 #include <string_view>
27 #include <thread>
28 #include <unordered_set>
29 #include <vector>
30 
31 // We also want to test legacy trace events.
32 #define PERFETTO_ENABLE_LEGACY_TRACE_EVENTS 1
33 
34 #include "perfetto/tracing.h"
35 #include "test/gtest_and_gmock.h"
36 #include "test/integrationtest_initializer.h"
37 
38 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
39 #include <Windows.h>  // For CreateFile().
40 #else
41 #include <sys/socket.h>
42 #include <sys/types.h>
43 #include <sys/un.h>
44 #endif
45 
46 // Deliberately not pulling any non-public perfetto header to spot accidental
47 // header public -> non-public dependency while building this file.
48 
49 // These two are the only headers allowed here, see comments in
50 // api_test_support.h.
51 #include "src/tracing/test/api_test_support.h"
52 #include "src/tracing/test/tracing_module.h"
53 
54 #include "perfetto/base/time.h"
55 #include "perfetto/protozero/scattered_heap_buffer.h"
56 #include "perfetto/tracing/core/data_source_descriptor.h"
57 #include "perfetto/tracing/core/trace_config.h"
58 
59 // xxx.pbzero.h includes are for the writing path (the code that pretends to be
60 // production code).
61 // yyy.gen.h includes are for the test readback path (the code in the test that
62 // checks that the results are valid).
63 #include "protos/perfetto/common/builtin_clock.pbzero.h"
64 #include "protos/perfetto/common/interceptor_descriptor.gen.h"
65 #include "protos/perfetto/common/trace_stats.gen.h"
66 #include "protos/perfetto/common/tracing_service_state.gen.h"
67 #include "protos/perfetto/common/track_event_descriptor.gen.h"
68 #include "protos/perfetto/common/track_event_descriptor.pbzero.h"
69 #include "protos/perfetto/config/interceptor_config.gen.h"
70 #include "protos/perfetto/config/track_event/track_event_config.gen.h"
71 #include "protos/perfetto/trace/clock_snapshot.gen.h"
72 #include "protos/perfetto/trace/clock_snapshot.pbzero.h"
73 #include "protos/perfetto/trace/gpu/gpu_render_stage_event.gen.h"
74 #include "protos/perfetto/trace/gpu/gpu_render_stage_event.pbzero.h"
75 #include "protos/perfetto/trace/interned_data/interned_data.gen.h"
76 #include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
77 #include "protos/perfetto/trace/profiling/profile_common.gen.h"
78 #include "protos/perfetto/trace/test_event.gen.h"
79 #include "protos/perfetto/trace/test_event.pbzero.h"
80 #include "protos/perfetto/trace/test_extensions.pbzero.h"
81 #include "protos/perfetto/trace/trace.gen.h"
82 #include "protos/perfetto/trace/trace.pbzero.h"
83 #include "protos/perfetto/trace/trace_packet.gen.h"
84 #include "protos/perfetto/trace/trace_packet.pbzero.h"
85 #include "protos/perfetto/trace/trace_packet_defaults.gen.h"
86 #include "protos/perfetto/trace/track_event/chrome_process_descriptor.gen.h"
87 #include "protos/perfetto/trace/track_event/chrome_process_descriptor.pbzero.h"
88 #include "protos/perfetto/trace/track_event/counter_descriptor.gen.h"
89 #include "protos/perfetto/trace/track_event/debug_annotation.gen.h"
90 #include "protos/perfetto/trace/track_event/debug_annotation.pbzero.h"
91 #include "protos/perfetto/trace/track_event/log_message.gen.h"
92 #include "protos/perfetto/trace/track_event/log_message.pbzero.h"
93 #include "protos/perfetto/trace/track_event/process_descriptor.gen.h"
94 #include "protos/perfetto/trace/track_event/process_descriptor.pbzero.h"
95 #include "protos/perfetto/trace/track_event/source_location.gen.h"
96 #include "protos/perfetto/trace/track_event/source_location.pbzero.h"
97 #include "protos/perfetto/trace/track_event/thread_descriptor.gen.h"
98 #include "protos/perfetto/trace/track_event/thread_descriptor.pbzero.h"
99 #include "protos/perfetto/trace/track_event/track_descriptor.gen.h"
100 #include "protos/perfetto/trace/track_event/track_event.gen.h"
101 #include "protos/perfetto/trace/trigger.gen.h"
102 
103 // Events in categories starting with "dynamic" will use dynamic category
104 // lookup.
105 PERFETTO_DEFINE_TEST_CATEGORY_PREFIXES("dynamic");
106 
107 // Trace categories used in the tests.
108 PERFETTO_DEFINE_CATEGORIES(
109     perfetto::Category("test")
110         .SetDescription("This is a test category")
111         .SetTags("tag"),
112     perfetto::Category("foo"),
113     perfetto::Category("bar"),
114     perfetto::Category("cat").SetTags("slow"),
115     perfetto::Category("cat.verbose").SetTags("debug"),
116     perfetto::Category("cat-with-dashes"),
117     perfetto::Category::Group("foo,bar"),
118     perfetto::Category::Group("baz,bar,quux"),
119     perfetto::Category::Group("red,green,blue,foo"),
120     perfetto::Category::Group("red,green,blue,yellow"),
121     perfetto::Category(TRACE_DISABLED_BY_DEFAULT("cat")));
122 PERFETTO_TRACK_EVENT_STATIC_STORAGE();
123 
124 // Test declaring an extra set of categories in a namespace in addition to the
125 // default one.
126 PERFETTO_DEFINE_CATEGORIES_IN_NAMESPACE(other_ns,
127                                         perfetto::Category("other_ns"));
128 PERFETTO_TRACK_EVENT_STATIC_STORAGE_IN_NAMESPACE(other_ns);
129 
130 // For testing interning of complex objects.
131 using SourceLocation = std::tuple<const char* /* file_name */,
132                                   const char* /* function_name */,
133                                   uint32_t /* line_number */>;
134 
135 template <>
136 struct std::hash<SourceLocation> {
operator ()std::hash137   size_t operator()(const SourceLocation& value) const {
138     auto hasher = hash<size_t>();
139     return hasher(reinterpret_cast<size_t>(get<0>(value))) ^
140            hasher(reinterpret_cast<size_t>(get<1>(value))) ^
141            hasher(get<2>(value));
142   }
143 };
144 
WriteFile(const std::string & file_name,const char * content,size_t len)145 static void WriteFile(const std::string& file_name,
146                       const char* content,
147                       size_t len) {
148   std::ofstream output;
149   output.open(file_name.c_str(), std::ios::out | std::ios::binary);
150   output.write(content, static_cast<std::streamsize>(len));
151   output.close();
152 }
153 
154 // Unused in merged code, but very handy for debugging when trace generated in
155 // a test needs to be exported, to understand it further with other tools.
WriteFile(const std::string & file_name,const std::vector<char> & data)156 PERFETTO_UNUSED static void WriteFile(const std::string& file_name,
157                                       const std::vector<char>& data) {
158   return WriteFile(file_name, data.data(), data.size());
159 }
160 
161 // Returns true if the |key| is present in |container|.
162 template <typename ContainerType, class KeyType>
ContainsKey(const ContainerType & container,const KeyType & key)163 bool ContainsKey(const ContainerType& container, const KeyType& key) {
164   return container.find(key) != container.end();
165 }
166 
167 // Represents an opaque (from Perfetto's point of view) thread identifier (e.g.,
168 // base::PlatformThreadId in Chromium).
169 struct MyThreadId {
MyThreadIdMyThreadId170   explicit MyThreadId(int tid_) : tid(tid_) {}
171 
172   const int tid = 0;
173 };
174 
175 // Represents an opaque timestamp (e.g., base::TimeTicks in Chromium).
176 class MyTimestamp {
177  public:
MyTimestamp(uint64_t ts_)178   explicit MyTimestamp(uint64_t ts_) : ts(ts_) {}
179 
180   const uint64_t ts;
181 };
182 
183 namespace perfetto {
184 namespace legacy {
185 
186 template <>
ConvertThreadId(const MyThreadId & thread)187 ThreadTrack ConvertThreadId(const MyThreadId& thread) {
188   return perfetto::ThreadTrack::ForThread(
189       static_cast<base::PlatformThreadId>(thread.tid));
190 }
191 
192 }  // namespace legacy
193 
194 template <>
195 struct TraceTimestampTraits<MyTimestamp> {
ConvertTimestampToTraceTimeNsperfetto::TraceTimestampTraits196   static TraceTimestamp ConvertTimestampToTraceTimeNs(
197       const MyTimestamp& timestamp) {
198     return {static_cast<uint32_t>(TrackEvent::GetTraceClockId()), timestamp.ts};
199   }
200 };
201 
202 }  // namespace perfetto
203 
204 namespace {
205 
206 using perfetto::TracingInitArgs;
207 using perfetto::internal::TrackEventIncrementalState;
208 using perfetto::internal::TrackEventInternal;
209 using ::perfetto::test::DataSourceInternalForTest;
210 using ::testing::_;
211 using ::testing::AllOf;
212 using ::testing::ContainerEq;
213 using ::testing::Contains;
214 using ::testing::Each;
215 using ::testing::ElementsAre;
216 using ::testing::HasSubstr;
217 using ::testing::Invoke;
218 using ::testing::InvokeWithoutArgs;
219 using ::testing::IsEmpty;
220 using ::testing::MockFunction;
221 using ::testing::NiceMock;
222 using ::testing::Not;
223 using ::testing::Property;
224 using ::testing::StrEq;
225 
226 // ------------------------------
227 // Declarations of helper classes
228 // ------------------------------
229 
230 class WaitableTestEvent {
231  public:
notified()232   bool notified() {
233     std::unique_lock<std::mutex> lock(mutex_);
234     return notified_;
235   }
236 
Wait()237   void Wait() {
238     std::unique_lock<std::mutex> lock(mutex_);
239     // TSAN gets confused by wait_for, which we would use here in a perfect
240     // world.
241     cv_.wait(lock, [this] { return notified_; });
242   }
243 
Notify()244   void Notify() {
245     std::lock_guard<std::mutex> lock(mutex_);
246     notified_ = true;
247     cv_.notify_one();
248   }
249 
Reset()250   void Reset() {
251     std::lock_guard<std::mutex> lock(mutex_);
252     notified_ = false;
253     cv_.notify_one();
254   }
255 
256  private:
257   std::mutex mutex_;
258   std::condition_variable cv_;
259   bool notified_ = false;
260 };
261 
262 template <typename Func>
263 class Cleanup {
264  public:
Cleanup(Func f)265   explicit Cleanup(Func f) : f_(std::move(f)) {}
~Cleanup()266   ~Cleanup() { f_(); }
267   Cleanup(Cleanup&&) noexcept = default;
268   Cleanup& operator=(Cleanup&&) noexcept = default;
269   Cleanup(const Cleanup&) = delete;
270   Cleanup& operator=(const Cleanup&) = delete;
271 
272  private:
273   Func f_;
274 };
275 template <typename Func>
MakeCleanup(Func f)276 Cleanup<Func> MakeCleanup(Func f) {
277   return Cleanup<Func>(std::move(f));
278 }
279 
280 class CustomDataSource : public perfetto::DataSource<CustomDataSource> {};
281 
282 class MockDataSource;
283 
284 // We can't easily use gmock here because instances of data sources are lazily
285 // created by the service and are not owned by the test fixture.
286 struct TestDataSourceHandle {
287   WaitableTestEvent on_create;
288   WaitableTestEvent on_setup;
289   WaitableTestEvent on_start;
290   WaitableTestEvent on_stop;
291   WaitableTestEvent on_flush;
292   MockDataSource* instance;
293   perfetto::DataSourceConfig config;
294   bool is_datasource_started = false;
295   bool handle_stop_asynchronously = false;
296   bool handle_flush_asynchronously = false;
297   std::function<void()> on_start_callback;
298   std::function<void()> on_stop_callback;
299   std::function<void(perfetto::FlushFlags)> on_flush_callback;
300   std::function<void()> async_stop_closure;
301   std::function<void()> async_flush_closure;
302 };
303 
304 class MockDataSource : public perfetto::DataSource<MockDataSource> {
305  public:
306   void OnSetup(const SetupArgs&) override;
307   void OnStart(const StartArgs&) override;
308   void OnStop(const StopArgs&) override;
309   void OnFlush(const FlushArgs&) override;
310   TestDataSourceHandle* handle_ = nullptr;
311 };
312 
313 constexpr int kTestDataSourceArg = 123;
314 
315 class MockDataSource2 : public perfetto::DataSource<MockDataSource2> {
316  public:
MockDataSource2(int arg)317   MockDataSource2(int arg) { EXPECT_EQ(arg, kTestDataSourceArg); }
OnSetup(const SetupArgs &)318   void OnSetup(const SetupArgs&) override {}
OnStart(const StartArgs &)319   void OnStart(const StartArgs&) override {}
OnStop(const StopArgs &)320   void OnStop(const StopArgs&) override {}
321 };
322 
323 // Used to verify that track event data sources in different namespaces register
324 // themselves correctly in the muxer.
325 class MockTracingMuxer : public perfetto::internal::TracingMuxer {
326  public:
327   struct DataSource {
328     perfetto::DataSourceDescriptor dsd;
329     perfetto::internal::DataSourceStaticState* static_state;
330   };
331 
MockTracingMuxer()332   MockTracingMuxer() : TracingMuxer(nullptr), prev_instance_(instance_) {
333     instance_ = this;
334   }
~MockTracingMuxer()335   ~MockTracingMuxer() override { instance_ = prev_instance_; }
336 
RegisterDataSource(const perfetto::DataSourceDescriptor & dsd,DataSourceFactory,perfetto::internal::DataSourceParams,bool,perfetto::internal::DataSourceStaticState * static_state)337   bool RegisterDataSource(
338       const perfetto::DataSourceDescriptor& dsd,
339       DataSourceFactory,
340       perfetto::internal::DataSourceParams,
341       bool,
342       perfetto::internal::DataSourceStaticState* static_state) override {
343     data_sources.emplace_back(DataSource{dsd, static_state});
344     return true;
345   }
346 
UpdateDataSourceDescriptor(const perfetto::DataSourceDescriptor & dsd,const perfetto::internal::DataSourceStaticState * static_state)347   void UpdateDataSourceDescriptor(
348       const perfetto::DataSourceDescriptor& dsd,
349       const perfetto::internal::DataSourceStaticState* static_state) override {
350     for (auto& rds : data_sources) {
351       if (rds.static_state == static_state) {
352         rds.dsd = dsd;
353         return;
354       }
355     }
356   }
357 
CreateTraceWriter(perfetto::internal::DataSourceStaticState *,uint32_t,perfetto::internal::DataSourceState *,perfetto::BufferExhaustedPolicy)358   std::unique_ptr<perfetto::TraceWriterBase> CreateTraceWriter(
359       perfetto::internal::DataSourceStaticState*,
360       uint32_t,
361       perfetto::internal::DataSourceState*,
362       perfetto::BufferExhaustedPolicy) override {
363     return nullptr;
364   }
365 
DestroyStoppedTraceWritersForCurrentThread()366   void DestroyStoppedTraceWritersForCurrentThread() override {}
RegisterInterceptor(const perfetto::InterceptorDescriptor &,InterceptorFactory,perfetto::InterceptorBase::TLSFactory,perfetto::InterceptorBase::TracePacketCallback)367   void RegisterInterceptor(
368       const perfetto::InterceptorDescriptor&,
369       InterceptorFactory,
370       perfetto::InterceptorBase::TLSFactory,
371       perfetto::InterceptorBase::TracePacketCallback) override {}
372 
ActivateTriggers(const std::vector<std::string> &,uint32_t)373   void ActivateTriggers(const std::vector<std::string>&, uint32_t) override {}
374 
375   std::vector<DataSource> data_sources;
376 
377  private:
378   TracingMuxer* prev_instance_;
379 };
380 
381 struct TestIncrementalState {
TestIncrementalState__anonfc73210d0111::TestIncrementalState382   TestIncrementalState() { constructed = true; }
383   // Note: a virtual destructor is not required for incremental state.
~TestIncrementalState__anonfc73210d0111::TestIncrementalState384   ~TestIncrementalState() { destroyed = true; }
385 
386   int count = 100;
387   bool flag = false;
388   static bool constructed;
389   static bool destroyed;
390 };
391 
392 bool TestIncrementalState::constructed;
393 bool TestIncrementalState::destroyed;
394 
395 struct TestIncrementalDataSourceTraits
396     : public perfetto::DefaultDataSourceTraits {
397   using IncrementalStateType = TestIncrementalState;
398   using CustomTlsState = void;
399 };
400 
401 class TestIncrementalDataSource
402     : public perfetto::DataSource<TestIncrementalDataSource,
403                                   TestIncrementalDataSourceTraits> {
404  public:
OnSetup(const SetupArgs &)405   void OnSetup(const SetupArgs&) override {}
OnStart(const StartArgs &)406   void OnStart(const StartArgs&) override {}
OnStop(const StopArgs &)407   void OnStop(const StopArgs&) override {}
WillClearIncrementalState(const ClearIncrementalStateArgs & args)408   void WillClearIncrementalState(
409       const ClearIncrementalStateArgs& args) override {
410     if (will_clear_incremental_state) {
411       (*will_clear_incremental_state)(args);
412     }
413   }
414 
SetWillClearIncrementalStateCallback(std::function<void (const DataSourceBase::ClearIncrementalStateArgs &)> cb)415   static void SetWillClearIncrementalStateCallback(
416       std::function<void(const DataSourceBase::ClearIncrementalStateArgs&)> cb) {
417     if (will_clear_incremental_state) {
418       delete will_clear_incremental_state;
419       will_clear_incremental_state = nullptr;
420     }
421     if (cb) {
422       will_clear_incremental_state = new decltype(cb)(cb);
423     }
424   }
425 
426  private:
427   static std::function<void(const ClearIncrementalStateArgs&)>*
428       will_clear_incremental_state;
429 };
430 
431 std::function<void(const perfetto::DataSourceBase::ClearIncrementalStateArgs&)>*
432     TestIncrementalDataSource::will_clear_incremental_state;
433 
434 // A convenience wrapper around TracingSession that allows to do block on
435 //
436 struct TestTracingSessionHandle {
get__anonfc73210d0111::TestTracingSessionHandle437   perfetto::TracingSession* get() { return session.get(); }
438   std::unique_ptr<perfetto::TracingSession> session;
439   WaitableTestEvent on_stop;
440 };
441 
442 class MyDebugAnnotation : public perfetto::DebugAnnotation {
443  public:
444   ~MyDebugAnnotation() override = default;
445 
Add(perfetto::protos::pbzero::DebugAnnotation * annotation) const446   void Add(
447       perfetto::protos::pbzero::DebugAnnotation* annotation) const override {
448     annotation->set_legacy_json_value(R"({"key": 123})");
449   }
450 };
451 
452 class TestTracingPolicy : public perfetto::TracingPolicy {
453  public:
ShouldAllowConsumerSession(const ShouldAllowConsumerSessionArgs & args)454   void ShouldAllowConsumerSession(
455       const ShouldAllowConsumerSessionArgs& args) override {
456     EXPECT_NE(args.backend_type, perfetto::BackendType::kUnspecifiedBackend);
457     args.result_callback(should_allow_consumer_connection);
458   }
459 
460   bool should_allow_consumer_connection = true;
461 };
462 
463 TestTracingPolicy* g_test_tracing_policy = new TestTracingPolicy();  // Leaked.
464 
465 class ParsedIncrementalState {
466  public:
ClearIfNeeded(const perfetto::protos::gen::TracePacket & packet)467   void ClearIfNeeded(const perfetto::protos::gen::TracePacket& packet) {
468     if (packet.sequence_flags() &
469         perfetto::protos::pbzero::TracePacket::SEQ_INCREMENTAL_STATE_CLEARED) {
470       incremental_state_was_cleared_ = true;
471       categories_.clear();
472       event_names_.clear();
473       debug_annotation_names_.clear();
474       seen_tracks_.clear();
475     }
476   }
477 
Parse(const perfetto::protos::gen::TracePacket & packet)478   void Parse(const perfetto::protos::gen::TracePacket& packet) {
479     // Update incremental state.
480     if (packet.has_interned_data()) {
481       const auto& interned_data = packet.interned_data();
482       for (const auto& it : interned_data.event_categories()) {
483         EXPECT_EQ(categories_.find(it.iid()), categories_.end());
484         categories_[it.iid()] = it.name();
485       }
486       for (const auto& it : interned_data.event_names()) {
487         EXPECT_EQ(event_names_.find(it.iid()), event_names_.end());
488         event_names_[it.iid()] = it.name();
489       }
490       for (const auto& it : interned_data.debug_annotation_names()) {
491         EXPECT_EQ(debug_annotation_names_.find(it.iid()),
492                   debug_annotation_names_.end());
493         debug_annotation_names_[it.iid()] = it.name();
494       }
495     }
496   }
497 
HasSeenTrack(uint64_t uuid) const498   bool HasSeenTrack(uint64_t uuid) const {
499     return seen_tracks_.count(uuid) != 0;
500   }
501 
InsertTrack(uint64_t uuid)502   void InsertTrack(uint64_t uuid) { seen_tracks_.insert(uuid); }
503 
GetCategory(uint64_t iid)504   std::string GetCategory(uint64_t iid) { return categories_[iid]; }
505 
GetEventName(const perfetto::protos::gen::TrackEvent & event)506   std::string GetEventName(const perfetto::protos::gen::TrackEvent& event) {
507     if (event.has_name_iid())
508       return event_names_[event.name_iid()];
509     return event.name();
510   }
511 
GetDebugAnnotationName(uint64_t iid)512   std::string GetDebugAnnotationName(uint64_t iid) {
513     return debug_annotation_names_[iid];
514   }
515 
WasCleared() const516   bool WasCleared() const { return incremental_state_was_cleared_; }
517 
518  private:
519   bool incremental_state_was_cleared_ = false;
520   std::map<uint64_t, std::string> categories_;
521   std::map<uint64_t, std::string> event_names_;
522   std::map<uint64_t, std::string> debug_annotation_names_;
523   std::set<uint64_t> seen_tracks_;
524 };
525 
ReadSlicesFromTrace(const perfetto::protos::gen::Trace & parsed_trace,bool expect_incremental_state_cleared=true)526 std::vector<std::string> ReadSlicesFromTrace(
527     const perfetto::protos::gen::Trace& parsed_trace,
528     bool expect_incremental_state_cleared = true) {
529   // Read back the trace, maintaining interning tables as we go.
530   std::vector<std::string> slices;
531   if (parsed_trace.packet().size() == 0)
532     return slices;
533   ParsedIncrementalState incremental_state;
534 
535   uint32_t sequence_id = 0;
536   for (const auto& packet : parsed_trace.packet()) {
537     incremental_state.ClearIfNeeded(packet);
538 
539     if (packet.has_track_descriptor()) {
540       // Make sure we haven't seen any events on this track before the
541       // descriptor was written.
542       EXPECT_FALSE(
543           incremental_state.HasSeenTrack(packet.track_descriptor().uuid()));
544     }
545 
546     if (!packet.has_track_event())
547       continue;
548 
549     // Make sure we only see track events on one sequence.
550     if (packet.trusted_packet_sequence_id()) {
551       if (!sequence_id)
552         sequence_id = packet.trusted_packet_sequence_id();
553       EXPECT_EQ(sequence_id, packet.trusted_packet_sequence_id());
554     }
555 
556     incremental_state.Parse(packet);
557 
558     const auto& track_event = packet.track_event();
559     std::string slice;
560 
561     if (track_event.has_track_uuid()) {
562       incremental_state.InsertTrack(track_event.track_uuid());
563       std::stringstream track;
564       track << "[track=" << track_event.track_uuid() << "]";
565       slice += track.str();
566     }
567 
568     switch (track_event.type()) {
569       case perfetto::protos::gen::TrackEvent::TYPE_SLICE_BEGIN:
570         slice += "B";
571         break;
572       case perfetto::protos::gen::TrackEvent::TYPE_SLICE_END:
573         slice += "E";
574         break;
575       case perfetto::protos::gen::TrackEvent::TYPE_INSTANT:
576         slice += "I";
577         break;
578       case perfetto::protos::gen::TrackEvent::TYPE_UNSPECIFIED: {
579         EXPECT_TRUE(track_event.has_legacy_event());
580         EXPECT_FALSE(track_event.type());
581         auto legacy_event = track_event.legacy_event();
582         slice +=
583             "Legacy_" + std::string(1, static_cast<char>(legacy_event.phase()));
584         break;
585       }
586       case perfetto::protos::gen::TrackEvent::TYPE_COUNTER:
587         slice += "C";
588         break;
589       default:
590         ADD_FAILURE();
591     }
592     if (track_event.has_legacy_event()) {
593       auto legacy_event = track_event.legacy_event();
594       std::stringstream id;
595       if (legacy_event.has_unscoped_id()) {
596         id << "(unscoped_id=" << legacy_event.unscoped_id() << ")";
597       } else if (legacy_event.has_local_id()) {
598         id << "(local_id=" << legacy_event.local_id() << ")";
599       } else if (legacy_event.has_global_id()) {
600         id << "(global_id=" << legacy_event.global_id() << ")";
601       } else if (legacy_event.has_bind_id()) {
602         id << "(bind_id=" << legacy_event.bind_id() << ")";
603       }
604       if (legacy_event.has_id_scope())
605         id << "(id_scope=\"" << legacy_event.id_scope() << "\")";
606       if (legacy_event.use_async_tts())
607         id << "(use_async_tts)";
608       if (legacy_event.bind_to_enclosing())
609         id << "(bind_to_enclosing)";
610       if (legacy_event.has_flow_direction())
611         id << "(flow_direction=" << legacy_event.flow_direction() << ")";
612       if (legacy_event.has_pid_override())
613         id << "(pid_override=" << legacy_event.pid_override() << ")";
614       if (legacy_event.has_tid_override())
615         id << "(tid_override=" << legacy_event.tid_override() << ")";
616       slice += id.str();
617     }
618     size_t category_count = 0;
619     for (const auto& it : track_event.category_iids())
620       slice +=
621           (category_count++ ? "," : ":") + incremental_state.GetCategory(it);
622     for (const auto& it : track_event.categories())
623       slice += (category_count++ ? ",$" : ":$") + it;
624     if (track_event.has_name() || track_event.has_name_iid())
625       slice += "." + incremental_state.GetEventName(track_event);
626 
627     if (track_event.debug_annotations_size()) {
628       slice += "(";
629       bool first_annotation = true;
630       for (const auto& it : track_event.debug_annotations()) {
631         if (!first_annotation) {
632           slice += ",";
633         }
634         if (it.has_name_iid()) {
635           slice += incremental_state.GetDebugAnnotationName(it.name_iid());
636         } else {
637           slice += it.name();
638         }
639         slice += "=";
640         std::stringstream value;
641         if (it.has_bool_value()) {
642           value << "(bool)" << it.bool_value();
643         } else if (it.has_uint_value()) {
644           value << "(uint)" << it.uint_value();
645         } else if (it.has_int_value()) {
646           value << "(int)" << it.int_value();
647         } else if (it.has_double_value()) {
648           value << "(double)" << it.double_value();
649         } else if (it.has_string_value()) {
650           value << "(string)" << it.string_value();
651         } else if (it.has_pointer_value()) {
652           value << "(pointer)" << std::hex << it.pointer_value();
653         } else if (it.has_legacy_json_value()) {
654           value << "(json)" << it.legacy_json_value();
655         } else if (it.has_nested_value()) {
656           value << "(nested)" << it.nested_value().string_value();
657         }
658         slice += value.str();
659         first_annotation = false;
660       }
661       slice += ")";
662     }
663 
664     if (track_event.flow_ids_old_size()) {
665       slice += "(flow_ids_old=";
666       std::stringstream value;
667       bool first_annotation = true;
668       for (uint64_t id : track_event.flow_ids_old()) {
669         if (!first_annotation) {
670           value << ",";
671         }
672         first_annotation = false;
673         value << id;
674       }
675       slice += value.str() + ")";
676     }
677 
678     if (track_event.flow_ids_size()) {
679       slice += "(flow_ids=";
680       std::stringstream value;
681       bool first_annotation = true;
682       for (uint64_t id : track_event.flow_ids()) {
683         if (!first_annotation) {
684           value << ",";
685         }
686         first_annotation = false;
687         value << id;
688       }
689       slice += value.str() + ")";
690     }
691 
692     if (track_event.terminating_flow_ids_old_size()) {
693       slice += "(terminating_flow_ids_old=";
694       std::stringstream value;
695       bool first_annotation = true;
696       for (uint64_t id : track_event.terminating_flow_ids_old()) {
697         if (!first_annotation) {
698           value << ",";
699         }
700         value << id;
701         first_annotation = false;
702       }
703       slice += value.str() + ")";
704     }
705 
706     if (track_event.terminating_flow_ids_size()) {
707       slice += "(terminating_flow_ids=";
708       std::stringstream value;
709       bool first_annotation = true;
710       for (uint64_t id : track_event.terminating_flow_ids()) {
711         if (!first_annotation) {
712           value << ",";
713         }
714         value << id;
715         first_annotation = false;
716       }
717       slice += value.str() + ")";
718     }
719 
720     slices.push_back(slice);
721   }
722   if (expect_incremental_state_cleared) {
723     EXPECT_TRUE(incremental_state.WasCleared());
724   }
725   return slices;
726 }
727 
ReadSlicesFromTrace(const std::vector<char> & raw_trace,bool expect_incremental_state_cleared=true)728 std::vector<std::string> ReadSlicesFromTrace(
729     const std::vector<char>& raw_trace,
730     bool expect_incremental_state_cleared = true) {
731   EXPECT_GE(raw_trace.size(), 0u);
732 
733   perfetto::protos::gen::Trace parsed_trace;
734   EXPECT_TRUE(parsed_trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
735   return ReadSlicesFromTrace(parsed_trace, expect_incremental_state_cleared);
736 }
737 
WaitForOneProducerConnected(perfetto::TracingSession * session)738 bool WaitForOneProducerConnected(perfetto::TracingSession* session) {
739   for (size_t i = 0; i < 100; i++) {
740     // Blocking read.
741     auto result = session->QueryServiceStateBlocking();
742     perfetto::protos::gen::TracingServiceState state;
743     EXPECT_TRUE(result.success);
744     EXPECT_TRUE(state.ParseFromArray(result.service_state_data.data(),
745                                      result.service_state_data.size()));
746     // The producer has connected to the new restarted system service.
747     if (state.producers().size() == 1) {
748       return true;
749     }
750     std::this_thread::sleep_for(std::chrono::milliseconds(100));
751   }
752   ADD_FAILURE() << "Producer not connected";
753   return false;
754 }
755 
756 // -------------------------
757 // Declaration of test class
758 // -------------------------
759 class PerfettoApiTest : public ::testing::TestWithParam<perfetto::BackendType> {
760  public:
761   static PerfettoApiTest* instance;
762 
SetUp()763   void SetUp() override {
764     instance = this;
765     g_test_tracing_policy->should_allow_consumer_connection = true;
766 
767     // Start a fresh system service for this test, tearing down any previous
768     // service that was running.
769     if (GetParam() == perfetto::kSystemBackend) {
770       system_service_ = perfetto::test::SystemService::Start();
771       // If the system backend isn't supported, skip all system backend tests.
772       if (!system_service_.valid()) {
773         GTEST_SKIP();
774       }
775     }
776 
777     EXPECT_FALSE(perfetto::Tracing::IsInitialized());
778     TracingInitArgs args;
779     args.backends = GetParam();
780     args.tracing_policy = g_test_tracing_policy;
781     perfetto::Tracing::Initialize(args);
782     RegisterDataSource<MockDataSource>("my_data_source");
783     {
784       perfetto::DataSourceDescriptor dsd;
785       dsd.set_name("CustomDataSource");
786       CustomDataSource::Register(dsd);
787     }
788     perfetto::TrackEvent::Register();
789 
790     // Make sure our data source always has a valid handle.
791     data_sources_["my_data_source"];
792 
793     // If this wasn't the first test to run in this process, any producers
794     // connected to the old system service will have been disconnected by the
795     // service restarting above. Wait for all producers to connect again before
796     // proceeding with the test.
797     perfetto::test::SyncProducers();
798 
799     perfetto::test::DisableReconnectLimit();
800   }
801 
TearDown()802   void TearDown() override {
803     instance = nullptr;
804     sessions_.clear();
805     perfetto::test::TracingMuxerImplInternalsForTest::
806         ClearDataSourceTlsStateOnReset<MockDataSource>();
807     perfetto::test::TracingMuxerImplInternalsForTest::
808         ClearDataSourceTlsStateOnReset<CustomDataSource>();
809     perfetto::test::TracingMuxerImplInternalsForTest::
810         ClearDataSourceTlsStateOnReset<perfetto::TrackEvent>();
811     perfetto::Tracing::ResetForTesting();
812   }
813 
814   template <typename DerivedDataSource>
RegisterDataSource(std::string name)815   TestDataSourceHandle* RegisterDataSource(std::string name) {
816     perfetto::DataSourceDescriptor dsd;
817     dsd.set_name(name);
818     return RegisterDataSource<DerivedDataSource>(dsd);
819   }
820 
821   template <typename DerivedDataSource>
RegisterDataSource(const perfetto::DataSourceDescriptor & dsd)822   TestDataSourceHandle* RegisterDataSource(
823       const perfetto::DataSourceDescriptor& dsd) {
824     EXPECT_EQ(data_sources_.count(dsd.name()), 0u);
825     TestDataSourceHandle* handle = &data_sources_[dsd.name()];
826     DerivedDataSource::Register(dsd);
827     return handle;
828   }
829 
830   template <typename DerivedDataSource>
UpdateDataSource(const perfetto::DataSourceDescriptor & dsd)831   TestDataSourceHandle* UpdateDataSource(
832       const perfetto::DataSourceDescriptor& dsd) {
833     EXPECT_EQ(data_sources_.count(dsd.name()), 1u);
834     TestDataSourceHandle* handle = &data_sources_[dsd.name()];
835     DerivedDataSource::UpdateDescriptor(dsd);
836     return handle;
837   }
838 
NewTrace(const perfetto::TraceConfig & cfg,int fd=-1)839   TestTracingSessionHandle* NewTrace(const perfetto::TraceConfig& cfg,
840                                      int fd = -1) {
841     return NewTrace(cfg, /*backend_type=*/GetParam(), fd);
842   }
843 
NewTrace(const perfetto::TraceConfig & cfg,perfetto::BackendType backend_type,int fd=-1)844   TestTracingSessionHandle* NewTrace(const perfetto::TraceConfig& cfg,
845                                      perfetto::BackendType backend_type,
846                                      int fd = -1) {
847     sessions_.emplace_back();
848     TestTracingSessionHandle* handle = &sessions_.back();
849     handle->session = perfetto::Tracing::NewTrace(backend_type);
850     handle->session->SetOnStopCallback([handle] { handle->on_stop.Notify(); });
851     handle->session->Setup(cfg, fd);
852     return handle;
853   }
854 
NewTraceWithCategories(std::vector<std::string> categories,perfetto::protos::gen::TrackEventConfig te_cfg={},perfetto::TraceConfig cfg={})855   TestTracingSessionHandle* NewTraceWithCategories(
856       std::vector<std::string> categories,
857       perfetto::protos::gen::TrackEventConfig te_cfg = {},
858       perfetto::TraceConfig cfg = {}) {
859     cfg.set_duration_ms(500);
860     cfg.add_buffers()->set_size_kb(1024);
861     auto* ds_cfg = cfg.add_data_sources()->mutable_config();
862     ds_cfg->set_name("track_event");
863     te_cfg.add_disabled_categories("*");
864     for (const auto& category : categories)
865       te_cfg.add_enabled_categories(category);
866     ds_cfg->set_track_event_config_raw(te_cfg.SerializeAsString());
867 
868     return NewTrace(cfg);
869   }
870 
ReadLogMessagesFromTrace(perfetto::TracingSession * tracing_session)871   std::vector<std::string> ReadLogMessagesFromTrace(
872       perfetto::TracingSession* tracing_session) {
873     std::vector<char> raw_trace = tracing_session->ReadTraceBlocking();
874     EXPECT_GE(raw_trace.size(), 0u);
875 
876     // Read back the trace, maintaining interning tables as we go.
877     std::vector<std::string> log_messages;
878     std::map<uint64_t, std::string> log_message_bodies;
879     std::map<uint64_t, perfetto::protos::gen::SourceLocation> source_locations;
880     perfetto::protos::gen::Trace parsed_trace;
881     EXPECT_TRUE(
882         parsed_trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
883 
884     for (const auto& packet : parsed_trace.packet()) {
885       if (!packet.has_track_event())
886         continue;
887 
888       if (packet.has_interned_data()) {
889         const auto& interned_data = packet.interned_data();
890         for (const auto& it : interned_data.log_message_body()) {
891           EXPECT_GE(it.iid(), 1u);
892           EXPECT_EQ(log_message_bodies.find(it.iid()),
893                     log_message_bodies.end());
894           log_message_bodies[it.iid()] = it.body();
895         }
896         for (const auto& it : interned_data.source_locations()) {
897           EXPECT_GE(it.iid(), 1u);
898           EXPECT_EQ(source_locations.find(it.iid()), source_locations.end());
899           source_locations[it.iid()] = it;
900         }
901       }
902       const auto& track_event = packet.track_event();
903       if (track_event.type() !=
904           perfetto::protos::gen::TrackEvent::TYPE_SLICE_BEGIN)
905         continue;
906 
907       EXPECT_TRUE(track_event.has_log_message());
908       const auto& log = track_event.log_message();
909       if (log.source_location_iid()) {
910         std::stringstream msg;
911         const auto& source_location =
912             source_locations[log.source_location_iid()];
913         msg << source_location.function_name() << "("
914             << source_location.file_name() << ":"
915             << source_location.line_number()
916             << "): " << log_message_bodies[log.body_iid()];
917         log_messages.emplace_back(msg.str());
918       } else {
919         log_messages.emplace_back(log_message_bodies[log.body_iid()]);
920       }
921     }
922     return log_messages;
923   }
924 
ReadSlicesFromTraceSession(perfetto::TracingSession * tracing_session)925   std::vector<std::string> ReadSlicesFromTraceSession(
926       perfetto::TracingSession* tracing_session) {
927     return ReadSlicesFromTrace(tracing_session->ReadTraceBlocking());
928   }
929 
StopSessionAndReadSlicesFromTrace(TestTracingSessionHandle * tracing_session)930   std::vector<std::string> StopSessionAndReadSlicesFromTrace(
931       TestTracingSessionHandle* tracing_session) {
932     return ReadSlicesFromTrace(StopSessionAndReturnBytes(tracing_session));
933   }
934 
GetMainThreadPacketSequenceId(const perfetto::protos::gen::Trace & trace)935   uint32_t GetMainThreadPacketSequenceId(
936       const perfetto::protos::gen::Trace& trace) {
937     for (const auto& packet : trace.packet()) {
938       if (packet.has_track_descriptor() &&
939           packet.track_descriptor().thread().tid() ==
940               static_cast<int32_t>(perfetto::base::GetThreadId())) {
941         return packet.trusted_packet_sequence_id();
942       }
943     }
944     ADD_FAILURE() << "Main thread not found";
945     return 0;
946   }
947 
StopSessionAndReturnBytes(TestTracingSessionHandle * tracing_session)948   static std::vector<char> StopSessionAndReturnBytes(
949       TestTracingSessionHandle* tracing_session) {
950     perfetto::TrackEvent::Flush();
951     tracing_session->get()->StopBlocking();
952     return tracing_session->get()->ReadTraceBlocking();
953   }
954 
StopSessionAndReturnParsedTrace(TestTracingSessionHandle * tracing_session)955   static perfetto::protos::gen::Trace StopSessionAndReturnParsedTrace(
956       TestTracingSessionHandle* tracing_session) {
957     std::vector<char> raw_trace = StopSessionAndReturnBytes(tracing_session);
958     perfetto::protos::gen::Trace trace;
959     if (trace.ParseFromArray(raw_trace.data(), raw_trace.size())) {
960       return trace;
961     } else {
962       ADD_FAILURE() << "trace.ParseFromArray failed";
963       return perfetto::protos::gen::Trace();
964     }
965   }
966 
967   perfetto::test::SystemService system_service_;
968   std::map<std::string, TestDataSourceHandle> data_sources_;
969   std::list<TestTracingSessionHandle> sessions_;  // Needs stable pointers.
970 };
971 
972 // ---------------------------------------------
973 // Definitions for non-inlineable helper methods
974 // ---------------------------------------------
975 PerfettoApiTest* PerfettoApiTest::instance;
976 
OnSetup(const SetupArgs & args)977 void MockDataSource::OnSetup(const SetupArgs& args) {
978   EXPECT_EQ(handle_, nullptr);
979   auto it = PerfettoApiTest::instance->data_sources_.find(args.config->name());
980 
981   // We should not see an OnSetup for a data source that we didn't register
982   // before via PerfettoApiTest::RegisterDataSource().
983   EXPECT_NE(it, PerfettoApiTest::instance->data_sources_.end());
984   handle_ = &it->second;
985   handle_->config = *args.config;  // Deliberate copy.
986   handle_->on_setup.Notify();
987 }
988 
OnStart(const StartArgs &)989 void MockDataSource::OnStart(const StartArgs&) {
990   EXPECT_NE(handle_, nullptr);
991   EXPECT_FALSE(handle_->is_datasource_started);
992   handle_->is_datasource_started = true;
993   if (handle_->on_start_callback)
994     handle_->on_start_callback();
995   handle_->on_start.Notify();
996 }
997 
OnStop(const StopArgs & args)998 void MockDataSource::OnStop(const StopArgs& args) {
999   EXPECT_NE(handle_, nullptr);
1000   EXPECT_TRUE(handle_->is_datasource_started);
1001   handle_->is_datasource_started = false;
1002   if (handle_->handle_stop_asynchronously)
1003     handle_->async_stop_closure = args.HandleStopAsynchronously();
1004   if (handle_->on_stop_callback)
1005     handle_->on_stop_callback();
1006   handle_->on_stop.Notify();
1007 }
1008 
OnFlush(const FlushArgs & args)1009 void MockDataSource::OnFlush(const FlushArgs& args) {
1010   EXPECT_NE(handle_, nullptr);
1011   EXPECT_TRUE(handle_->is_datasource_started);
1012   if (handle_->handle_flush_asynchronously)
1013     handle_->async_flush_closure = args.HandleFlushAsynchronously();
1014   if (handle_->on_flush_callback) {
1015     handle_->on_flush_callback(args.flush_flags);
1016   }
1017   handle_->on_flush.Notify();
1018 }
1019 
1020 // -------------
1021 // Test fixtures
1022 // -------------
1023 
TEST_P(PerfettoApiTest,StartAndStopWithoutDataSources)1024 TEST_P(PerfettoApiTest, StartAndStopWithoutDataSources) {
1025   // Create a new trace session without any data sources configured.
1026   perfetto::TraceConfig cfg;
1027   cfg.add_buffers()->set_size_kb(1024);
1028   auto* tracing_session = NewTrace(cfg);
1029   // This should not timeout.
1030   tracing_session->get()->StartBlocking();
1031   tracing_session->get()->StopBlocking();
1032 }
1033 
1034 // Disabled by default because it leaks tracing sessions into subsequent tests,
1035 // which can result in the per-uid tracing session limit (5) to be hit in later
1036 // tests.
1037 // TODO(b/261493947): fix or remove.
TEST_P(PerfettoApiTest,DISABLED_TrackEventStartStopAndDestroy)1038 TEST_P(PerfettoApiTest, DISABLED_TrackEventStartStopAndDestroy) {
1039   // This test used to cause a use after free as the tracing session got
1040   // destroyed. It needed to be run approximately 2000 times to catch it so test
1041   // with --gtest_repeat=3000 (less if running under GDB).
1042 
1043   // Setup the trace config.
1044   perfetto::TraceConfig cfg;
1045   cfg.set_duration_ms(500);
1046   cfg.add_buffers()->set_size_kb(1024);
1047   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
1048   ds_cfg->set_name("track_event");
1049 
1050   // Create five new trace sessions.
1051   std::vector<std::unique_ptr<perfetto::TracingSession>> sessions;
1052   for (size_t i = 0; i < 5; ++i) {
1053     sessions.push_back(perfetto::Tracing::NewTrace(/*BackendType=*/GetParam()));
1054     sessions[i]->Setup(cfg);
1055     sessions[i]->Start();
1056     sessions[i]->Stop();
1057   }
1058 }
1059 
TEST_P(PerfettoApiTest,TrackEventStartStopAndStopBlocking)1060 TEST_P(PerfettoApiTest, TrackEventStartStopAndStopBlocking) {
1061   // This test used to cause a deadlock (due to StopBlocking() after the session
1062   // already stopped). This usually occurred within 1 or 2 runs of the test so
1063   // use --gtest_repeat=10
1064 
1065   // Setup the trace config.
1066   perfetto::TraceConfig cfg;
1067   cfg.set_duration_ms(500);
1068   cfg.add_buffers()->set_size_kb(1024);
1069   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
1070   ds_cfg->set_name("track_event");
1071 
1072   // Create five new trace sessions.
1073   std::vector<std::unique_ptr<perfetto::TracingSession>> sessions;
1074   for (size_t i = 0; i < 5; ++i) {
1075     sessions.push_back(perfetto::Tracing::NewTrace(/*BackendType=*/GetParam()));
1076     sessions[i]->Setup(cfg);
1077     sessions[i]->Start();
1078     sessions[i]->Stop();
1079   }
1080   for (auto& session : sessions) {
1081     session->StopBlocking();
1082   }
1083 }
1084 
TEST_P(PerfettoApiTest,ChangeTraceConfiguration)1085 TEST_P(PerfettoApiTest, ChangeTraceConfiguration) {
1086   // Setup the trace config.
1087   perfetto::TraceConfig trace_config;
1088   trace_config.set_duration_ms(2000);
1089   trace_config.add_buffers()->set_size_kb(1024);
1090   auto* data_source = trace_config.add_data_sources();
1091 
1092   // Configure track events with category "foo".
1093   auto* ds_cfg = data_source->mutable_config();
1094   ds_cfg->set_name("track_event");
1095   perfetto::protos::gen::TrackEventConfig te_cfg;
1096   te_cfg.add_disabled_categories("*");
1097   te_cfg.add_enabled_categories("foo");
1098   ds_cfg->set_track_event_config_raw(te_cfg.SerializeAsString());
1099 
1100   // Initially, exclude all producers (the client library's producer is named
1101   // after current process's name, which will not match
1102   // "all_producers_excluded").
1103   data_source->add_producer_name_filter("all_producers_excluded");
1104 
1105   auto* tracing_session = NewTrace(trace_config);
1106 
1107   tracing_session->get()->StartBlocking();
1108 
1109   // Emit a first trace event, this one should be filtered out due
1110   // to the mismatching producer name filter.
1111   TRACE_EVENT_BEGIN("foo", "EventFilteredOut");
1112   TRACE_EVENT_END("foo");
1113 
1114   // Remove the producer name filter by changing configs.
1115   data_source->clear_producer_name_filter();
1116   tracing_session->get()->ChangeTraceConfig(trace_config);
1117 
1118   // We don't have a blocking version of ChangeTraceConfig, because there is
1119   // currently no response to it from producers or the service. Instead, we sync
1120   // the consumer and producer IPC streams for this test, to ensure that the
1121   // producer_name_filter change has propagated.
1122   tracing_session->get()->GetTraceStatsBlocking();  // sync consumer stream.
1123   perfetto::test::SyncProducers();                  // sync producer stream.
1124 
1125   // Emit a second trace event, this one should be included because
1126   // the producer name filter was cleared.
1127   TRACE_EVENT_BEGIN("foo", "EventIncluded");
1128   TRACE_EVENT_END("foo");
1129 
1130   // Verify that only the second event is in the trace data.
1131   std::vector<char> raw_trace = StopSessionAndReturnBytes(tracing_session);
1132   std::string trace(raw_trace.data(), raw_trace.size());
1133   EXPECT_THAT(trace, Not(HasSubstr("EventFilteredOut")));
1134   EXPECT_THAT(trace, HasSubstr("EventIncluded"));
1135 }
1136 
1137 // This is a build-only regression test that checks you can have a track event
1138 // inside a template.
1139 template <typename T>
TestTrackEventInsideTemplate(T)1140 void TestTrackEventInsideTemplate(T) {
1141   TRACE_EVENT_BEGIN("cat", "Name");
1142 }
1143 
1144 // This is a build-only regression test that checks you can specify the tracing
1145 // category as a template argument.
1146 constexpr const char kTestCategory[] = "foo";
1147 template <const char* category>
TestCategoryAsTemplateParameter()1148 void TestCategoryAsTemplateParameter() {
1149   TRACE_EVENT_BEGIN(category, "Name");
1150 }
1151 
1152 // Sleep for |nano_seconds| in a way that this duration is counted in
1153 // thread_time. i.e. sleep without using OS's sleep method, which blocks the
1154 // thread and OS doesn't schedule it until expected wake-up-time.
SpinForThreadTimeNanos(int64_t nano_seconds)1155 void SpinForThreadTimeNanos(int64_t nano_seconds) {
1156   auto time_now = perfetto::base::GetThreadCPUTimeNs().count();
1157   auto goal_time = time_now + nano_seconds;
1158   while (perfetto::base::GetThreadCPUTimeNs().count() < goal_time) {
1159   }
1160 }
1161 
TEST_P(PerfettoApiTest,TrackEventTimestampUnitAbsolute)1162 TEST_P(PerfettoApiTest, TrackEventTimestampUnitAbsolute) {
1163   for (auto unit_multiplier : {1u, 1000u}) {
1164     perfetto::protos::gen::TrackEventConfig te_cfg;
1165     te_cfg.set_disable_incremental_timestamps(true);
1166     te_cfg.set_timestamp_unit_multiplier(unit_multiplier);
1167     auto* tracing_session = NewTraceWithCategories({"foo"}, te_cfg);
1168     tracing_session->get()->StartBlocking();
1169     int64_t t_before = static_cast<int64_t>(TrackEventInternal::GetTimeNs());
1170     TRACE_EVENT_BEGIN("foo", "Event1");
1171     SpinForThreadTimeNanos(1000000);
1172     TRACE_EVENT_BEGIN("foo", "Event2");
1173     SpinForThreadTimeNanos(1000000);
1174     TRACE_EVENT_BEGIN("foo", "Event3");
1175     int64_t t_after = static_cast<int64_t>(TrackEventInternal::GetTimeNs());
1176     auto trace = StopSessionAndReturnParsedTrace(tracing_session);
1177     std::unordered_map<std::string, int64_t> event_map;
1178     bool found_absolute_clock = false;
1179     for (const auto& packet : trace.packet()) {
1180       if (packet.has_interned_data()) {
1181         if (packet.interned_data().event_names().size() == 1) {
1182           auto& event_name = packet.interned_data().event_names()[0].name();
1183           event_map[event_name] = static_cast<int64_t>(packet.timestamp());
1184         }
1185       }
1186       if (packet.has_trace_packet_defaults()) {
1187         auto clock_id = packet.trace_packet_defaults().timestamp_clock_id();
1188         EXPECT_EQ(unit_multiplier == 1
1189                       ? static_cast<uint32_t>(TrackEventInternal::GetClockId())
1190                       : TrackEventIncrementalState::kClockIdAbsolute,
1191                   clock_id);
1192         if (packet.has_clock_snapshot()) {
1193           for (auto& clock : packet.clock_snapshot().clocks()) {
1194             if (clock.clock_id() ==
1195                 TrackEventIncrementalState::kClockIdAbsolute) {
1196               found_absolute_clock = true;
1197               EXPECT_EQ(unit_multiplier, clock.unit_multiplier_ns());
1198               EXPECT_FALSE(clock.is_incremental());
1199             }
1200           }
1201         }
1202       }
1203     }
1204 
1205     EXPECT_EQ((unit_multiplier == 1000), found_absolute_clock);
1206 
1207     auto e1_t = event_map.at("Event1");
1208     auto e2_t = event_map.at("Event2");
1209     auto e3_t = event_map.at("Event3");
1210 
1211     int64_t min_delta = 1000000 / unit_multiplier;
1212     int64_t max_delta = (t_after - t_before) / unit_multiplier;
1213 
1214     EXPECT_LE(t_before / unit_multiplier, e1_t);
1215     EXPECT_LE(e3_t, t_after / unit_multiplier);
1216 
1217     EXPECT_GE(e2_t - e1_t, min_delta);
1218     EXPECT_GE(e3_t - e2_t, min_delta);
1219 
1220     EXPECT_LE(e2_t - e1_t, max_delta);
1221     EXPECT_LE(e3_t - e2_t, max_delta);
1222   }
1223 }
1224 
TEST_P(PerfettoApiTest,TrackEventTimestampUnitIncremental)1225 TEST_P(PerfettoApiTest, TrackEventTimestampUnitIncremental) {
1226   for (auto unit_multiplier : {1u, 1000u}) {
1227     perfetto::protos::gen::TrackEventConfig te_cfg;
1228     te_cfg.set_enable_thread_time_sampling(true);
1229     te_cfg.set_timestamp_unit_multiplier(unit_multiplier);
1230     auto* tracing_session = NewTraceWithCategories({"foo"}, te_cfg);
1231     tracing_session->get()->StartBlocking();
1232     SpinForThreadTimeNanos(1000000);
1233     TRACE_EVENT_BEGIN("foo", "Event1");
1234     SpinForThreadTimeNanos(1000000);
1235     TRACE_EVENT_BEGIN("foo", "Event2");
1236     SpinForThreadTimeNanos(1000000);
1237     TRACE_EVENT_BEGIN("foo", "Event3");
1238     auto trace = StopSessionAndReturnParsedTrace(tracing_session);
1239     struct TimeInfo {
1240       int64_t timestamp;
1241       int64_t thread_time;
1242     };
1243     std::unordered_map<std::string, TimeInfo> event_map;
1244     for (const auto& packet : trace.packet()) {
1245       if (packet.has_interned_data()) {
1246         if (packet.interned_data().event_names().size() == 1) {
1247           auto& event_name = packet.interned_data().event_names()[0].name();
1248           if (packet.has_track_event() &&
1249               packet.track_event().extra_counter_values().size() > 0) {
1250             auto thread_time = packet.track_event().extra_counter_values()[0];
1251             event_map[event_name] = {static_cast<int64_t>(packet.timestamp()),
1252                                      thread_time};
1253           }
1254         }
1255       }
1256     }
1257     int min_delta = 1000 * (unit_multiplier == 1 ? 1000 : 1);
1258 
1259     EXPECT_EQ(0, event_map.at("Event1").timestamp);
1260     EXPECT_GT(event_map.at("Event2").timestamp, min_delta);
1261     EXPECT_GT(event_map.at("Event3").timestamp, min_delta);
1262 
1263     EXPECT_GT(event_map.at("Event2").thread_time, min_delta);
1264     EXPECT_GT(event_map.at("Event3").thread_time, min_delta);
1265   }
1266 }
1267 
1268 // Tests that we don't accumulate error when using incremental timestamps with
1269 // timestamp unit multiplier.
TEST_P(PerfettoApiTest,TrackEventTimestampIncrementalAccumulatedError)1270 TEST_P(PerfettoApiTest, TrackEventTimestampIncrementalAccumulatedError) {
1271   constexpr uint64_t kUnitMultiplier = 100000;
1272   constexpr uint64_t kNumberOfEvents = 1000;
1273   constexpr uint64_t kTimeBetweenEventsNs = 50000;
1274 
1275   perfetto::protos::gen::TrackEventConfig te_cfg;
1276   te_cfg.set_timestamp_unit_multiplier(kUnitMultiplier);
1277   auto* tracing_session = NewTraceWithCategories({"foo"}, te_cfg);
1278   tracing_session->get()->StartBlocking();
1279   auto start = perfetto::TrackEvent::GetTraceTimeNs();
1280   TRACE_EVENT_BEGIN("foo", "Start");
1281   for (uint64_t i = 0; i < kNumberOfEvents; ++i) {
1282     SpinForThreadTimeNanos(kTimeBetweenEventsNs);
1283     TRACE_EVENT_BEGIN("foo", "Event");
1284   }
1285   auto end = perfetto::TrackEvent::GetTraceTimeNs();
1286   auto trace = StopSessionAndReturnParsedTrace(tracing_session);
1287   uint64_t accumulated_timestamp = 0;
1288   for (const auto& packet : trace.packet()) {
1289     if (packet.has_track_event()) {
1290       accumulated_timestamp += packet.timestamp() * kUnitMultiplier;
1291     }
1292   }
1293 
1294   EXPECT_GE(accumulated_timestamp, kNumberOfEvents * kTimeBetweenEventsNs);
1295   EXPECT_LE(accumulated_timestamp, end - start);
1296 }
1297 
TEST_P(PerfettoApiTest,TrackEvent)1298 TEST_P(PerfettoApiTest, TrackEvent) {
1299   // Create a new trace session.
1300   auto* tracing_session = NewTraceWithCategories({"test"});
1301   tracing_session->get()->StartBlocking();
1302 
1303   // Emit one complete track event.
1304   TRACE_EVENT_BEGIN("test", "TestEvent");
1305   TRACE_EVENT_END("test");
1306   perfetto::TrackEvent::Flush();
1307 
1308   tracing_session->on_stop.Wait();
1309   std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
1310   ASSERT_GE(raw_trace.size(), 0u);
1311 
1312   // Read back the trace, maintaining interning tables as we go.
1313   perfetto::protos::gen::Trace trace;
1314   std::map<uint64_t, std::string> categories;
1315   std::map<uint64_t, std::string> event_names;
1316   ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
1317 
1318   auto now = perfetto::TrackEvent::GetTraceTimeNs();
1319 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE) && \
1320     !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
1321   auto clock_id = perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME;
1322 #else
1323   auto clock_id = perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC;
1324 #endif
1325   EXPECT_EQ(clock_id, perfetto::TrackEvent::GetTraceClockId());
1326 
1327   bool incremental_state_was_cleared = false;
1328   bool begin_found = false;
1329   bool end_found = false;
1330   bool process_descriptor_found = false;
1331   uint32_t sequence_id = 0;
1332   int32_t cur_pid = perfetto::test::GetCurrentProcessId();
1333   uint64_t recent_absolute_time_ns = 0;
1334   bool found_incremental_clock = false;
1335   constexpr auto kClockIdIncremental =
1336       TrackEventIncrementalState::kClockIdIncremental;
1337 
1338   for (const auto& packet : trace.packet()) {
1339     if (packet.has_track_descriptor()) {
1340       const auto& desc = packet.track_descriptor();
1341       if (desc.has_process()) {
1342         EXPECT_FALSE(process_descriptor_found);
1343         const auto& pd = desc.process();
1344         EXPECT_EQ(cur_pid, pd.pid());
1345         process_descriptor_found = true;
1346       }
1347     }
1348     if (packet.sequence_flags() &
1349         perfetto::protos::pbzero::TracePacket::SEQ_INCREMENTAL_STATE_CLEARED) {
1350       EXPECT_TRUE(packet.has_trace_packet_defaults());
1351       incremental_state_was_cleared = true;
1352       categories.clear();
1353       event_names.clear();
1354       EXPECT_EQ(kClockIdIncremental,
1355                 packet.trace_packet_defaults().timestamp_clock_id());
1356     }
1357     if (packet.has_clock_snapshot()) {
1358       for (auto& clock : packet.clock_snapshot().clocks()) {
1359         if (clock.is_incremental()) {
1360           found_incremental_clock = true;
1361           recent_absolute_time_ns = clock.timestamp();
1362           EXPECT_EQ(kClockIdIncremental, clock.clock_id());
1363         }
1364       }
1365     }
1366 
1367     if (!packet.has_track_event())
1368       continue;
1369     EXPECT_TRUE(
1370         packet.sequence_flags() &
1371         (perfetto::protos::pbzero::TracePacket::SEQ_INCREMENTAL_STATE_CLEARED |
1372          perfetto::protos::pbzero::TracePacket::SEQ_NEEDS_INCREMENTAL_STATE));
1373     const auto& track_event = packet.track_event();
1374 
1375     // Make sure we only see track events on one sequence.
1376     if (packet.trusted_packet_sequence_id()) {
1377       if (!sequence_id)
1378         sequence_id = packet.trusted_packet_sequence_id();
1379       EXPECT_EQ(sequence_id, packet.trusted_packet_sequence_id());
1380     }
1381 
1382     // Update incremental state.
1383     if (packet.has_interned_data()) {
1384       const auto& interned_data = packet.interned_data();
1385       for (const auto& it : interned_data.event_categories()) {
1386         EXPECT_EQ(categories.find(it.iid()), categories.end());
1387         categories[it.iid()] = it.name();
1388       }
1389       for (const auto& it : interned_data.event_names()) {
1390         EXPECT_EQ(event_names.find(it.iid()), event_names.end());
1391         event_names[it.iid()] = it.name();
1392       }
1393     }
1394     EXPECT_TRUE(found_incremental_clock);
1395     uint64_t absolute_timestamp = packet.timestamp() + recent_absolute_time_ns;
1396     recent_absolute_time_ns = absolute_timestamp;
1397     EXPECT_GT(absolute_timestamp, 0u);
1398     EXPECT_LE(absolute_timestamp, now);
1399     // Packet uses default (incremental) clock.
1400     EXPECT_FALSE(packet.has_timestamp_clock_id());
1401     if (track_event.type() ==
1402         perfetto::protos::gen::TrackEvent::TYPE_SLICE_BEGIN) {
1403       EXPECT_FALSE(begin_found);
1404       EXPECT_EQ(track_event.category_iids().size(), 1u);
1405       EXPECT_GE(track_event.category_iids()[0], 1u);
1406       EXPECT_EQ("test", categories[track_event.category_iids()[0]]);
1407       EXPECT_EQ("TestEvent", event_names[track_event.name_iid()]);
1408       begin_found = true;
1409     } else if (track_event.type() ==
1410                perfetto::protos::gen::TrackEvent::TYPE_SLICE_END) {
1411       EXPECT_FALSE(end_found);
1412       EXPECT_EQ(track_event.category_iids().size(), 0u);
1413       EXPECT_EQ(0u, track_event.name_iid());
1414       end_found = true;
1415     }
1416   }
1417   EXPECT_TRUE(incremental_state_was_cleared);
1418   EXPECT_TRUE(process_descriptor_found);
1419   EXPECT_TRUE(begin_found);
1420   EXPECT_TRUE(end_found);
1421 
1422   // Dummy instantiation of test templates.
1423   TestTrackEventInsideTemplate(true);
1424   TestCategoryAsTemplateParameter<kTestCategory>();
1425 }
1426 
TEST_P(PerfettoApiTest,TrackEventWithIncrementalTimestamp)1427 TEST_P(PerfettoApiTest, TrackEventWithIncrementalTimestamp) {
1428   for (auto disable_incremental_timestamps : {false, true}) {
1429     // Create a new trace session.
1430     perfetto::protos::gen::TrackEventConfig te_cfg;
1431     te_cfg.set_disable_incremental_timestamps(disable_incremental_timestamps);
1432     auto* tracing_session = NewTraceWithCategories({"bar"}, te_cfg);
1433     constexpr auto kClockIdIncremental =
1434         TrackEventIncrementalState::kClockIdIncremental;
1435     tracing_session->get()->StartBlocking();
1436 
1437     std::map<uint64_t, std::string> event_names;
1438 
1439     auto empty_lambda = [](perfetto::EventContext) {};
1440 
1441     constexpr uint64_t kInstantEvent1Time = 92718891479583;
1442     TRACE_EVENT_INSTANT(
1443         "bar", "InstantEvent1",
1444         perfetto::TraceTimestamp{kClockIdIncremental, kInstantEvent1Time},
1445         empty_lambda);
1446 
1447     constexpr uint64_t kInstantEvent2Time = 92718891618959;
1448     TRACE_EVENT_INSTANT(
1449         "bar", "InstantEvent2",
1450         perfetto::TraceTimestamp{kClockIdIncremental, kInstantEvent2Time},
1451         empty_lambda);
1452 
1453     auto trace = StopSessionAndReturnParsedTrace(tracing_session);
1454     uint64_t absolute_timestamp = 0;
1455     uint64_t prv_timestamp = 0;
1456     int event_count = 0;
1457     // Go through the packets and add the timestamps of those packets that use
1458     // the incremental clock - in order to get the absolute timestamps of the
1459     // track events.
1460 
1461     uint64_t default_clock_id = 0;
1462     bool is_incremental = false;
1463 
1464     for (const auto& packet : trace.packet()) {
1465       if (!packet.has_track_event() && !packet.has_clock_snapshot())
1466         continue;
1467       if (packet.has_trace_packet_defaults()) {
1468         auto& defaults = packet.trace_packet_defaults();
1469         if (defaults.has_timestamp_clock_id()) {
1470           default_clock_id = defaults.timestamp_clock_id();
1471         }
1472       }
1473       if (packet.has_clock_snapshot()) {
1474         for (auto& clock : packet.clock_snapshot().clocks()) {
1475           if (clock.is_incremental()) {
1476             is_incremental = true;
1477             absolute_timestamp = clock.timestamp();
1478             EXPECT_EQ(clock.clock_id(), kClockIdIncremental);
1479             EXPECT_FALSE(disable_incremental_timestamps);
1480           }
1481         }
1482       } else {
1483         auto clock_id = packet.has_timestamp_clock_id()
1484                             ? packet.timestamp_clock_id()
1485                             : default_clock_id;
1486         if (clock_id == kClockIdIncremental) {
1487           absolute_timestamp = prv_timestamp + packet.timestamp();
1488           EXPECT_FALSE(disable_incremental_timestamps);
1489         } else {
1490           absolute_timestamp = packet.timestamp();
1491           EXPECT_TRUE(disable_incremental_timestamps);
1492         }
1493       }
1494       prv_timestamp = absolute_timestamp;
1495 
1496       if (packet.sequence_flags() & perfetto::protos::pbzero::TracePacket::
1497                                         SEQ_INCREMENTAL_STATE_CLEARED) {
1498         event_names.clear();
1499       }
1500 
1501       // Update incremental state.
1502       if (packet.has_interned_data()) {
1503         const auto& interned_data = packet.interned_data();
1504         for (const auto& it : interned_data.event_names()) {
1505           EXPECT_EQ(event_names.find(it.iid()), event_names.end());
1506           event_names[it.iid()] = it.name();
1507         }
1508       }
1509 
1510       if (event_names[packet.track_event().name_iid()] == "InstantEvent1") {
1511         event_count++;
1512         EXPECT_EQ(absolute_timestamp, kInstantEvent1Time);
1513       } else if (event_names[packet.track_event().name_iid()] ==
1514                  "InstantEvent2") {
1515         event_count++;
1516         EXPECT_EQ(absolute_timestamp, kInstantEvent2Time);
1517       }
1518     }
1519     EXPECT_NE(is_incremental, disable_incremental_timestamps);
1520     EXPECT_EQ(event_count, 2);
1521   }
1522 }
1523 
TEST_P(PerfettoApiTest,TrackEventCategories)1524 TEST_P(PerfettoApiTest, TrackEventCategories) {
1525   // Create a new trace session.
1526   auto* tracing_session = NewTraceWithCategories({"bar"});
1527   tracing_session->get()->StartBlocking();
1528 
1529   // Emit some track events.
1530   TRACE_EVENT_BEGIN("foo", "NotEnabled");
1531   TRACE_EVENT_END("foo");
1532   TRACE_EVENT_BEGIN("bar", "Enabled");
1533   TRACE_EVENT_END("bar");
1534 
1535   std::vector<char> raw_trace = StopSessionAndReturnBytes(tracing_session);
1536   std::string trace(raw_trace.data(), raw_trace.size());
1537   // TODO(skyostil): Come up with a nicer way to verify trace contents.
1538   EXPECT_THAT(trace, HasSubstr("Enabled"));
1539   EXPECT_THAT(trace, Not(HasSubstr("NotEnabled")));
1540 }
1541 
TEST_P(PerfettoApiTest,ClearIncrementalState)1542 TEST_P(PerfettoApiTest, ClearIncrementalState) {
1543   perfetto::DataSourceDescriptor dsd;
1544   dsd.set_name("incr_data_source");
1545   TestIncrementalDataSource::Register(dsd);
1546   perfetto::test::SyncProducers();
1547 
1548   // Setup the trace config with an incremental state clearing period.
1549   perfetto::TraceConfig cfg;
1550   cfg.set_duration_ms(500);
1551   cfg.add_buffers()->set_size_kb(1024);
1552   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
1553   ds_cfg->set_name("incr_data_source");
1554   auto* is_cfg = cfg.mutable_incremental_state_config();
1555   is_cfg->set_clear_period_ms(10);
1556 
1557   // Create a new trace session.
1558   auto* tracing_session = NewTrace(cfg);
1559   tracing_session->get()->StartBlocking();
1560 
1561   // Observe at least 5 incremental state resets.
1562   constexpr size_t kMaxLoops = 100;
1563   size_t loops = 0;
1564   size_t times_cleared = 0;
1565   while (times_cleared < 5) {
1566     ASSERT_LT(loops++, kMaxLoops);
1567     TestIncrementalDataSource::Trace(
1568         [&](TestIncrementalDataSource::TraceContext ctx) {
1569           auto* incr_state = ctx.GetIncrementalState();
1570           if (!incr_state->flag) {
1571             incr_state->flag = true;
1572             times_cleared++;
1573           }
1574         });
1575     std::this_thread::sleep_for(std::chrono::milliseconds(10));
1576   }
1577   tracing_session->get()->StopBlocking();
1578   perfetto::test::TracingMuxerImplInternalsForTest::
1579       ClearDataSourceTlsStateOnReset<TestIncrementalDataSource>();
1580 }
1581 
TEST_P(PerfettoApiTest,ClearIncrementalStateMultipleInstances)1582 TEST_P(PerfettoApiTest, ClearIncrementalStateMultipleInstances) {
1583   perfetto::DataSourceDescriptor dsd;
1584   dsd.set_name("incr_data_source");
1585   TestIncrementalDataSource::Register(dsd);
1586   perfetto::test::SyncProducers();
1587 
1588   // Setup the trace config with an incremental state clearing period.
1589   perfetto::TraceConfig cfg;
1590   cfg.add_buffers()->set_size_kb(1024);
1591   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
1592   ds_cfg->set_name("incr_data_source");
1593 
1594   WaitableTestEvent cleared;
1595   NiceMock<MockFunction<void(const perfetto::DataSourceBase::ClearIncrementalStateArgs&)>> cb;
1596   ON_CALL(cb, Call). WillByDefault([&]{
1597     cleared.Notify();
1598   });
1599   TestIncrementalDataSource::SetWillClearIncrementalStateCallback(cb.AsStdFunction());
1600   auto cleanup = MakeCleanup([&] {
1601     TestIncrementalDataSource::SetWillClearIncrementalStateCallback({});
1602   });
1603 
1604   // Create a new trace session.
1605   auto* tracing_session = NewTrace(cfg);
1606   tracing_session->get()->StartBlocking();
1607 
1608   auto* is_cfg = cfg.mutable_incremental_state_config();
1609   is_cfg->set_clear_period_ms(10);
1610 
1611   // Create another tracing session that clear the incremental state
1612   // periodically.
1613   auto* tracing_session2 = NewTrace(cfg);
1614   tracing_session2->get()->StartBlocking();
1615 
1616   size_t count_instances = 0;
1617   TestIncrementalDataSource::Trace(
1618       [&](TestIncrementalDataSource::TraceContext ctx) {
1619         count_instances++;
1620         auto* incr_state = ctx.GetIncrementalState();
1621         if (!incr_state->flag) {
1622           incr_state->flag = true;
1623         }
1624       });
1625   ASSERT_EQ(count_instances, 2u);
1626 
1627   // Wait for two incremental state reset.
1628   cleared.Reset();
1629   cleared.Wait();
1630   cleared.Reset();
1631   cleared.Wait();
1632 
1633   std::vector<bool> instances_incremental_states;
1634   TestIncrementalDataSource::Trace(
1635       [&](TestIncrementalDataSource::TraceContext ctx) {
1636         auto* incr_state = ctx.GetIncrementalState();
1637         instances_incremental_states.push_back(incr_state->flag);
1638       });
1639 
1640   // There are two instances.
1641   EXPECT_EQ(instances_incremental_states.size(), 2u);
1642   // One was cleared.
1643   EXPECT_THAT(instances_incremental_states, Contains(false));
1644   // The other one wasn't.
1645   EXPECT_THAT(instances_incremental_states, Contains(true));
1646 
1647   tracing_session->get()->StopBlocking();
1648   tracing_session2->get()->StopBlocking();
1649 
1650   perfetto::test::TracingMuxerImplInternalsForTest::
1651       ClearDataSourceTlsStateOnReset<TestIncrementalDataSource>();
1652 }
1653 
TEST_P(PerfettoApiTest,TrackEventRegistrationWithModule)1654 TEST_P(PerfettoApiTest, TrackEventRegistrationWithModule) {
1655   MockTracingMuxer muxer;
1656 
1657   // Each track event namespace registers its own data source.
1658   perfetto::TrackEvent::Register();
1659   EXPECT_EQ(1u, muxer.data_sources.size());
1660 
1661   tracing_module::InitializeCategories();
1662   EXPECT_EQ(3u, muxer.data_sources.size());
1663 
1664   // Both data sources have the same name but distinct static data (i.e.,
1665   // individual instance states).
1666   EXPECT_EQ("track_event", muxer.data_sources[0].dsd.name());
1667   EXPECT_EQ("track_event", muxer.data_sources[1].dsd.name());
1668   EXPECT_EQ("track_event", muxer.data_sources[2].dsd.name());
1669   EXPECT_NE(muxer.data_sources[0].static_state,
1670             muxer.data_sources[1].static_state);
1671   EXPECT_NE(muxer.data_sources[0].static_state,
1672             muxer.data_sources[2].static_state);
1673 }
1674 
TEST_P(PerfettoApiTest,TrackEventDescriptor)1675 TEST_P(PerfettoApiTest, TrackEventDescriptor) {
1676   MockTracingMuxer muxer;
1677 
1678   perfetto::TrackEvent::Register();
1679   EXPECT_EQ(1u, muxer.data_sources.size());
1680   EXPECT_EQ("track_event", muxer.data_sources[0].dsd.name());
1681 
1682   perfetto::protos::gen::TrackEventDescriptor desc;
1683   auto desc_raw = muxer.data_sources[0].dsd.track_event_descriptor_raw();
1684   EXPECT_TRUE(desc.ParseFromArray(desc_raw.data(), desc_raw.size()));
1685 
1686   // Check that the advertised categories match PERFETTO_DEFINE_CATEGORIES (see
1687   // above).
1688   EXPECT_EQ(7, desc.available_categories_size());
1689   EXPECT_EQ("test", desc.available_categories()[0].name());
1690   EXPECT_EQ("This is a test category",
1691             desc.available_categories()[0].description());
1692   EXPECT_EQ("tag", desc.available_categories()[0].tags()[0]);
1693   EXPECT_EQ("foo", desc.available_categories()[1].name());
1694   EXPECT_EQ("bar", desc.available_categories()[2].name());
1695   EXPECT_EQ("cat", desc.available_categories()[3].name());
1696   EXPECT_EQ("slow", desc.available_categories()[3].tags()[0]);
1697   EXPECT_EQ("cat.verbose", desc.available_categories()[4].name());
1698   EXPECT_EQ("debug", desc.available_categories()[4].tags()[0]);
1699   EXPECT_EQ("cat-with-dashes", desc.available_categories()[5].name());
1700   EXPECT_EQ("disabled-by-default-cat", desc.available_categories()[6].name());
1701   EXPECT_EQ("slow", desc.available_categories()[6].tags()[0]);
1702 }
1703 
TEST_P(PerfettoApiTest,TrackEventSharedIncrementalState)1704 TEST_P(PerfettoApiTest, TrackEventSharedIncrementalState) {
1705   tracing_module::InitializeCategories();
1706 
1707   // Setup the trace config.
1708   perfetto::TraceConfig cfg;
1709   cfg.set_duration_ms(500);
1710   cfg.add_buffers()->set_size_kb(1024);
1711   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
1712   ds_cfg->set_name("track_event");
1713   auto* tracing_session = NewTrace(cfg);
1714   tracing_session->get()->StartBlocking();
1715 
1716   perfetto::internal::TrackEventIncrementalState* main_state = nullptr;
1717   perfetto::TrackEvent::Trace(
1718       [&main_state](perfetto::TrackEvent::TraceContext ctx) {
1719         main_state = ctx.GetIncrementalState();
1720       });
1721   perfetto::internal::TrackEventIncrementalState* module_state =
1722       tracing_module::GetIncrementalState();
1723 
1724   // Both track event data sources should use the same incremental state (thanks
1725   // to sharing TLS).
1726   EXPECT_NE(nullptr, main_state);
1727   EXPECT_EQ(main_state, module_state);
1728   tracing_session->get()->StopBlocking();
1729 }
1730 
TEST_P(PerfettoApiTest,TrackEventCategoriesWithModule)1731 TEST_P(PerfettoApiTest, TrackEventCategoriesWithModule) {
1732   // Check that categories defined in two different category registries are
1733   // enabled and disabled correctly.
1734   tracing_module::InitializeCategories();
1735 
1736   // Create a new trace session. Only the "foo" category is enabled. It also
1737   // exists both locally and in the existing module.
1738   auto* tracing_session = NewTraceWithCategories({"foo"});
1739   tracing_session->get()->StartBlocking();
1740 
1741   // Emit some track events locally and from the test module.
1742   TRACE_EVENT_BEGIN("foo", "FooEventFromMain");
1743   TRACE_EVENT_END("foo");
1744   tracing_module::EmitTrackEvents();
1745   tracing_module::EmitTrackEvents2();
1746   TRACE_EVENT_BEGIN("bar", "DisabledEventFromMain");
1747   TRACE_EVENT_END("bar");
1748 
1749   std::vector<char> raw_trace = StopSessionAndReturnBytes(tracing_session);
1750   std::string trace(raw_trace.data(), raw_trace.size());
1751   EXPECT_THAT(trace, HasSubstr("FooEventFromMain"));
1752   EXPECT_THAT(trace, Not(HasSubstr("DisabledEventFromMain")));
1753   EXPECT_THAT(trace, HasSubstr("FooEventFromModule"));
1754   EXPECT_THAT(trace, Not(HasSubstr("DisabledEventFromModule")));
1755   EXPECT_THAT(trace, HasSubstr("FooEventFromModule2"));
1756   EXPECT_THAT(trace, Not(HasSubstr("DisabledEventFromModule2")));
1757 
1758   perfetto::protos::gen::Trace parsed_trace;
1759   ASSERT_TRUE(parsed_trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
1760 
1761   uint32_t sequence_id = 0;
1762   for (const auto& packet : parsed_trace.packet()) {
1763     if (!packet.has_track_event())
1764       continue;
1765 
1766     // Make sure we only see track events on one sequence. This means all track
1767     // event modules are sharing the same trace writer (by using the same TLS
1768     // index).
1769     if (packet.trusted_packet_sequence_id()) {
1770       if (!sequence_id)
1771         sequence_id = packet.trusted_packet_sequence_id();
1772       EXPECT_EQ(sequence_id, packet.trusted_packet_sequence_id());
1773     }
1774   }
1775 }
1776 
TEST_P(PerfettoApiTest,TrackEventNamespaces)1777 TEST_P(PerfettoApiTest, TrackEventNamespaces) {
1778   perfetto::TrackEvent::Register();
1779   other_ns::TrackEvent::Register();
1780   tracing_module::InitializeCategories();
1781 
1782   auto* tracing_session =
1783       NewTraceWithCategories({"test", "cat1", "extra", "other_ns"});
1784   tracing_session->get()->StartBlocking();
1785 
1786   // Default namespace.
1787   TRACE_EVENT_INSTANT("test", "MainNamespaceEvent");
1788   EXPECT_TRUE(TRACE_EVENT_CATEGORY_ENABLED("test"));
1789 
1790   // Other namespace in a block scope.
1791   {
1792     PERFETTO_USE_CATEGORIES_FROM_NAMESPACE_SCOPED(other_ns);
1793     TRACE_EVENT_INSTANT("other_ns", "OtherNamespaceEvent");
1794     EXPECT_TRUE(TRACE_EVENT_CATEGORY_ENABLED("other_ns"));
1795   }
1796 
1797   // Back to the default namespace.
1798   TRACE_EVENT_INSTANT("test", "MainNamespaceEvent2");
1799 
1800   // More namespaces defined in another module.
1801   tracing_module::EmitTrackEventsFromAllNamespaces();
1802 
1803   auto slices = StopSessionAndReadSlicesFromTrace(tracing_session);
1804   EXPECT_THAT(
1805       slices,
1806       ElementsAre("I:test.MainNamespaceEvent", "I:other_ns.OtherNamespaceEvent",
1807                   "I:test.MainNamespaceEvent2",
1808                   "B:cat1.DefaultNamespaceFromModule",
1809                   "B:extra.ExtraNamespaceFromModule",
1810                   "B:extra.OverrideNamespaceFromModule",
1811                   "B:extra.DefaultNamespace", "B:cat1.DefaultNamespace"));
1812 }
1813 
TEST_P(PerfettoApiTest,TrackEventDynamicCategories)1814 TEST_P(PerfettoApiTest, TrackEventDynamicCategories) {
1815   // Setup the trace config.
1816   perfetto::TraceConfig cfg;
1817   cfg.set_duration_ms(500);
1818   cfg.add_buffers()->set_size_kb(1024);
1819   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
1820   ds_cfg->set_name("track_event");
1821 
1822   // Session #1 enabled the "dynamic" category.
1823   auto* tracing_session = NewTraceWithCategories({"dynamic"});
1824   tracing_session->get()->StartBlocking();
1825 
1826   EXPECT_TRUE(TRACE_EVENT_CATEGORY_ENABLED("dynamic"));
1827   EXPECT_FALSE(TRACE_EVENT_CATEGORY_ENABLED("dynamic_2"));
1828 
1829   // Session #2 enables "dynamic_2".
1830   auto* tracing_session2 = NewTraceWithCategories({"dynamic_2"});
1831   tracing_session2->get()->StartBlocking();
1832 
1833   // Test naming dynamic categories with std::string.
1834   perfetto::DynamicCategory dynamic{"dynamic"};
1835   TRACE_EVENT_BEGIN(dynamic, "EventInDynamicCategory");
1836   perfetto::DynamicCategory dynamic_disabled{"dynamic_disabled"};
1837   TRACE_EVENT_BEGIN(dynamic_disabled, "EventInDisabledDynamicCategory");
1838 
1839   // Test naming dynamic categories statically.
1840   TRACE_EVENT_BEGIN("dynamic", "EventInStaticallyNamedDynamicCategory");
1841 
1842   perfetto::DynamicCategory dynamic_2{"dynamic_2"};
1843   TRACE_EVENT_BEGIN(dynamic_2, "EventInSecondDynamicCategory");
1844   TRACE_EVENT_BEGIN("dynamic_2", "EventInSecondStaticallyNamedDynamicCategory");
1845 
1846   EXPECT_TRUE(TRACE_EVENT_CATEGORY_ENABLED(dynamic));
1847   EXPECT_TRUE(TRACE_EVENT_CATEGORY_ENABLED(dynamic_2));
1848 
1849   std::thread thread([] {
1850     // Make sure the category name can actually be computed at runtime.
1851     std::string name = "dyn";
1852     if (perfetto::base::GetThreadId())
1853       name += "amic";
1854     perfetto::DynamicCategory cat{name};
1855     TRACE_EVENT_BEGIN(cat, "DynamicFromOtherThread");
1856     perfetto::DynamicCategory cat2{"dynamic_disabled"};
1857     TRACE_EVENT_BEGIN(cat2, "EventInDisabledDynamicCategory");
1858   });
1859   thread.join();
1860 
1861   std::vector<char> raw_trace = StopSessionAndReturnBytes(tracing_session);
1862   std::string trace(raw_trace.data(), raw_trace.size());
1863   EXPECT_THAT(trace, HasSubstr("EventInDynamicCategory"));
1864   EXPECT_THAT(trace, Not(HasSubstr("EventInDisabledDynamicCategory")));
1865   EXPECT_THAT(trace, HasSubstr("DynamicFromOtherThread"));
1866   EXPECT_THAT(trace, Not(HasSubstr("EventInSecondDynamicCategory")));
1867   EXPECT_THAT(trace, HasSubstr("EventInStaticallyNamedDynamicCategory"));
1868   EXPECT_THAT(trace,
1869               Not(HasSubstr("EventInSecondStaticallyNamedDynamicCategory")));
1870 
1871   raw_trace = StopSessionAndReturnBytes(tracing_session2);
1872   trace = std::string(raw_trace.data(), raw_trace.size());
1873   EXPECT_THAT(trace, Not(HasSubstr("EventInDynamicCategory")));
1874   EXPECT_THAT(trace, Not(HasSubstr("EventInDisabledDynamicCategory")));
1875   EXPECT_THAT(trace, Not(HasSubstr("DynamicFromOtherThread")));
1876   EXPECT_THAT(trace, HasSubstr("EventInSecondDynamicCategory"));
1877   EXPECT_THAT(trace, Not(HasSubstr("EventInStaticallyNamedDynamicCategory")));
1878   EXPECT_THAT(trace, HasSubstr("EventInSecondStaticallyNamedDynamicCategory"));
1879 }
1880 
TEST_P(PerfettoApiTest,TrackEventConcurrentSessions)1881 TEST_P(PerfettoApiTest, TrackEventConcurrentSessions) {
1882   // Check that categories that are enabled and disabled in two parallel tracing
1883   // sessions don't interfere.
1884 
1885   // Session #1 enables the "foo" category.
1886   auto* tracing_session = NewTraceWithCategories({"foo"});
1887   tracing_session->get()->StartBlocking();
1888 
1889   // Session #2 enables the "bar" category.
1890   auto* tracing_session2 = NewTraceWithCategories({"bar"});
1891   tracing_session2->get()->StartBlocking();
1892 
1893   // Emit some track events under both categories.
1894   TRACE_EVENT_BEGIN("foo", "Session1_First");
1895   TRACE_EVENT_END("foo");
1896   TRACE_EVENT_BEGIN("bar", "Session2_First");
1897   TRACE_EVENT_END("bar");
1898 
1899   tracing_session->get()->StopBlocking();
1900   TRACE_EVENT_BEGIN("foo", "Session1_Second");
1901   TRACE_EVENT_END("foo");
1902   TRACE_EVENT_BEGIN("bar", "Session2_Second");
1903   TRACE_EVENT_END("bar");
1904 
1905   tracing_session2->get()->StopBlocking();
1906   TRACE_EVENT_BEGIN("foo", "Session1_Third");
1907   TRACE_EVENT_END("foo");
1908   TRACE_EVENT_BEGIN("bar", "Session2_Third");
1909   TRACE_EVENT_END("bar");
1910 
1911   std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
1912   std::string trace(raw_trace.data(), raw_trace.size());
1913   EXPECT_THAT(trace, HasSubstr("Session1_First"));
1914   EXPECT_THAT(trace, Not(HasSubstr("Session1_Second")));
1915   EXPECT_THAT(trace, Not(HasSubstr("Session1_Third")));
1916   EXPECT_THAT(trace, Not(HasSubstr("Session2_First")));
1917   EXPECT_THAT(trace, Not(HasSubstr("Session2_Second")));
1918   EXPECT_THAT(trace, Not(HasSubstr("Session2_Third")));
1919 
1920   std::vector<char> raw_trace2 = tracing_session2->get()->ReadTraceBlocking();
1921   std::string trace2(raw_trace2.data(), raw_trace2.size());
1922   EXPECT_THAT(trace2, Not(HasSubstr("Session1_First")));
1923   EXPECT_THAT(trace2, Not(HasSubstr("Session1_Second")));
1924   EXPECT_THAT(trace2, Not(HasSubstr("Session1_Third")));
1925   EXPECT_THAT(trace2, HasSubstr("Session2_First"));
1926   EXPECT_THAT(trace2, HasSubstr("Session2_Second"));
1927   EXPECT_THAT(trace2, Not(HasSubstr("Session2_Third")));
1928 }
1929 
TEST_P(PerfettoApiTest,TrackEventProcessAndThreadDescriptors)1930 TEST_P(PerfettoApiTest, TrackEventProcessAndThreadDescriptors) {
1931   // Thread and process descriptors can be set before tracing is enabled.
1932   {
1933     auto track = perfetto::ProcessTrack::Current();
1934     auto desc = track.Serialize();
1935     desc.set_name("hello.exe");
1936     desc.mutable_chrome_process()->set_process_priority(1);
1937     perfetto::TrackEvent::SetTrackDescriptor(track, std::move(desc));
1938   }
1939 
1940   // Erased tracks shouldn't show up anywhere.
1941   {
1942     perfetto::Track erased(1234u);
1943     auto desc = erased.Serialize();
1944     desc.set_name("ErasedTrack");
1945     perfetto::TrackEvent::SetTrackDescriptor(erased, std::move(desc));
1946     perfetto::TrackEvent::EraseTrackDescriptor(erased);
1947   }
1948 
1949   // Setup the trace config.
1950   perfetto::TraceConfig cfg;
1951   cfg.set_duration_ms(500);
1952   cfg.add_buffers()->set_size_kb(1024);
1953   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
1954   ds_cfg->set_name("track_event");
1955 
1956   // Create a new trace session.
1957   auto* tracing_session = NewTrace(cfg);
1958   tracing_session->get()->StartBlocking();
1959   TRACE_EVENT_INSTANT("test", "MainThreadEvent");
1960 
1961   std::thread thread([&] {
1962     auto track = perfetto::ThreadTrack::Current();
1963     auto desc = track.Serialize();
1964     desc.set_name("TestThread");
1965     perfetto::TrackEvent::SetTrackDescriptor(track, std::move(desc));
1966     TRACE_EVENT_INSTANT("test", "ThreadEvent");
1967   });
1968   thread.join();
1969 
1970   // Update the process descriptor while tracing is enabled. It should be
1971   // immediately reflected in the trace.
1972   {
1973     auto track = perfetto::ProcessTrack::Current();
1974     auto desc = track.Serialize();
1975     desc.set_name("goodbye.exe");
1976     perfetto::TrackEvent::SetTrackDescriptor(track, std::move(desc));
1977     perfetto::TrackEvent::Flush();
1978   }
1979 
1980   tracing_session->get()->StopBlocking();
1981 
1982   // After tracing ends, setting the descriptor has no immediate effect.
1983   {
1984     auto track = perfetto::ProcessTrack::Current();
1985     auto desc = track.Serialize();
1986     desc.set_name("noop.exe");
1987     perfetto::TrackEvent::SetTrackDescriptor(track, std::move(desc));
1988   }
1989 
1990   std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
1991   perfetto::protos::gen::Trace trace;
1992   ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
1993 
1994   std::vector<perfetto::protos::gen::TrackDescriptor> descs;
1995   std::vector<perfetto::protos::gen::TrackDescriptor> thread_descs;
1996   uint32_t main_thread_sequence = GetMainThreadPacketSequenceId(trace);
1997   for (const auto& packet : trace.packet()) {
1998     if (packet.has_track_descriptor()) {
1999       if (packet.trusted_packet_sequence_id() == main_thread_sequence) {
2000         descs.push_back(packet.track_descriptor());
2001       } else if (packet.track_descriptor().has_thread()) {
2002         thread_descs.push_back(packet.track_descriptor());
2003       }
2004     }
2005   }
2006 
2007   // The main thread records the initial process name as well as the one that's
2008   // set during tracing. Additionally it records a thread descriptor for the
2009   // main thread.
2010 
2011   EXPECT_EQ(3u, descs.size());
2012 
2013   // Default track for the main thread.
2014   EXPECT_EQ(0, descs[0].process().pid());
2015   EXPECT_NE(0, descs[0].thread().pid());
2016 
2017   // First process descriptor.
2018   EXPECT_NE(0, descs[1].process().pid());
2019   EXPECT_EQ("hello.exe", descs[1].name());
2020 
2021   // Second process descriptor.
2022   EXPECT_NE(0, descs[2].process().pid());
2023   EXPECT_EQ("goodbye.exe", descs[2].name());
2024 
2025   // The child thread records only its own thread descriptor (twice, since it
2026   // was mutated).
2027   ASSERT_EQ(2u, thread_descs.size());
2028   EXPECT_EQ("TestThread", thread_descs[0].name());
2029   EXPECT_NE(0, thread_descs[0].thread().pid());
2030   EXPECT_NE(0, thread_descs[0].thread().tid());
2031   EXPECT_EQ("TestThread", thread_descs[1].name());
2032   EXPECT_NE(0, thread_descs[1].thread().pid());
2033   EXPECT_NE(0, thread_descs[1].thread().tid());
2034   EXPECT_NE(0, descs[2].process().pid());
2035   EXPECT_EQ("goodbye.exe", descs[2].name());
2036 }
2037 
TEST_P(PerfettoApiTest,CustomTrackDescriptor)2038 TEST_P(PerfettoApiTest, CustomTrackDescriptor) {
2039   // Setup the trace config.
2040   perfetto::TraceConfig cfg;
2041   cfg.set_duration_ms(500);
2042   cfg.add_buffers()->set_size_kb(1024);
2043   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
2044   ds_cfg->set_name("track_event");
2045 
2046   // Create a new trace session.
2047   auto* tracing_session = NewTrace(cfg);
2048   tracing_session->get()->StartBlocking();
2049 
2050   auto track = perfetto::ProcessTrack::Current();
2051   auto desc = track.Serialize();
2052   desc.mutable_process()->set_process_name("testing.exe");
2053   desc.mutable_thread()->set_tid(
2054       static_cast<int32_t>(perfetto::base::GetThreadId()));
2055   desc.mutable_chrome_process()->set_process_priority(123);
2056   perfetto::TrackEvent::SetTrackDescriptor(track, std::move(desc));
2057 
2058   auto trace = StopSessionAndReturnParsedTrace(tracing_session);
2059 
2060   uint32_t main_thread_sequence = GetMainThreadPacketSequenceId(trace);
2061   bool found_desc = false;
2062   for (const auto& packet : trace.packet()) {
2063     if (packet.trusted_packet_sequence_id() != main_thread_sequence)
2064       continue;
2065     if (packet.has_track_descriptor()) {
2066       auto td = packet.track_descriptor();
2067       if (!td.has_process())
2068         continue;
2069       EXPECT_NE(0, td.process().pid());
2070       EXPECT_TRUE(td.has_chrome_process());
2071       EXPECT_EQ("testing.exe", td.process().process_name());
2072       EXPECT_EQ(123, td.chrome_process().process_priority());
2073       found_desc = true;
2074     }
2075   }
2076   EXPECT_TRUE(found_desc);
2077 }
2078 
TEST_P(PerfettoApiTest,TrackEventCustomTrack)2079 TEST_P(PerfettoApiTest, TrackEventCustomTrack) {
2080   // Create a new trace session.
2081   auto* tracing_session = NewTraceWithCategories({"bar"});
2082   tracing_session->get()->StartBlocking();
2083 
2084   // Declare a custom track and give it a name.
2085   uint64_t async_id = 123;
2086 
2087   {
2088     auto track = perfetto::Track(async_id);
2089     auto desc = track.Serialize();
2090     desc.set_name("MyCustomTrack");
2091     perfetto::TrackEvent::SetTrackDescriptor(track, std::move(desc));
2092   }
2093 
2094   // Start events on one thread and end them on another.
2095   TRACE_EVENT_BEGIN("bar", "AsyncEvent", perfetto::Track(async_id), "debug_arg",
2096                     123);
2097 
2098   TRACE_EVENT_BEGIN("bar", "SubEvent", perfetto::Track(async_id),
2099                     [](perfetto::EventContext) {});
2100   const auto main_thread_track =
2101       perfetto::Track(async_id, perfetto::ThreadTrack::Current());
2102   std::thread thread([&] {
2103     TRACE_EVENT_END("bar", perfetto::Track(async_id));
2104     TRACE_EVENT_END("bar", perfetto::Track(async_id), "arg1", false, "arg2",
2105                     true);
2106     const auto thread_track =
2107         perfetto::Track(async_id, perfetto::ThreadTrack::Current());
2108     // Thread-scoped tracks will have different uuids on different thread even
2109     // if the id matches.
2110     ASSERT_NE(main_thread_track.uuid, thread_track.uuid);
2111   });
2112   thread.join();
2113 
2114   auto trace = StopSessionAndReturnParsedTrace(tracing_session);
2115 
2116   // Check that the track uuids match on the begin and end events.
2117   const auto track = perfetto::Track(async_id);
2118   uint32_t main_thread_sequence = GetMainThreadPacketSequenceId(trace);
2119   int event_count = 0;
2120   bool found_descriptor = false;
2121   for (const auto& packet : trace.packet()) {
2122     if (packet.has_track_descriptor() &&
2123         !packet.track_descriptor().has_process() &&
2124         !packet.track_descriptor().has_thread()) {
2125       auto td = packet.track_descriptor();
2126       EXPECT_EQ("MyCustomTrack", td.name());
2127       EXPECT_EQ(track.uuid, td.uuid());
2128       EXPECT_EQ(perfetto::ProcessTrack::Current().uuid, td.parent_uuid());
2129       found_descriptor = true;
2130       continue;
2131     }
2132 
2133     if (!packet.has_track_event())
2134       continue;
2135     auto track_event = packet.track_event();
2136     if (track_event.type() ==
2137         perfetto::protos::gen::TrackEvent::TYPE_SLICE_BEGIN) {
2138       EXPECT_EQ(main_thread_sequence, packet.trusted_packet_sequence_id());
2139       EXPECT_EQ(track.uuid, track_event.track_uuid());
2140     } else {
2141       EXPECT_NE(main_thread_sequence, packet.trusted_packet_sequence_id());
2142       EXPECT_EQ(track.uuid, track_event.track_uuid());
2143     }
2144     event_count++;
2145   }
2146   EXPECT_TRUE(found_descriptor);
2147   EXPECT_EQ(4, event_count);
2148   perfetto::TrackEvent::EraseTrackDescriptor(track);
2149 }
2150 
TEST_P(PerfettoApiTest,TrackEventCustomNamedTrack)2151 TEST_P(PerfettoApiTest, TrackEventCustomNamedTrack) {
2152   // Create a new trace session.
2153   auto* tracing_session = NewTraceWithCategories({"bar"});
2154   tracing_session->get()->StartBlocking();
2155 
2156   // Declare a custom track and give it a name.
2157   uint64_t async_id = 123;
2158 
2159   // Start events on one thread and end them on another.
2160   TRACE_EVENT_BEGIN("bar", "AsyncEvent",
2161                     perfetto::NamedTrack("MyCustomTrack", async_id),
2162                     "debug_arg", 123);
2163 
2164   TRACE_EVENT_BEGIN("bar", "SubEvent",
2165                     perfetto::NamedTrack("MyCustomTrack", async_id),
2166                     [](perfetto::EventContext) {});
2167   const auto main_thread_track = perfetto::NamedTrack(
2168       "MyCustomTrack", async_id, perfetto::ThreadTrack::Current());
2169   std::thread thread([&] {
2170     TRACE_EVENT_END("bar", perfetto::NamedTrack("MyCustomTrack", async_id));
2171     TRACE_EVENT_END("bar", perfetto::NamedTrack("MyCustomTrack", async_id),
2172                     "arg1", false, "arg2", true);
2173     const auto thread_track = perfetto::NamedTrack(
2174         "MyCustomTrack", async_id, perfetto::ThreadTrack::Current());
2175     // Thread-scoped tracks will have different uuids on different thread even
2176     // if the id matches.
2177     ASSERT_NE(main_thread_track.uuid, thread_track.uuid);
2178   });
2179   thread.join();
2180 
2181   auto trace = StopSessionAndReturnParsedTrace(tracing_session);
2182 
2183   // Check that the track uuids match on the begin and end events.
2184   const auto track = perfetto::NamedTrack("MyCustomTrack", async_id);
2185   uint32_t main_thread_sequence = GetMainThreadPacketSequenceId(trace);
2186   int event_count = 0;
2187   bool found_descriptor = false;
2188   for (const auto& packet : trace.packet()) {
2189     if (packet.has_track_descriptor() &&
2190         !packet.track_descriptor().has_process() &&
2191         !packet.track_descriptor().has_thread()) {
2192       auto td = packet.track_descriptor();
2193       EXPECT_EQ("MyCustomTrack", td.static_name());
2194       EXPECT_EQ(track.uuid, td.uuid());
2195       EXPECT_EQ(perfetto::ProcessTrack::Current().uuid, td.parent_uuid());
2196       found_descriptor = true;
2197       continue;
2198     }
2199 
2200     if (!packet.has_track_event())
2201       continue;
2202     auto track_event = packet.track_event();
2203     if (track_event.type() ==
2204         perfetto::protos::gen::TrackEvent::TYPE_SLICE_BEGIN) {
2205       EXPECT_EQ(main_thread_sequence, packet.trusted_packet_sequence_id());
2206       EXPECT_EQ(track.uuid, track_event.track_uuid());
2207     } else {
2208       EXPECT_NE(main_thread_sequence, packet.trusted_packet_sequence_id());
2209       EXPECT_EQ(track.uuid, track_event.track_uuid());
2210     }
2211     event_count++;
2212   }
2213   EXPECT_TRUE(found_descriptor);
2214   EXPECT_EQ(4, event_count);
2215 }
2216 
TEST_P(PerfettoApiTest,CustomTrackDescriptorForParent)2217 TEST_P(PerfettoApiTest, CustomTrackDescriptorForParent) {
2218   // Setup the trace config.
2219   perfetto::TraceConfig cfg;
2220   cfg.set_duration_ms(500);
2221   cfg.add_buffers()->set_size_kb(1024);
2222   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
2223   ds_cfg->set_name("track_event");
2224 
2225   // SetTrackDescriptor before starting the tracing session.
2226   auto parent_track = perfetto::NamedTrack("MyCustomParent");
2227   auto desc = parent_track.Serialize();
2228   perfetto::TrackEvent::SetTrackDescriptor(parent_track, std::move(desc));
2229 
2230   // Create a new trace session.
2231   auto* tracing_session = NewTrace(cfg);
2232   tracing_session->get()->StartBlocking();
2233 
2234   TRACE_EVENT_INSTANT("bar", "AsyncEvent",
2235                       perfetto::NamedTrack("MyCustomChild", 123, parent_track));
2236 
2237   auto trace = StopSessionAndReturnParsedTrace(tracing_session);
2238 
2239   bool found_parent_desc = false;
2240   bool found_child_desc = false;
2241   for (const auto& packet : trace.packet()) {
2242     if (packet.has_track_descriptor()) {
2243       const auto& td = packet.track_descriptor();
2244 
2245       if (td.static_name() == "MyCustomParent") {
2246         found_parent_desc = true;
2247       } else if (td.static_name() == "MyCustomChild") {
2248         found_child_desc = true;
2249       }
2250     }
2251   }
2252   // SetTrackDescriptor for the parent happened before the tracing session was
2253   // running, but when emitting the child, the parent should be emitted as well.
2254   EXPECT_TRUE(found_parent_desc);
2255   EXPECT_TRUE(found_child_desc);
2256 }
2257 
TEST_P(PerfettoApiTest,TrackEventCustomTimestampClock)2258 TEST_P(PerfettoApiTest, TrackEventCustomTimestampClock) {
2259   // Create a new trace session.
2260   auto* tracing_session = NewTraceWithCategories({"foo"});
2261   tracing_session->get()->StartBlocking();
2262 
2263   static constexpr perfetto::protos::pbzero::BuiltinClock kMyClockId =
2264       static_cast<perfetto::protos::pbzero::BuiltinClock>(700);
2265   static constexpr uint64_t kTimestamp = 12345678;
2266 
2267   // First emit a clock snapshot that maps our custom clock to regular trace
2268   // time. Note that the clock snapshot should come before any events
2269   // referencing that clock.
2270   perfetto::TrackEvent::Trace([](perfetto::TrackEvent::TraceContext ctx) {
2271     auto packet = ctx.NewTracePacket();
2272     packet->set_timestamp_clock_id(
2273         static_cast<uint32_t>(perfetto::TrackEvent::GetTraceClockId()));
2274     packet->set_timestamp(perfetto::TrackEvent::GetTraceTimeNs());
2275     auto* clock_snapshot = packet->set_clock_snapshot();
2276     // First set the reference clock, i.e., the default trace clock in this
2277     // case.
2278     auto* clock = clock_snapshot->add_clocks();
2279     clock->set_clock_id(
2280         static_cast<uint32_t>(perfetto::TrackEvent::GetTraceClockId()));
2281     clock->set_timestamp(perfetto::TrackEvent::GetTraceTimeNs());
2282     // Then set the value of our reference clock at the same point in time. We
2283     // pretend our clock is one second behind trace time.
2284     clock = clock_snapshot->add_clocks();
2285     clock->set_clock_id(kMyClockId);
2286     clock->set_timestamp(kTimestamp + 1000000000ull);
2287   });
2288 
2289   // Next emit a trace event with a custom timestamp and a custom clock.
2290   TRACE_EVENT_INSTANT("foo", "EventWithCustomTime",
2291                       perfetto::TraceTimestamp{kMyClockId, kTimestamp});
2292   TRACE_EVENT_INSTANT("foo", "EventWithNormalTime");
2293 
2294   auto trace = StopSessionAndReturnParsedTrace(tracing_session);
2295 
2296   // Check that both the clock id and the timestamp got written together with
2297   // the packet. Note that we don't check the actual clock sync behavior here
2298   // since that happens in the Trace Processor instead.
2299   bool found_clock_snapshot = false;
2300   bool found_event = false;
2301   for (const auto& packet : trace.packet()) {
2302     if (packet.has_clock_snapshot())
2303       found_clock_snapshot = true;
2304     if (!packet.has_track_event() || packet.timestamp() != kTimestamp)
2305       continue;
2306     found_event = true;
2307     EXPECT_EQ(static_cast<uint32_t>(kMyClockId), packet.timestamp_clock_id());
2308     EXPECT_EQ(kTimestamp, packet.timestamp());
2309   }
2310   EXPECT_TRUE(found_clock_snapshot);
2311   EXPECT_TRUE(found_event);
2312 }
2313 
2314 // Only synchronous phases are supported for other threads. Hence disabled this
2315 // test.
2316 // TODO(b/261493947): fix or remove.
TEST_P(PerfettoApiTest,DISABLED_LegacyEventWithThreadOverride)2317 TEST_P(PerfettoApiTest, DISABLED_LegacyEventWithThreadOverride) {
2318   // Create a new trace session.
2319   auto* tracing_session = NewTraceWithCategories({"cat"});
2320   tracing_session->get()->StartBlocking();
2321 
2322   TRACE_EVENT_BEGIN_WITH_ID_TID_AND_TIMESTAMP0("cat", "Name", 1,
2323                                                MyThreadId(456), MyTimestamp{0});
2324   auto trace = StopSessionAndReturnParsedTrace(tracing_session);
2325 
2326   // Check that we wrote a track descriptor for the custom thread track, and
2327   // that the event was associated with that track.
2328   const auto track = perfetto::ThreadTrack::ForThread(456);
2329   bool found_descriptor = false;
2330   bool found_event = false;
2331   for (const auto& packet : trace.packet()) {
2332     if (packet.has_track_descriptor() &&
2333         packet.track_descriptor().has_thread()) {
2334       auto td = packet.track_descriptor().thread();
2335       if (td.tid() == 456) {
2336         EXPECT_EQ(track.uuid, packet.track_descriptor().uuid());
2337         found_descriptor = true;
2338       }
2339     }
2340 
2341     if (!packet.has_track_event())
2342       continue;
2343     auto track_event = packet.track_event();
2344     if (track_event.legacy_event().phase() == TRACE_EVENT_PHASE_ASYNC_BEGIN) {
2345       EXPECT_EQ(0u, track_event.track_uuid());
2346       found_event = true;
2347     }
2348   }
2349   EXPECT_TRUE(found_descriptor);
2350   EXPECT_TRUE(found_event);
2351   perfetto::TrackEvent::EraseTrackDescriptor(track);
2352 }
2353 
2354 // Only synchronous phases are supported for other threads. Hence disabled this
2355 // test.
TEST_P(PerfettoApiTest,DISABLED_LegacyEventWithProcessOverride)2356 TEST_P(PerfettoApiTest, DISABLED_LegacyEventWithProcessOverride) {
2357   // Create a new trace session.
2358   auto* tracing_session = NewTraceWithCategories({"cat"});
2359   tracing_session->get()->StartBlocking();
2360 
2361   // Note: there's no direct entrypoint for adding trace events for another
2362   // process, so we're using the internal support macro here.
2363   INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP(
2364       TRACE_EVENT_PHASE_INSTANT, "cat", "Name", 0, MyThreadId{789},
2365       MyTimestamp{0}, TRACE_EVENT_FLAG_HAS_PROCESS_ID);
2366   auto trace = StopSessionAndReturnParsedTrace(tracing_session);
2367 
2368   // Check that the event has a pid_override matching MyThread above.
2369   bool found_event = false;
2370   for (const auto& packet : trace.packet()) {
2371     if (!packet.has_track_event())
2372       continue;
2373     auto track_event = packet.track_event();
2374     if (track_event.type() == perfetto::protos::gen::TrackEvent::TYPE_INSTANT) {
2375       EXPECT_EQ(789, track_event.legacy_event().pid_override());
2376       EXPECT_EQ(-1, track_event.legacy_event().tid_override());
2377       found_event = true;
2378     }
2379   }
2380   EXPECT_TRUE(found_event);
2381 }
2382 
TEST_P(PerfettoApiTest,TrackDescriptorWrittenBeforeEvent)2383 TEST_P(PerfettoApiTest, TrackDescriptorWrittenBeforeEvent) {
2384   // Create a new trace session.
2385   auto* tracing_session = NewTraceWithCategories({"bar"});
2386   tracing_session->get()->StartBlocking();
2387 
2388   // Emit an event on a custom track.
2389   TRACE_EVENT_INSTANT("bar", "Event", perfetto::Track(8086));
2390   auto trace = StopSessionAndReturnParsedTrace(tracing_session);
2391 
2392   // Check that the descriptor was written before the event.
2393   std::set<uint64_t> seen_descriptors;
2394   for (const auto& packet : trace.packet()) {
2395     if (packet.has_track_descriptor())
2396       seen_descriptors.insert(packet.track_descriptor().uuid());
2397 
2398     if (!packet.has_track_event())
2399       continue;
2400     auto track_event = packet.track_event();
2401     EXPECT_TRUE(seen_descriptors.find(track_event.track_uuid()) !=
2402                 seen_descriptors.end());
2403   }
2404 }
2405 
TEST_P(PerfettoApiTest,TrackEventCustomTrackAndTimestamp)2406 TEST_P(PerfettoApiTest, TrackEventCustomTrackAndTimestamp) {
2407   // Create a new trace session.
2408   auto* tracing_session = NewTraceWithCategories({"bar"});
2409   tracing_session->get()->StartBlocking();
2410 
2411   // Custom track.
2412   perfetto::Track track(789);
2413 
2414   auto empty_lambda = [](perfetto::EventContext) {};
2415   constexpr uint64_t kBeginEventTime = 10;
2416   const MyTimestamp kEndEventTime{15};
2417   TRACE_EVENT_BEGIN("bar", "Event", track, kBeginEventTime, empty_lambda);
2418   TRACE_EVENT_END("bar", track, kEndEventTime, empty_lambda);
2419 
2420   constexpr uint64_t kInstantEventTime = 1;
2421   TRACE_EVENT_INSTANT("bar", "InstantEvent", track, kInstantEventTime,
2422                       empty_lambda);
2423 
2424   auto trace = StopSessionAndReturnParsedTrace(tracing_session);
2425 
2426   int event_count = 0;
2427   for (const auto& packet : trace.packet()) {
2428     if (!packet.has_track_event())
2429       continue;
2430 
2431     EXPECT_EQ(packet.timestamp_clock_id(),
2432               static_cast<uint32_t>(perfetto::TrackEvent::GetTraceClockId()));
2433     event_count++;
2434     switch (packet.track_event().type()) {
2435       case perfetto::protos::gen::TrackEvent::TYPE_SLICE_BEGIN:
2436         EXPECT_EQ(packet.timestamp(), kBeginEventTime);
2437         break;
2438       case perfetto::protos::gen::TrackEvent::TYPE_SLICE_END:
2439         EXPECT_EQ(packet.timestamp(), kEndEventTime.ts);
2440         break;
2441       case perfetto::protos::gen::TrackEvent::TYPE_INSTANT:
2442         EXPECT_EQ(packet.timestamp(), kInstantEventTime);
2443         break;
2444       case perfetto::protos::gen::TrackEvent::TYPE_COUNTER:
2445       case perfetto::protos::gen::TrackEvent::TYPE_UNSPECIFIED:
2446         ADD_FAILURE();
2447     }
2448   }
2449   EXPECT_EQ(event_count, 3);
2450   perfetto::TrackEvent::EraseTrackDescriptor(track);
2451 }
2452 
TEST_P(PerfettoApiTest,TrackEventCustomTrackAndTimestampNoLambda)2453 TEST_P(PerfettoApiTest, TrackEventCustomTrackAndTimestampNoLambda) {
2454   auto* tracing_session = NewTraceWithCategories({"bar"});
2455   tracing_session->get()->StartBlocking();
2456 
2457   perfetto::Track track(789);
2458 
2459   constexpr uint64_t kBeginEventTime = 10;
2460   constexpr uint64_t kEndEventTime = 15;
2461   TRACE_EVENT_BEGIN("bar", "Event", track, kBeginEventTime);
2462   TRACE_EVENT_END("bar", track, kEndEventTime);
2463 
2464   auto trace = StopSessionAndReturnParsedTrace(tracing_session);
2465 
2466   int event_count = 0;
2467   for (const auto& packet : trace.packet()) {
2468     if (!packet.has_track_event())
2469       continue;
2470     event_count++;
2471     switch (packet.track_event().type()) {
2472       case perfetto::protos::gen::TrackEvent::TYPE_SLICE_BEGIN:
2473         EXPECT_EQ(packet.timestamp(), kBeginEventTime);
2474         break;
2475       case perfetto::protos::gen::TrackEvent::TYPE_SLICE_END:
2476         EXPECT_EQ(packet.timestamp(), kEndEventTime);
2477         break;
2478       case perfetto::protos::gen::TrackEvent::TYPE_INSTANT:
2479       case perfetto::protos::gen::TrackEvent::TYPE_COUNTER:
2480       case perfetto::protos::gen::TrackEvent::TYPE_UNSPECIFIED:
2481         ADD_FAILURE();
2482     }
2483   }
2484 
2485   EXPECT_EQ(event_count, 2);
2486 }
2487 
TEST_P(PerfettoApiTest,TrackEventAnonymousCustomTrack)2488 TEST_P(PerfettoApiTest, TrackEventAnonymousCustomTrack) {
2489   // Create a new trace session.
2490   auto* tracing_session = NewTraceWithCategories({"bar"});
2491   tracing_session->get()->StartBlocking();
2492 
2493   // Emit an async event without giving it an explicit descriptor.
2494   uint64_t async_id = 4004;
2495   auto track = perfetto::Track(async_id, perfetto::ThreadTrack::Current());
2496   TRACE_EVENT_BEGIN("bar", "AsyncEvent", track);
2497   std::thread thread([&] { TRACE_EVENT_END("bar", track); });
2498   thread.join();
2499 
2500   auto trace = StopSessionAndReturnParsedTrace(tracing_session);
2501 
2502   // Check that a descriptor for the track was emitted.
2503   bool found_descriptor = false;
2504   for (const auto& packet : trace.packet()) {
2505     if (packet.has_track_descriptor() &&
2506         !packet.track_descriptor().has_process() &&
2507         !packet.track_descriptor().has_thread() &&
2508         packet.track_descriptor().uuid() !=
2509             perfetto::ThreadTrack::Current().uuid) {
2510       auto td = packet.track_descriptor();
2511       EXPECT_EQ(track.uuid, td.uuid());
2512       EXPECT_EQ(perfetto::ThreadTrack::Current().uuid, td.parent_uuid());
2513       found_descriptor = true;
2514     }
2515   }
2516   EXPECT_TRUE(found_descriptor);
2517 }
2518 
TEST_P(PerfettoApiTest,TrackEventTypedArgs)2519 TEST_P(PerfettoApiTest, TrackEventTypedArgs) {
2520   // Create a new trace session.
2521   auto* tracing_session = NewTraceWithCategories({"foo"});
2522   tracing_session->get()->StartBlocking();
2523 
2524   auto random_value = rand();
2525   TRACE_EVENT_BEGIN("foo", "EventWithTypedArg",
2526                     [random_value](perfetto::EventContext ctx) {
2527                       auto* log = ctx.event()->set_log_message();
2528                       log->set_source_location_iid(1);
2529                       log->set_body_iid(2);
2530                       auto* dbg = ctx.event()->add_debug_annotations();
2531                       dbg->set_name("random");
2532                       dbg->set_int_value(random_value);
2533                     });
2534   TRACE_EVENT_END("foo");
2535 
2536   auto trace = StopSessionAndReturnParsedTrace(tracing_session);
2537 
2538   bool found_args = false;
2539   for (const auto& packet : trace.packet()) {
2540     if (!packet.has_track_event())
2541       continue;
2542     const auto& track_event = packet.track_event();
2543     if (track_event.type() !=
2544         perfetto::protos::gen::TrackEvent::TYPE_SLICE_BEGIN)
2545       continue;
2546 
2547     EXPECT_TRUE(track_event.has_log_message());
2548     const auto& log = track_event.log_message();
2549     EXPECT_EQ(1u, log.source_location_iid());
2550     EXPECT_EQ(2u, log.body_iid());
2551 
2552     const auto& dbg = track_event.debug_annotations()[0];
2553     EXPECT_EQ("random", dbg.name());
2554     EXPECT_EQ(random_value, dbg.int_value());
2555 
2556     found_args = true;
2557   }
2558   EXPECT_TRUE(found_args);
2559 }
2560 
TEST_P(PerfettoApiTest,InlineTrackEventTypedArgs_SimpleRepeated)2561 TEST_P(PerfettoApiTest, InlineTrackEventTypedArgs_SimpleRepeated) {
2562   // Create a new trace session.
2563   auto* tracing_session = NewTraceWithCategories({"foo"});
2564   tracing_session->get()->StartBlocking();
2565 
2566   std::vector<uint64_t> flow_ids_old{1, 2, 3};
2567   std::vector<uint64_t> flow_ids{4, 5, 6};
2568   TRACE_EVENT_BEGIN("foo", "EventWithTypedArg",
2569                     perfetto::protos::pbzero::TrackEvent::kFlowIdsOld,
2570                     flow_ids_old,
2571                     perfetto::protos::pbzero::TrackEvent::kFlowIds, flow_ids);
2572   TRACE_EVENT_END("foo");
2573 
2574   auto trace = StopSessionAndReturnParsedTrace(tracing_session);
2575 
2576   bool found_args = false;
2577   for (const auto& packet : trace.packet()) {
2578     if (!packet.has_track_event())
2579       continue;
2580     const auto& track_event = packet.track_event();
2581     if (track_event.type() !=
2582         perfetto::protos::gen::TrackEvent::TYPE_SLICE_BEGIN) {
2583       continue;
2584     }
2585 
2586     EXPECT_THAT(track_event.flow_ids_old(), testing::ElementsAre(1u, 2u, 3u));
2587     EXPECT_THAT(track_event.flow_ids(), testing::ElementsAre(4u, 5u, 6u));
2588     found_args = true;
2589   }
2590   EXPECT_TRUE(found_args);
2591 }
2592 
2593 namespace {
2594 
2595 struct LogMessage {
WriteIntoTrace__anonfc73210d0111::__anonfc73210d1511::LogMessage2596   void WriteIntoTrace(
2597       perfetto::TracedProto<perfetto::protos::pbzero::LogMessage> context)
2598       const {
2599     context->set_source_location_iid(1);
2600     context->set_body_iid(2);
2601   }
2602 };
2603 
__anonfc73210d1602() 2604 auto GetWriteLogMessageRefLambda = []() {
2605   return [](perfetto::EventContext& ctx) {
2606     auto* log = ctx.event()->set_log_message();
2607     log->set_source_location_iid(1);
2608     log->set_body_iid(2);
2609   };
2610 };
2611 
CheckTypedArguments(const std::vector<char> & raw_trace,const char * event_name,perfetto::protos::gen::TrackEvent::Type type,std::function<void (const perfetto::protos::gen::TrackEvent &)> checker)2612 void CheckTypedArguments(
2613     const std::vector<char>& raw_trace,
2614     const char* event_name,
2615     perfetto::protos::gen::TrackEvent::Type type,
2616     std::function<void(const perfetto::protos::gen::TrackEvent&)> checker) {
2617   perfetto::protos::gen::Trace parsed_trace;
2618   ASSERT_TRUE(parsed_trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
2619 
2620   bool found_slice = false;
2621   ParsedIncrementalState incremental_state;
2622 
2623   for (const auto& packet : parsed_trace.packet()) {
2624     incremental_state.ClearIfNeeded(packet);
2625     incremental_state.Parse(packet);
2626 
2627     if (!packet.has_track_event())
2628       continue;
2629     const auto& track_event = packet.track_event();
2630     if (track_event.type() != type) {
2631       continue;
2632     }
2633     if (event_name &&
2634         incremental_state.GetEventName(track_event) != event_name) {
2635       continue;
2636     }
2637 
2638     checker(track_event);
2639     found_slice = true;
2640   }
2641   EXPECT_TRUE(found_slice);
2642 }
2643 
CheckLogMessagePresent(const std::vector<char> & raw_trace)2644 void CheckLogMessagePresent(const std::vector<char>& raw_trace) {
2645   CheckTypedArguments(raw_trace, nullptr,
2646                       perfetto::protos::gen::TrackEvent::TYPE_SLICE_BEGIN,
2647                       [](const perfetto::protos::gen::TrackEvent& track_event) {
2648                         EXPECT_TRUE(track_event.has_log_message());
2649                         const auto& log = track_event.log_message();
2650                         EXPECT_EQ(1u, log.source_location_iid());
2651                         EXPECT_EQ(2u, log.body_iid());
2652                       });
2653 }
2654 
2655 }  // namespace
2656 
TEST_P(PerfettoApiTest,InlineTrackEventTypedArgs_NestedSingle)2657 TEST_P(PerfettoApiTest, InlineTrackEventTypedArgs_NestedSingle) {
2658   // Create a new trace session.
2659   auto* tracing_session = NewTraceWithCategories({"foo"});
2660   tracing_session->get()->StartBlocking();
2661 
2662   TRACE_EVENT_BEGIN("foo", "EventWithTypedArg",
2663                     perfetto::protos::pbzero::TrackEvent::kLogMessage,
2664                     LogMessage());
2665   TRACE_EVENT_END("foo");
2666 
2667   std::vector<char> raw_trace = StopSessionAndReturnBytes(tracing_session);
2668 }
2669 
TEST_P(PerfettoApiTest,TrackEventThreadTime)2670 TEST_P(PerfettoApiTest, TrackEventThreadTime) {
2671   for (auto enable_thread_time : {true, false}) {
2672     perfetto::protos::gen::TrackEventConfig te_cfg;
2673     te_cfg.set_enable_thread_time_sampling(enable_thread_time);
2674     auto* tracing_session = NewTraceWithCategories({"foo"}, te_cfg);
2675 
2676     tracing_session->get()->StartBlocking();
2677 
2678     perfetto::Track custom_track(1);
2679 
2680     TRACE_EVENT_BEGIN("foo", "event1");
2681     TRACE_EVENT_BEGIN("foo", "event2");
2682     TRACE_EVENT_BEGIN("foo", "event3");
2683     TRACE_EVENT_BEGIN("foo", "event4", custom_track);
2684     TRACE_EVENT_END("foo");
2685     TRACE_EVENT_END("foo");
2686     TRACE_EVENT_END("foo");
2687     TRACE_EVENT_END("foo");
2688 
2689     auto trace = StopSessionAndReturnParsedTrace(tracing_session);
2690 
2691     bool found_counter_track_descriptor = false;
2692     uint64_t thread_time_counter_uuid = 0;
2693     uint64_t default_counter_uuid = 0;
2694     std::unordered_set<std::string> event_names;
2695     for (const auto& packet : trace.packet()) {
2696       if (packet.has_track_descriptor() &&
2697           packet.track_descriptor().has_counter()) {
2698         EXPECT_FALSE(found_counter_track_descriptor);
2699         found_counter_track_descriptor = true;
2700         thread_time_counter_uuid = packet.track_descriptor().uuid();
2701         EXPECT_EQ("thread_time", packet.track_descriptor().static_name());
2702         auto counter = packet.track_descriptor().counter();
2703         EXPECT_EQ(
2704             perfetto::protos::gen::
2705                 CounterDescriptor_BuiltinCounterType_COUNTER_THREAD_TIME_NS,
2706             counter.type());
2707         EXPECT_TRUE(counter.is_incremental());
2708       }
2709       if (packet.has_trace_packet_defaults()) {
2710         auto& defaults = packet.trace_packet_defaults().track_event_defaults();
2711         ASSERT_EQ(enable_thread_time ? 1u : 0u,
2712                   defaults.extra_counter_track_uuids().size());
2713         if (enable_thread_time) {
2714           default_counter_uuid = defaults.extra_counter_track_uuids().at(0);
2715         }
2716       }
2717       if (packet.has_track_event()) {
2718         std::string event_name;
2719         if (packet.has_interned_data()) {
2720           auto& event_names_info = packet.interned_data().event_names();
2721           if (event_names_info.size() > 0) {
2722             event_name = event_names_info[0].name();
2723           }
2724         }
2725         event_names.insert(event_name);
2726         EXPECT_EQ((enable_thread_time && event_name != "event4") ? 1u : 0u,
2727                   packet.track_event().extra_counter_values().size());
2728       }
2729     }
2730     EXPECT_TRUE(ContainsKey(event_names, "event1"));
2731     EXPECT_TRUE(ContainsKey(event_names, "event2"));
2732     EXPECT_TRUE(ContainsKey(event_names, "event3"));
2733     EXPECT_TRUE(ContainsKey(event_names, "event4"));
2734     EXPECT_EQ(enable_thread_time, found_counter_track_descriptor);
2735     EXPECT_EQ(default_counter_uuid, thread_time_counter_uuid);
2736     if (enable_thread_time) {
2737       EXPECT_GT(thread_time_counter_uuid, 0u);
2738     } else {
2739       EXPECT_EQ(thread_time_counter_uuid, 0u);
2740     }
2741   }
2742 }
2743 
TEST_P(PerfettoApiTest,TrackEventArgs_TypedAndUntyped)2744 TEST_P(PerfettoApiTest, TrackEventArgs_TypedAndUntyped) {
2745   // Create a new trace session.
2746   auto* tracing_session = NewTraceWithCategories({"foo"});
2747   tracing_session->get()->StartBlocking();
2748 
2749   TRACE_EVENT_BEGIN("foo", "E",
2750                     perfetto::protos::pbzero::TrackEvent::kLogMessage,
2751                     LogMessage(), "arg", "value");
2752   TRACE_EVENT_END("foo");
2753 
2754   std::vector<char> raw_trace = StopSessionAndReturnBytes(tracing_session);
2755   std::string trace(raw_trace.data(), raw_trace.size());
2756 
2757   // Find typed argument.
2758   CheckLogMessagePresent(raw_trace);
2759 
2760   // Find untyped argument.
2761   EXPECT_THAT(ReadSlicesFromTrace(raw_trace),
2762               ElementsAre("B:foo.E(arg=(string)value)", "E"));
2763 }
2764 
TEST_P(PerfettoApiTest,TrackEventArgs_UntypedAndTyped)2765 TEST_P(PerfettoApiTest, TrackEventArgs_UntypedAndTyped) {
2766   // Create a new trace session.
2767   auto* tracing_session = NewTraceWithCategories({"foo"});
2768   tracing_session->get()->StartBlocking();
2769 
2770   TRACE_EVENT_BEGIN("foo", "E", "arg", "value",
2771                     perfetto::protos::pbzero::TrackEvent::kLogMessage,
2772                     LogMessage());
2773   TRACE_EVENT_END("foo");
2774 
2775   std::vector<char> raw_trace = StopSessionAndReturnBytes(tracing_session);
2776 
2777   // Find typed argument.
2778   CheckLogMessagePresent(raw_trace);
2779 
2780   // Find untyped argument.
2781   EXPECT_THAT(ReadSlicesFromTrace(raw_trace),
2782               ElementsAre("B:foo.E(arg=(string)value)", "E"));
2783 }
2784 
TEST_P(PerfettoApiTest,TrackEventArgs_UntypedAndRefLambda)2785 TEST_P(PerfettoApiTest, TrackEventArgs_UntypedAndRefLambda) {
2786   // Create a new trace session.
2787   auto* tracing_session = NewTraceWithCategories({"foo"});
2788   tracing_session->get()->StartBlocking();
2789 
2790   TRACE_EVENT_BEGIN("foo", "E", "arg", "value", GetWriteLogMessageRefLambda());
2791   TRACE_EVENT_END("foo");
2792 
2793   std::vector<char> raw_trace = StopSessionAndReturnBytes(tracing_session);
2794 
2795   // Find typed argument.
2796   CheckLogMessagePresent(raw_trace);
2797 
2798   // Find untyped argument.
2799   EXPECT_THAT(ReadSlicesFromTrace(raw_trace),
2800               ElementsAre("B:foo.E(arg=(string)value)", "E"));
2801 }
2802 
TEST_P(PerfettoApiTest,TrackEventArgs_RefLambdaAndUntyped)2803 TEST_P(PerfettoApiTest, TrackEventArgs_RefLambdaAndUntyped) {
2804   // Create a new trace session.
2805   auto* tracing_session = NewTraceWithCategories({"foo"});
2806   tracing_session->get()->StartBlocking();
2807 
2808   TRACE_EVENT_BEGIN("foo", "E", GetWriteLogMessageRefLambda(), "arg", "value");
2809   TRACE_EVENT_END("foo");
2810 
2811   std::vector<char> raw_trace = StopSessionAndReturnBytes(tracing_session);
2812 
2813   // Find typed argument.
2814   CheckLogMessagePresent(raw_trace);
2815 
2816   // Find untyped argument.
2817   EXPECT_THAT(ReadSlicesFromTrace(raw_trace),
2818               ElementsAre("B:foo.E(arg=(string)value)", "E"));
2819 }
2820 
TEST_P(PerfettoApiTest,TrackEventArgs_RefLambdaAndTyped)2821 TEST_P(PerfettoApiTest, TrackEventArgs_RefLambdaAndTyped) {
2822   // Create a new trace session.
2823   auto* tracing_session = NewTraceWithCategories({"foo"});
2824   tracing_session->get()->StartBlocking();
2825 
2826   TRACE_EVENT_BEGIN(
2827       "foo", "E",
2828       [](perfetto::EventContext& ctx) {
2829         ctx.AddDebugAnnotation("arg", "value");
2830       },
2831       perfetto::protos::pbzero::TrackEvent::kLogMessage, LogMessage());
2832   TRACE_EVENT_END("foo");
2833 
2834   std::vector<char> raw_trace = StopSessionAndReturnBytes(tracing_session);
2835 
2836   // Find typed argument.
2837   CheckLogMessagePresent(raw_trace);
2838 
2839   // Find untyped argument.
2840   EXPECT_THAT(ReadSlicesFromTrace(raw_trace),
2841               ElementsAre("B:foo.E(arg=(string)value)", "E"));
2842 }
2843 
TEST_P(PerfettoApiTest,TrackEventArgs_TypedAndRefLambda)2844 TEST_P(PerfettoApiTest, TrackEventArgs_TypedAndRefLambda) {
2845   // Create a new trace session.
2846   auto* tracing_session = NewTraceWithCategories({"foo"});
2847   tracing_session->get()->StartBlocking();
2848 
2849   TRACE_EVENT_BEGIN("foo", "E",
2850                     perfetto::protos::pbzero::TrackEvent::kLogMessage,
2851                     LogMessage(), [](perfetto::EventContext& ctx) {
2852                       ctx.AddDebugAnnotation("arg", "value");
2853                     });
2854   TRACE_EVENT_END("foo");
2855 
2856   std::vector<char> raw_trace = StopSessionAndReturnBytes(tracing_session);
2857 
2858   // Find typed argument.
2859   CheckLogMessagePresent(raw_trace);
2860 
2861   // Find untyped argument.
2862   EXPECT_THAT(ReadSlicesFromTrace(raw_trace),
2863               ElementsAre("B:foo.E(arg=(string)value)", "E"));
2864 }
2865 
TEST_P(PerfettoApiTest,TrackEventArgs_RefLambdaAndRefLambda)2866 TEST_P(PerfettoApiTest, TrackEventArgs_RefLambdaAndRefLambda) {
2867   // Create a new trace session.
2868   auto* tracing_session = NewTraceWithCategories({"foo"});
2869   tracing_session->get()->StartBlocking();
2870 
2871   TRACE_EVENT_BEGIN(
2872       "foo", "E",
2873       [](perfetto::EventContext& ctx) {
2874         ctx.AddDebugAnnotation("arg1", "value1");
2875       },
2876       [](perfetto::EventContext& ctx) {
2877         ctx.AddDebugAnnotation("arg2", "value2");
2878       });
2879   TRACE_EVENT_END("foo");
2880 
2881   std::vector<char> raw_trace = StopSessionAndReturnBytes(tracing_session);
2882 
2883   // Find untyped arguments.
2884   EXPECT_THAT(
2885       ReadSlicesFromTrace(raw_trace),
2886       ElementsAre("B:foo.E(arg1=(string)value1,arg2=(string)value2)", "E"));
2887 }
2888 
TEST_P(PerfettoApiTest,TrackEventArgs_RefLambdaAndLambda)2889 TEST_P(PerfettoApiTest, TrackEventArgs_RefLambdaAndLambda) {
2890   // Create a new trace session.
2891   auto* tracing_session = NewTraceWithCategories({"foo"});
2892   tracing_session->get()->StartBlocking();
2893 
2894   TRACE_EVENT_BEGIN(
2895       "foo", "E",
2896       [](perfetto::EventContext& ctx) {
2897         ctx.AddDebugAnnotation("arg1", "value1");
2898       },
2899       [](perfetto::EventContext ctx) {
2900         ctx.AddDebugAnnotation("arg2", "value2");
2901       });
2902   TRACE_EVENT_END("foo");
2903 
2904   std::vector<char> raw_trace = StopSessionAndReturnBytes(tracing_session);
2905 
2906   // Find untyped arguments.
2907   EXPECT_THAT(
2908       ReadSlicesFromTrace(raw_trace),
2909       ElementsAre("B:foo.E(arg1=(string)value1,arg2=(string)value2)", "E"));
2910 }
2911 
TEST_P(PerfettoApiTest,TrackEventArgs_RefLambda)2912 TEST_P(PerfettoApiTest, TrackEventArgs_RefLambda) {
2913   // Create a new trace session.
2914   auto* tracing_session = NewTraceWithCategories({"foo"});
2915   tracing_session->get()->StartBlocking();
2916 
2917   TRACE_EVENT_BEGIN("foo", "E", [](perfetto::EventContext& ctx) {
2918     ctx.AddDebugAnnotation("arg", "value");
2919   });
2920   TRACE_EVENT_END("foo");
2921 
2922   std::vector<char> raw_trace = StopSessionAndReturnBytes(tracing_session);
2923 
2924   // Find untyped argument.
2925   EXPECT_THAT(ReadSlicesFromTrace(raw_trace),
2926               ElementsAre("B:foo.E(arg=(string)value)", "E"));
2927 }
2928 
TEST_P(PerfettoApiTest,TrackEventArgs_Flow_Global)2929 TEST_P(PerfettoApiTest, TrackEventArgs_Flow_Global) {
2930   // Create a new trace session.
2931   auto* tracing_session = NewTraceWithCategories({"foo"});
2932   tracing_session->get()->StartBlocking();
2933 
2934   TRACE_EVENT_INSTANT("foo", "E1", perfetto::Flow::Global(42));
2935   TRACE_EVENT_INSTANT("foo", "E2", perfetto::TerminatingFlow::Global(42));
2936 
2937   std::vector<char> raw_trace = StopSessionAndReturnBytes(tracing_session);
2938 
2939   // Find typed argument.
2940   CheckTypedArguments(
2941       raw_trace, "E1", perfetto::protos::gen::TrackEvent::TYPE_INSTANT,
2942       [](const perfetto::protos::gen::TrackEvent& track_event) {
2943         EXPECT_TRUE(track_event.flow_ids_old().empty());
2944         EXPECT_THAT(track_event.flow_ids(), testing::ElementsAre(42u));
2945       });
2946 }
2947 
TEST_P(PerfettoApiTest,TrackEventArgs_Lambda_Multisession)2948 TEST_P(PerfettoApiTest, TrackEventArgs_Lambda_Multisession) {
2949   // Create two simultaneous tracing sessions.
2950   auto* tracing_session = NewTraceWithCategories({"foo"});
2951   auto* tracing_session2 = NewTraceWithCategories({"foo"});
2952   tracing_session->get()->StartBlocking();
2953   tracing_session2->get()->StartBlocking();
2954 
2955   // Emit an event in both sessions using an argument function.
2956   auto make_arg = []() -> std::function<void(perfetto::EventContext&)> {
2957     return [](perfetto::EventContext& ctx) {
2958       ctx.event()->set_type(perfetto::protos::pbzero::TrackEvent::TYPE_INSTANT);
2959       ctx.event()->add_flow_ids(42);
2960     };
2961   };
2962   TRACE_EVENT_INSTANT("foo", "E1", make_arg());
2963 
2964   std::vector<char> raw_trace = StopSessionAndReturnBytes(tracing_session);
2965   std::vector<char> raw_trace2 = StopSessionAndReturnBytes(tracing_session2);
2966 
2967   // Check that the event was output twice.
2968   CheckTypedArguments(
2969       raw_trace, "E1", perfetto::protos::gen::TrackEvent::TYPE_INSTANT,
2970       [](const perfetto::protos::gen::TrackEvent& track_event) {
2971         EXPECT_TRUE(track_event.flow_ids_old().empty());
2972         EXPECT_THAT(track_event.flow_ids(), testing::ElementsAre(42u));
2973       });
2974   CheckTypedArguments(
2975       raw_trace2, "E1", perfetto::protos::gen::TrackEvent::TYPE_INSTANT,
2976       [](const perfetto::protos::gen::TrackEvent& track_event) {
2977         EXPECT_TRUE(track_event.flow_ids_old().empty());
2978         EXPECT_THAT(track_event.flow_ids(), testing::ElementsAre(42u));
2979       });
2980 }
2981 
TEST_P(PerfettoApiTest,TrackEventArgs_MultipleFlows)2982 TEST_P(PerfettoApiTest, TrackEventArgs_MultipleFlows) {
2983   // Create a new trace session.
2984   auto* tracing_session = NewTraceWithCategories({"foo"});
2985   tracing_session->get()->StartBlocking();
2986 
2987   {
2988     TRACE_EVENT("foo", "E1", perfetto::Flow::Global(1),
2989                 perfetto::Flow::Global(2), perfetto::Flow::Global(3));
2990   }
2991   {
2992     TRACE_EVENT("foo", "E2", perfetto::Flow::Global(1),
2993                 perfetto::TerminatingFlow::Global(2));
2994   }
2995   { TRACE_EVENT("foo", "E3", perfetto::TerminatingFlow::Global(3)); }
2996 
2997   std::vector<char> raw_trace = StopSessionAndReturnBytes(tracing_session);
2998   EXPECT_THAT(ReadSlicesFromTrace(raw_trace),
2999               ElementsAre("B:foo.E1(flow_ids=1,2,3)", "E",
3000                           "B:foo.E2(flow_ids=1)(terminating_flow_ids=2)", "E",
3001                           "B:foo.E3(terminating_flow_ids=3)", "E"));
3002 }
3003 
TEST_P(PerfettoApiTest,TrackEventArgs_Flow_ProcessScoped)3004 TEST_P(PerfettoApiTest, TrackEventArgs_Flow_ProcessScoped) {
3005   // Create a new trace session.
3006   auto* tracing_session = NewTraceWithCategories({"foo"});
3007   tracing_session->get()->StartBlocking();
3008 
3009   TRACE_EVENT_INSTANT("foo", "E1", perfetto::Flow::ProcessScoped(1));
3010   TRACE_EVENT_INSTANT("foo", "E2", perfetto::TerminatingFlow::ProcessScoped(1));
3011   TRACE_EVENT_INSTANT("foo", "Flush");
3012 
3013   std::vector<char> raw_trace = StopSessionAndReturnBytes(tracing_session);
3014 
3015   // Find typed arguments.
3016   CheckTypedArguments(raw_trace, "E1",
3017                       perfetto::protos::gen::TrackEvent::TYPE_INSTANT,
3018                       [](const perfetto::protos::gen::TrackEvent& track_event) {
3019                         EXPECT_EQ(track_event.flow_ids_old_size(), 0);
3020                         EXPECT_EQ(track_event.flow_ids_size(), 1);
3021                       });
3022   CheckTypedArguments(
3023       raw_trace, "E2", perfetto::protos::gen::TrackEvent::TYPE_INSTANT,
3024       [](const perfetto::protos::gen::TrackEvent& track_event) {
3025         EXPECT_EQ(track_event.terminating_flow_ids_old_size(), 0);
3026         EXPECT_EQ(track_event.terminating_flow_ids_size(), 1);
3027       });
3028 }
3029 
TEST_P(PerfettoApiTest,TrackEventArgs_Flow_FromPointer)3030 TEST_P(PerfettoApiTest, TrackEventArgs_Flow_FromPointer) {
3031   // Create a new trace session.
3032   auto* tracing_session = NewTraceWithCategories({"foo"});
3033   tracing_session->get()->StartBlocking();
3034 
3035   int a;
3036   int* ptr = &a;
3037   TRACE_EVENT_INSTANT("foo", "E1", perfetto::Flow::FromPointer(ptr));
3038   TRACE_EVENT_INSTANT("foo", "E2", perfetto::TerminatingFlow::FromPointer(ptr));
3039   TRACE_EVENT_INSTANT("foo", "Flush");
3040 
3041   std::vector<char> raw_trace = StopSessionAndReturnBytes(tracing_session);
3042 
3043   // Find typed arguments.
3044   CheckTypedArguments(raw_trace, "E1",
3045                       perfetto::protos::gen::TrackEvent::TYPE_INSTANT,
3046                       [](const perfetto::protos::gen::TrackEvent& track_event) {
3047                         EXPECT_EQ(track_event.flow_ids_old_size(), 0);
3048                         EXPECT_EQ(track_event.flow_ids_size(), 1);
3049                       });
3050   CheckTypedArguments(
3051       raw_trace, "E2", perfetto::protos::gen::TrackEvent::TYPE_INSTANT,
3052       [](const perfetto::protos::gen::TrackEvent& track_event) {
3053         EXPECT_EQ(track_event.terminating_flow_ids_old_size(), 0);
3054         EXPECT_EQ(track_event.terminating_flow_ids_size(), 1);
3055       });
3056 }
3057 
3058 struct InternedLogMessageBody
3059     : public perfetto::TrackEventInternedDataIndex<
3060           InternedLogMessageBody,
3061           perfetto::protos::pbzero::InternedData::kLogMessageBodyFieldNumber,
3062           std::string> {
Add__anonfc73210d0111::InternedLogMessageBody3063   static void Add(perfetto::protos::pbzero::InternedData* interned_data,
3064                   size_t iid,
3065                   const std::string& value) {
3066     auto l = interned_data->add_log_message_body();
3067     l->set_iid(iid);
3068     l->set_body(value.data(), value.size());
3069     commit_count++;
3070   }
3071 
3072   static int commit_count;
3073 };
3074 
3075 int InternedLogMessageBody::commit_count = 0;
3076 
TEST_P(PerfettoApiTest,TrackEventTypedArgsWithInterning)3077 TEST_P(PerfettoApiTest, TrackEventTypedArgsWithInterning) {
3078   // Create a new trace session.
3079   auto* tracing_session = NewTraceWithCategories({"foo"});
3080   tracing_session->get()->StartBlocking();
3081 
3082   std::stringstream large_message;
3083   for (size_t i = 0; i < 512; i++)
3084     large_message << i << ". Something wicked this way comes. ";
3085 
3086   size_t body_iid;
3087   InternedLogMessageBody::commit_count = 0;
3088   TRACE_EVENT_BEGIN("foo", "EventWithState", [&](perfetto::EventContext ctx) {
3089     EXPECT_EQ(0, InternedLogMessageBody::commit_count);
3090     body_iid = InternedLogMessageBody::Get(&ctx, "Alas, poor Yorick!");
3091     auto log = ctx.event()->set_log_message();
3092     log->set_body_iid(body_iid);
3093     EXPECT_EQ(1, InternedLogMessageBody::commit_count);
3094 
3095     auto body_iid2 = InternedLogMessageBody::Get(&ctx, "Alas, poor Yorick!");
3096     EXPECT_EQ(body_iid, body_iid2);
3097     EXPECT_EQ(1, InternedLogMessageBody::commit_count);
3098   });
3099   TRACE_EVENT_END("foo");
3100 
3101   TRACE_EVENT_BEGIN("foo", "EventWithState", [&](perfetto::EventContext ctx) {
3102     // Check that very large amounts of interned data works.
3103     auto log = ctx.event()->set_log_message();
3104     log->set_body_iid(InternedLogMessageBody::Get(&ctx, large_message.str()));
3105     EXPECT_EQ(2, InternedLogMessageBody::commit_count);
3106   });
3107   TRACE_EVENT_END("foo");
3108 
3109   // Make sure interned data persists across trace points.
3110   TRACE_EVENT_BEGIN("foo", "EventWithState", [&](perfetto::EventContext ctx) {
3111     auto body_iid2 = InternedLogMessageBody::Get(&ctx, "Alas, poor Yorick!");
3112     EXPECT_EQ(body_iid, body_iid2);
3113 
3114     auto body_iid3 = InternedLogMessageBody::Get(&ctx, "I knew him, Horatio");
3115     EXPECT_NE(body_iid, body_iid3);
3116     auto log = ctx.event()->set_log_message();
3117     log->set_body_iid(body_iid3);
3118     EXPECT_EQ(3, InternedLogMessageBody::commit_count);
3119   });
3120   TRACE_EVENT_END("foo");
3121 
3122   tracing_session->get()->StopBlocking();
3123   auto log_messages = ReadLogMessagesFromTrace(tracing_session->get());
3124   EXPECT_THAT(log_messages,
3125               ElementsAre("Alas, poor Yorick!", large_message.str(),
3126                           "I knew him, Horatio"));
3127 }
3128 
3129 struct InternedLogMessageBodySmall
3130     : public perfetto::TrackEventInternedDataIndex<
3131           InternedLogMessageBodySmall,
3132           perfetto::protos::pbzero::InternedData::kLogMessageBodyFieldNumber,
3133           const char*,
3134           perfetto::SmallInternedDataTraits> {
Add__anonfc73210d0111::InternedLogMessageBodySmall3135   static void Add(perfetto::protos::pbzero::InternedData* interned_data,
3136                   size_t iid,
3137                   const char* value) {
3138     auto l = interned_data->add_log_message_body();
3139     l->set_iid(iid);
3140     l->set_body(value);
3141   }
3142 };
3143 
TEST_P(PerfettoApiTest,TrackEventTypedArgsWithInterningByValue)3144 TEST_P(PerfettoApiTest, TrackEventTypedArgsWithInterningByValue) {
3145   // Create a new trace session.
3146   auto* tracing_session = NewTraceWithCategories({"foo"});
3147   tracing_session->get()->StartBlocking();
3148 
3149   size_t body_iid;
3150   TRACE_EVENT_BEGIN("foo", "EventWithState", [&](perfetto::EventContext ctx) {
3151     body_iid = InternedLogMessageBodySmall::Get(&ctx, "This above all:");
3152     auto log = ctx.event()->set_log_message();
3153     log->set_body_iid(body_iid);
3154 
3155     auto body_iid2 = InternedLogMessageBodySmall::Get(&ctx, "This above all:");
3156     EXPECT_EQ(body_iid, body_iid2);
3157 
3158     auto body_iid3 =
3159         InternedLogMessageBodySmall::Get(&ctx, "to thine own self be true");
3160     EXPECT_NE(body_iid, body_iid3);
3161   });
3162   TRACE_EVENT_END("foo");
3163 
3164   tracing_session->get()->StopBlocking();
3165   auto log_messages = ReadLogMessagesFromTrace(tracing_session->get());
3166   EXPECT_THAT(log_messages, ElementsAre("This above all:"));
3167 }
3168 
3169 struct InternedLogMessageBodyHashed
3170     : public perfetto::TrackEventInternedDataIndex<
3171           InternedLogMessageBodyHashed,
3172           perfetto::protos::pbzero::InternedData::kLogMessageBodyFieldNumber,
3173           std::string,
3174           perfetto::HashedInternedDataTraits> {
Add__anonfc73210d0111::InternedLogMessageBodyHashed3175   static void Add(perfetto::protos::pbzero::InternedData* interned_data,
3176                   size_t iid,
3177                   const std::string& value) {
3178     auto l = interned_data->add_log_message_body();
3179     l->set_iid(iid);
3180     l->set_body(value.data(), value.size());
3181   }
3182 };
3183 
TEST_P(PerfettoApiTest,TrackEventTypedArgsWithInterningByHashing)3184 TEST_P(PerfettoApiTest, TrackEventTypedArgsWithInterningByHashing) {
3185   // Create a new trace session.
3186   auto* tracing_session = NewTraceWithCategories({"foo"});
3187   tracing_session->get()->StartBlocking();
3188 
3189   size_t body_iid;
3190   TRACE_EVENT_BEGIN("foo", "EventWithState", [&](perfetto::EventContext ctx) {
3191     // Test using a dynamically created interned value.
3192     body_iid = InternedLogMessageBodyHashed::Get(
3193         &ctx, std::string("Though this ") + "be madness,");
3194     auto log = ctx.event()->set_log_message();
3195     log->set_body_iid(body_iid);
3196 
3197     auto body_iid2 =
3198         InternedLogMessageBodyHashed::Get(&ctx, "Though this be madness,");
3199     EXPECT_EQ(body_iid, body_iid2);
3200 
3201     auto body_iid3 =
3202         InternedLogMessageBodyHashed::Get(&ctx, "yet there is method in’t");
3203     EXPECT_NE(body_iid, body_iid3);
3204   });
3205   TRACE_EVENT_END("foo");
3206 
3207   tracing_session->get()->StopBlocking();
3208   auto log_messages = ReadLogMessagesFromTrace(tracing_session->get());
3209   EXPECT_THAT(log_messages, ElementsAre("Though this be madness,"));
3210 }
3211 
3212 struct InternedSourceLocation
3213     : public perfetto::TrackEventInternedDataIndex<
3214           InternedSourceLocation,
3215           perfetto::protos::pbzero::InternedData::kSourceLocationsFieldNumber,
3216           SourceLocation> {
Add__anonfc73210d0111::InternedSourceLocation3217   static void Add(perfetto::protos::pbzero::InternedData* interned_data,
3218                   size_t iid,
3219                   const SourceLocation& value) {
3220     auto l = interned_data->add_source_locations();
3221     auto file_name = std::get<0>(value);
3222     auto function_name = std::get<1>(value);
3223     auto line_number = std::get<2>(value);
3224     l->set_iid(iid);
3225     l->set_file_name(file_name);
3226     l->set_function_name(function_name);
3227     l->set_line_number(line_number);
3228   }
3229 };
3230 
TEST_P(PerfettoApiTest,TrackEventTypedArgsWithInterningComplexValue)3231 TEST_P(PerfettoApiTest, TrackEventTypedArgsWithInterningComplexValue) {
3232   // Create a new trace session.
3233   auto* tracing_session = NewTraceWithCategories({"foo"});
3234   tracing_session->get()->StartBlocking();
3235 
3236   TRACE_EVENT_BEGIN("foo", "EventWithState", [&](perfetto::EventContext ctx) {
3237     const SourceLocation location{"file.cc", "SomeFunction", 123};
3238     auto location_iid = InternedSourceLocation::Get(&ctx, location);
3239     auto body_iid = InternedLogMessageBody::Get(&ctx, "To be, or not to be");
3240     auto log = ctx.event()->set_log_message();
3241     log->set_source_location_iid(location_iid);
3242     log->set_body_iid(body_iid);
3243 
3244     auto location_iid2 = InternedSourceLocation::Get(&ctx, location);
3245     EXPECT_EQ(location_iid, location_iid2);
3246 
3247     const SourceLocation location2{"file.cc", "SomeFunction", 456};
3248     auto location_iid3 = InternedSourceLocation::Get(&ctx, location2);
3249     EXPECT_NE(location_iid, location_iid3);
3250   });
3251   TRACE_EVENT_END("foo");
3252 
3253   tracing_session->get()->StopBlocking();
3254   auto log_messages = ReadLogMessagesFromTrace(tracing_session->get());
3255   EXPECT_THAT(log_messages,
3256               ElementsAre("SomeFunction(file.cc:123): To be, or not to be"));
3257 }
3258 
TEST_P(PerfettoApiTest,TrackEventScoped)3259 TEST_P(PerfettoApiTest, TrackEventScoped) {
3260   // Create a new trace session.
3261   auto* tracing_session = NewTraceWithCategories({"test"});
3262   tracing_session->get()->StartBlocking();
3263 
3264   {
3265     uint64_t arg = 123;
3266     TRACE_EVENT("test", "TestEventWithArgs", [&](perfetto::EventContext ctx) {
3267       ctx.event()->set_log_message()->set_body_iid(arg);
3268     });
3269   }
3270 
3271   // Ensure a single line if statement counts as a valid scope for the macro.
3272   if (true)
3273     TRACE_EVENT("test", "SingleLineTestEvent");
3274 
3275   {
3276     // Make sure you can have multiple scoped events in the same scope.
3277     TRACE_EVENT("test", "TestEvent");
3278     TRACE_EVENT("test", "AnotherEvent");
3279     TRACE_EVENT("foo", "DisabledEvent");
3280   }
3281   auto slices = StopSessionAndReadSlicesFromTrace(tracing_session);
3282   EXPECT_THAT(
3283       slices,
3284       ElementsAre("B:test.TestEventWithArgs", "E", "B:test.SingleLineTestEvent",
3285                   "E", "B:test.TestEvent", "B:test.AnotherEvent", "E", "E"));
3286 }
3287 
3288 // A class similar to what Protozero generates for extended message.
3289 class TestTrackEvent : public perfetto::protos::pbzero::TrackEvent {
3290  public:
3291   static const int field_number = 9901;
3292 
set_extension_value(int value)3293   void set_extension_value(int value) {
3294     // 9900-10000 is the range of extension field numbers reserved for testing.
3295     AppendTinyVarInt(field_number, value);
3296   }
3297 };
3298 
TEST_P(PerfettoApiTest,ExtensionClass)3299 TEST_P(PerfettoApiTest, ExtensionClass) {
3300   auto* tracing_session = NewTraceWithCategories({"test"});
3301   tracing_session->get()->StartBlocking();
3302 
3303   {
3304     TRACE_EVENT("test", "TestEventWithExtensionArgs",
3305                 [&](perfetto::EventContext ctx) {
3306                   ctx.event<perfetto::protos::pbzero::TestExtension>()
3307                       ->add_int_extension_for_testing(42);
3308                 });
3309   }
3310 
3311   std::vector<char> raw_trace = StopSessionAndReturnBytes(tracing_session);
3312   EXPECT_GE(raw_trace.size(), 0u);
3313 
3314   bool found_extension = false;
3315   perfetto::protos::pbzero::Trace_Decoder trace(
3316       reinterpret_cast<uint8_t*>(raw_trace.data()), raw_trace.size());
3317 
3318   for (auto it = trace.packet(); it; ++it) {
3319     perfetto::protos::pbzero::TracePacket_Decoder packet(it->data(),
3320                                                          it->size());
3321 
3322     if (!packet.has_track_event())
3323       continue;
3324 
3325     auto track_event = packet.track_event();
3326     protozero::ProtoDecoder decoder(track_event.data, track_event.size);
3327 
3328     for (protozero::Field f = decoder.ReadField(); f.valid();
3329          f = decoder.ReadField()) {
3330       if (f.id() == perfetto::protos::pbzero::TestExtension::
3331                         FieldMetadata_IntExtensionForTesting::kFieldId) {
3332         found_extension = true;
3333       }
3334     }
3335   }
3336 
3337   EXPECT_TRUE(found_extension);
3338 }
3339 
TEST_P(PerfettoApiTest,InlineTypedExtensionField)3340 TEST_P(PerfettoApiTest, InlineTypedExtensionField) {
3341   auto* tracing_session = NewTraceWithCategories({"test"});
3342   tracing_session->get()->StartBlocking();
3343 
3344   {
3345     TRACE_EVENT(
3346         "test", "TestEventWithExtensionArgs",
3347         perfetto::protos::pbzero::TestExtension::kIntExtensionForTesting,
3348         std::vector<int>{42},
3349         perfetto::protos::pbzero::TestExtension::kUintExtensionForTesting, 42u);
3350   }
3351 
3352   std::vector<char> raw_trace = StopSessionAndReturnBytes(tracing_session);
3353   EXPECT_GE(raw_trace.size(), 0u);
3354 
3355   bool found_int_extension = false;
3356   bool found_uint_extension = false;
3357   perfetto::protos::pbzero::Trace_Decoder trace(
3358       reinterpret_cast<uint8_t*>(raw_trace.data()), raw_trace.size());
3359 
3360   for (auto it = trace.packet(); it; ++it) {
3361     perfetto::protos::pbzero::TracePacket_Decoder packet(it->data(),
3362                                                          it->size());
3363 
3364     if (!packet.has_track_event())
3365       continue;
3366 
3367     auto track_event = packet.track_event();
3368     protozero::ProtoDecoder decoder(track_event.data, track_event.size);
3369 
3370     for (protozero::Field f = decoder.ReadField(); f.valid();
3371          f = decoder.ReadField()) {
3372       if (f.id() == perfetto::protos::pbzero::TestExtension::
3373                         FieldMetadata_IntExtensionForTesting::kFieldId) {
3374         found_int_extension = true;
3375       } else if (f.id() ==
3376                  perfetto::protos::pbzero::TestExtension::
3377                      FieldMetadata_UintExtensionForTesting::kFieldId) {
3378         found_uint_extension = true;
3379       }
3380     }
3381   }
3382 
3383   EXPECT_TRUE(found_int_extension);
3384   EXPECT_TRUE(found_uint_extension);
3385 }
3386 
TEST_P(PerfettoApiTest,TrackEventInstant)3387 TEST_P(PerfettoApiTest, TrackEventInstant) {
3388   // Create a new trace session.
3389   auto* tracing_session = NewTraceWithCategories({"test"});
3390   tracing_session->get()->StartBlocking();
3391 
3392   TRACE_EVENT_INSTANT("test", "TestEvent");
3393   TRACE_EVENT_INSTANT("test", "AnotherEvent");
3394   auto slices = StopSessionAndReadSlicesFromTrace(tracing_session);
3395   EXPECT_THAT(slices, ElementsAre("I:test.TestEvent", "I:test.AnotherEvent"));
3396 }
3397 
TEST_P(PerfettoApiTest,TrackEventDefaultGlobalTrack)3398 TEST_P(PerfettoApiTest, TrackEventDefaultGlobalTrack) {
3399   // Create a new trace session.
3400   auto* tracing_session = NewTraceWithCategories({"test"});
3401   tracing_session->get()->StartBlocking();
3402 
3403   TRACE_EVENT_INSTANT("test", "ThreadEvent");
3404   TRACE_EVENT_INSTANT("test", "GlobalEvent", perfetto::Track::Global(0u));
3405   auto slices = StopSessionAndReadSlicesFromTrace(tracing_session);
3406   EXPECT_THAT(slices,
3407               ElementsAre("I:test.ThreadEvent", "[track=0]I:test.GlobalEvent"));
3408 }
3409 
TEST_P(PerfettoApiTest,TrackEventTrackFromPointer)3410 TEST_P(PerfettoApiTest, TrackEventTrackFromPointer) {
3411   // Create a new trace session.
3412   auto* tracing_session = NewTraceWithCategories({"test"});
3413   tracing_session->get()->StartBlocking();
3414 
3415   perfetto::Track parent_track(1);
3416   int* ptr = reinterpret_cast<int*>(2);
3417   TRACE_EVENT_INSTANT("test", "Event",
3418                       perfetto::Track::FromPointer(ptr, parent_track));
3419 
3420   perfetto::Track track(reinterpret_cast<uintptr_t>(ptr), parent_track);
3421 
3422   auto slices = StopSessionAndReadSlicesFromTrace(tracing_session);
3423   EXPECT_THAT(slices, ElementsAre("[track=" + std::to_string(track.uuid) +
3424                                   "]I:test.Event"));
3425 }
3426 
TEST_P(PerfettoApiTest,TrackEventTrackFromThreadScopedPointer)3427 TEST_P(PerfettoApiTest, TrackEventTrackFromThreadScopedPointer) {
3428   // Create a new trace session.
3429   auto* tracing_session = NewTraceWithCategories({"test"});
3430   tracing_session->get()->StartBlocking();
3431 
3432   int num = 2;
3433   TRACE_EVENT_INSTANT("test", "Event0.1");
3434   TRACE_EVENT_INSTANT("test", "Event0.2");
3435   TRACE_EVENT_INSTANT("test", "Event1.1", perfetto::Track::ThreadScoped(&num));
3436   TRACE_EVENT_INSTANT("test", "Event1.2", perfetto::Track::ThreadScoped(&num));
3437   std::thread t1([&]() {
3438     TRACE_EVENT_INSTANT("test", "Event2.1",
3439                         perfetto::Track::ThreadScoped(&num));
3440     TRACE_EVENT_INSTANT("test", "Event2.2",
3441                         perfetto::Track::ThreadScoped(&num));
3442   });
3443   t1.join();
3444   std::thread t2([&]() {
3445     TRACE_EVENT_INSTANT("test", "Event3.1",
3446                         perfetto::Track::ThreadScoped(&num));
3447     TRACE_EVENT_INSTANT("test", "Event3.2",
3448                         perfetto::Track::ThreadScoped(&num));
3449   });
3450   t2.join();
3451 
3452   auto trace = StopSessionAndReturnParsedTrace(tracing_session);
3453 
3454   std::unordered_map<std::string, uint64_t> track_uuid_map;
3455   for (auto packet : trace.packet()) {
3456     if (packet.has_interned_data()) {
3457       for (auto& ename : packet.interned_data().event_names()) {
3458         track_uuid_map.emplace(ename.name(), packet.track_event().track_uuid());
3459       }
3460     }
3461   }
3462   EXPECT_EQ(track_uuid_map.at("Event0.1"), track_uuid_map.at("Event0.2"));
3463   EXPECT_EQ(track_uuid_map.at("Event1.1"), track_uuid_map.at("Event1.2"));
3464   EXPECT_EQ(track_uuid_map.at("Event2.1"), track_uuid_map.at("Event2.2"));
3465   EXPECT_EQ(track_uuid_map.at("Event3.1"), track_uuid_map.at("Event3.2"));
3466 
3467   EXPECT_EQ(4u,
3468             (std::unordered_set<uint64_t>{
3469                  track_uuid_map.at("Event0.1"), track_uuid_map.at("Event1.1"),
3470                  track_uuid_map.at("Event2.1"), track_uuid_map.at("Event3.1")})
3471                 .size());
3472 }
3473 
TEST_P(PerfettoApiTest,FilterDebugAnnotations)3474 TEST_P(PerfettoApiTest, FilterDebugAnnotations) {
3475   for (auto flag : {false, true}) {
3476     // Create a new trace session.
3477     perfetto::protos::gen::TrackEventConfig te_cfg;
3478     te_cfg.set_filter_debug_annotations(flag);
3479     auto* tracing_session = NewTraceWithCategories({"test"}, te_cfg);
3480     tracing_session->get()->StartBlocking();
3481 
3482     TRACE_EVENT_BEGIN("test", "Event1");
3483     TRACE_EVENT_BEGIN("test", "Event2", [&](perfetto::EventContext ctx) {
3484       ctx.AddDebugAnnotation("debug_name", "debug_value");
3485     });
3486     TRACE_EVENT_BEGIN("test", "Event3");
3487     auto slices = StopSessionAndReadSlicesFromTrace(tracing_session);
3488     ASSERT_EQ(3u, slices.size());
3489     if (flag) {
3490       EXPECT_EQ("B:test.Event2", slices[1]);
3491     } else {
3492       EXPECT_EQ("B:test.Event2(debug_name=(string)debug_value)", slices[1]);
3493     }
3494   }
3495 }
3496 
TEST_P(PerfettoApiTest,TrackEventDebugAnnotations)3497 TEST_P(PerfettoApiTest, TrackEventDebugAnnotations) {
3498   // Create a new trace session.
3499   auto* tracing_session = NewTraceWithCategories({"test"});
3500   tracing_session->get()->StartBlocking();
3501 
3502   enum MyEnum : uint32_t { ENUM_FOO, ENUM_BAR };
3503   enum MySignedEnum : int32_t { SIGNED_ENUM_FOO = -1, SIGNED_ENUM_BAR };
3504   enum class MyClassEnum { VALUE };
3505 
3506   TRACE_EVENT_BEGIN("test", "E", "bool_arg", false);
3507   TRACE_EVENT_BEGIN("test", "E", "int_arg", -123);
3508   TRACE_EVENT_BEGIN("test", "E", "uint_arg", 456u);
3509   TRACE_EVENT_BEGIN("test", "E", "float_arg", 3.14159262f);
3510   TRACE_EVENT_BEGIN("test", "E", "double_arg", 6.22);
3511   TRACE_EVENT_BEGIN("test", "E", "str_arg", "hello", "str_arg2",
3512                     std::string("tracing"), "str_arg3",
3513                     std::string_view("view"));
3514   TRACE_EVENT_BEGIN("test", "E", "ptr_arg",
3515                     reinterpret_cast<void*>(static_cast<intptr_t>(0xbaadf00d)));
3516   TRACE_EVENT_BEGIN("test", "E", "size_t_arg", size_t{42});
3517   TRACE_EVENT_BEGIN("test", "E", "ptrdiff_t_arg", ptrdiff_t{-7});
3518   TRACE_EVENT_BEGIN("test", "E", "enum_arg", ENUM_BAR);
3519   TRACE_EVENT_BEGIN("test", "E", "signed_enum_arg", SIGNED_ENUM_FOO);
3520   TRACE_EVENT_BEGIN("test", "E", "class_enum_arg", MyClassEnum::VALUE);
3521   TRACE_EVENT_BEGIN("test", "E", "traced_value",
3522                     [&](perfetto::TracedValue context) {
3523                       std::move(context).WriteInt64(42);
3524                     });
3525   TRACE_EVENT_BEGIN("test", "E", [&](perfetto::EventContext ctx) {
3526     ctx.AddDebugAnnotation("debug_annotation", "value");
3527   });
3528   auto slices = StopSessionAndReadSlicesFromTrace(tracing_session);
3529   EXPECT_THAT(
3530       slices,
3531       ElementsAre(
3532           "B:test.E(bool_arg=(bool)0)", "B:test.E(int_arg=(int)-123)",
3533           "B:test.E(uint_arg=(uint)456)", "B:test.E(float_arg=(double)3.14159)",
3534           "B:test.E(double_arg=(double)6.22)",
3535           "B:test.E(str_arg=(string)hello,str_arg2=(string)tracing,"
3536           "str_arg3=(string)view)",
3537           "B:test.E(ptr_arg=(pointer)baadf00d)",
3538           "B:test.E(size_t_arg=(uint)42)", "B:test.E(ptrdiff_t_arg=(int)-7)",
3539           "B:test.E(enum_arg=(uint)1)", "B:test.E(signed_enum_arg=(int)-1)",
3540           "B:test.E(class_enum_arg=(int)0)", "B:test.E(traced_value=(int)42)",
3541           "B:test.E(debug_annotation=(string)value)"));
3542 }
3543 
TEST_P(PerfettoApiTest,TrackEventCustomDebugAnnotations)3544 TEST_P(PerfettoApiTest, TrackEventCustomDebugAnnotations) {
3545   // Create a new trace session.
3546   auto* tracing_session = NewTraceWithCategories({"test"});
3547   tracing_session->get()->StartBlocking();
3548 
3549   std::unique_ptr<MyDebugAnnotation> owned_annotation(new MyDebugAnnotation());
3550 
3551   TRACE_EVENT_BEGIN("test", "E", "custom_arg", MyDebugAnnotation());
3552   TRACE_EVENT_BEGIN("test", "E", "normal_arg", "x", "custom_arg",
3553                     std::move(owned_annotation));
3554   auto slices = StopSessionAndReadSlicesFromTrace(tracing_session);
3555   EXPECT_THAT(
3556       slices,
3557       ElementsAre(
3558           R"(B:test.E(custom_arg=(json){"key": 123}))",
3559           R"(B:test.E(normal_arg=(string)x,custom_arg=(json){"key": 123}))"));
3560 }
3561 
TEST_P(PerfettoApiTest,TrackEventCustomRawDebugAnnotations)3562 TEST_P(PerfettoApiTest, TrackEventCustomRawDebugAnnotations) {
3563   // Note: this class is also testing a non-moveable and non-copiable argument.
3564   class MyRawDebugAnnotation : public perfetto::DebugAnnotation {
3565    public:
3566     MyRawDebugAnnotation() { msg_->set_string_value("nested_value"); }
3567     ~MyRawDebugAnnotation() = default;
3568 
3569     // |msg_| already deletes these implicitly, but let's be explicit for safety
3570     // against future changes.
3571     MyRawDebugAnnotation(const MyRawDebugAnnotation&) = delete;
3572     MyRawDebugAnnotation(MyRawDebugAnnotation&&) = delete;
3573 
3574     void Add(perfetto::protos::pbzero::DebugAnnotation* annotation) const {
3575       auto ranges = msg_.GetRanges();
3576       annotation->AppendScatteredBytes(
3577           perfetto::protos::pbzero::DebugAnnotation::kNestedValueFieldNumber,
3578           &ranges[0], ranges.size());
3579     }
3580 
3581    private:
3582     mutable protozero::HeapBuffered<
3583         perfetto::protos::pbzero::DebugAnnotation::NestedValue>
3584         msg_;
3585   };
3586 
3587   // Create a new trace session.
3588   auto* tracing_session = NewTraceWithCategories({"test"});
3589   tracing_session->get()->StartBlocking();
3590 
3591   TRACE_EVENT_BEGIN("test", "E", "raw_arg", MyRawDebugAnnotation());
3592   TRACE_EVENT_BEGIN("test", "E", "plain_arg", 42, "raw_arg",
3593                     MyRawDebugAnnotation());
3594   auto slices = StopSessionAndReadSlicesFromTrace(tracing_session);
3595   EXPECT_THAT(
3596       slices,
3597       ElementsAre("B:test.E(raw_arg=(nested)nested_value)",
3598                   "B:test.E(plain_arg=(int)42,raw_arg=(nested)nested_value)"));
3599 }
3600 
TEST_P(PerfettoApiTest,ManyDebugAnnotations)3601 TEST_P(PerfettoApiTest, ManyDebugAnnotations) {
3602   // Create a new trace session.
3603   auto* tracing_session = NewTraceWithCategories({"test"});
3604   tracing_session->get()->StartBlocking();
3605 
3606   TRACE_EVENT_BEGIN("test", "E", "arg1", 1, "arg2", 2, "arg3", 3);
3607   auto slices = StopSessionAndReadSlicesFromTrace(tracing_session);
3608   EXPECT_THAT(slices,
3609               ElementsAre("B:test.E(arg1=(int)1,arg2=(int)2,arg3=(int)3)"));
3610 }
3611 
TEST_P(PerfettoApiTest,DebugAnnotationAndLambda)3612 TEST_P(PerfettoApiTest, DebugAnnotationAndLambda) {
3613   // Create a new trace session.
3614   auto* tracing_session = NewTraceWithCategories({"test"});
3615   tracing_session->get()->StartBlocking();
3616 
3617   enum MyEnum : uint32_t { ENUM_FOO, ENUM_BAR };
3618   enum MySignedEnum : int32_t { SIGNED_ENUM_FOO = -1, SIGNED_ENUM_BAR };
3619   enum class MyClassEnum { VALUE };
3620 
3621   TRACE_EVENT_BEGIN(
3622       "test", "E", "key", "value", [](perfetto::EventContext ctx) {
3623         ctx.event()->set_log_message()->set_source_location_iid(42);
3624       });
3625   auto trace = StopSessionAndReturnParsedTrace(tracing_session);
3626 
3627   bool found_args = false;
3628   for (const auto& packet : trace.packet()) {
3629     if (!packet.has_track_event())
3630       continue;
3631     const auto& track_event = packet.track_event();
3632     if (track_event.type() !=
3633         perfetto::protos::gen::TrackEvent::TYPE_SLICE_BEGIN)
3634       continue;
3635 
3636     EXPECT_TRUE(track_event.has_log_message());
3637     const auto& log = track_event.log_message();
3638     EXPECT_EQ(42u, log.source_location_iid());
3639 
3640     const auto& dbg = track_event.debug_annotations()[0];
3641     EXPECT_EQ("value", dbg.string_value());
3642 
3643     found_args = true;
3644   }
3645   EXPECT_TRUE(found_args);
3646 }
3647 
TEST_P(PerfettoApiTest,ProtoInsideDebugAnnotation)3648 TEST_P(PerfettoApiTest, ProtoInsideDebugAnnotation) {
3649   auto* tracing_session = NewTraceWithCategories({"test"});
3650   tracing_session->get()->StartBlocking();
3651 
3652   TRACE_EVENT_INSTANT(
3653       "test", "E", "key",
3654       [](perfetto::TracedProto<perfetto::protos::pbzero::LogMessage> ctx) {
3655         ctx->set_source_location_iid(42);
3656       });
3657 
3658   auto trace = StopSessionAndReturnParsedTrace(tracing_session);
3659 
3660   std::vector<std::string> interned_debug_annotation_names;
3661   std::vector<std::string> interned_debug_annotation_proto_type_names;
3662 
3663   bool found_args = false;
3664   for (const auto& packet : trace.packet()) {
3665     if (packet.has_interned_data()) {
3666       for (const auto& interned_name :
3667            packet.interned_data().debug_annotation_names()) {
3668         interned_debug_annotation_names.push_back(interned_name.name());
3669       }
3670       for (const auto& interned_type_name :
3671            packet.interned_data().debug_annotation_value_type_names()) {
3672         interned_debug_annotation_proto_type_names.push_back(
3673             interned_type_name.name());
3674       }
3675     }
3676 
3677     if (!packet.has_track_event())
3678       continue;
3679     const auto& track_event = packet.track_event();
3680     if (track_event.type() != perfetto::protos::gen::TrackEvent::TYPE_INSTANT) {
3681       continue;
3682     }
3683 
3684     EXPECT_EQ(track_event.debug_annotations_size(), 1);
3685     found_args = true;
3686   }
3687   // TODO(altimin): Use DebugAnnotationParser here to parse the debug
3688   // annotations.
3689   EXPECT_TRUE(found_args);
3690   EXPECT_THAT(interned_debug_annotation_names,
3691               testing::UnorderedElementsAre("key"));
3692   EXPECT_THAT(interned_debug_annotation_proto_type_names,
3693               testing::UnorderedElementsAre(".perfetto.protos.LogMessage"));
3694 }
3695 
TEST_P(PerfettoApiTest,TrackEventComputedName)3696 TEST_P(PerfettoApiTest, TrackEventComputedName) {
3697   // Setup the trace config.
3698   perfetto::TraceConfig cfg;
3699   cfg.set_duration_ms(500);
3700   cfg.add_buffers()->set_size_kb(1024);
3701   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
3702   ds_cfg->set_name("track_event");
3703 
3704   // Create a new trace session.
3705   auto* tracing_session = NewTrace(cfg);
3706   tracing_session->get()->StartBlocking();
3707 
3708   // New macros require perfetto::StaticString{} annotation.
3709   for (int i = 0; i < 3; i++)
3710     TRACE_EVENT_BEGIN("test", perfetto::StaticString{i % 2 ? "Odd" : "Even"});
3711 
3712   // Legacy macros assume all arguments are static strings.
3713   for (int i = 0; i < 3; i++)
3714     TRACE_EVENT_BEGIN0("test", i % 2 ? "Odd" : "Even");
3715 
3716   auto slices = StopSessionAndReadSlicesFromTrace(tracing_session);
3717   EXPECT_THAT(slices, ElementsAre("B:test.Even", "B:test.Odd", "B:test.Even",
3718                                   "B:test.Even", "B:test.Odd", "B:test.Even"));
3719 }
3720 
TEST_P(PerfettoApiTest,TrackEventEventNameDynamicString)3721 TEST_P(PerfettoApiTest, TrackEventEventNameDynamicString) {
3722   // Create a new trace session.
3723   auto* tracing_session = NewTraceWithCategories({"foo"});
3724   tracing_session->get()->StartBlocking();
3725   TRACE_EVENT_BEGIN("foo", perfetto::DynamicString{std::string("Event1")});
3726   TRACE_EVENT_BEGIN("foo", perfetto::DynamicString{std::string("Event2")});
3727 
3728   TRACE_EVENT0("foo", TRACE_STR_COPY(std::string("Event3")));
3729   const char* event4 = "Event4";
3730   TRACE_EVENT0("foo", event4);
3731 
3732   // Ensure that event-name is not emitted in case of `_END` events.
3733   PERFETTO_INTERNAL_TRACK_EVENT_WITH_METHOD(
3734       TraceForCategory, "foo", perfetto::DynamicString{std::string("Event5")},
3735       ::perfetto::protos::pbzero::TrackEvent::TYPE_SLICE_END);
3736   PERFETTO_INTERNAL_TRACK_EVENT_WITH_METHOD(
3737       TraceForCategory, "foo", perfetto::StaticString{"Event6"},
3738       ::perfetto::protos::pbzero::TrackEvent::TYPE_SLICE_END);
3739 
3740   auto slices = StopSessionAndReadSlicesFromTrace(tracing_session);
3741   ASSERT_EQ(6u, slices.size());
3742   EXPECT_EQ("B:foo.Event1", slices[0]);
3743   EXPECT_EQ("B:foo.Event2", slices[1]);
3744   EXPECT_EQ("B:foo.Event3", slices[2]);
3745   EXPECT_EQ("B:foo.Event4", slices[3]);
3746   EXPECT_EQ("E", slices[4]);
3747   EXPECT_EQ("E", slices[5]);
3748 }
3749 
TEST_P(PerfettoApiTest,TrackEventDynamicStringInDebugArgs)3750 TEST_P(PerfettoApiTest, TrackEventDynamicStringInDebugArgs) {
3751   auto* tracing_session = NewTraceWithCategories({"foo"});
3752   tracing_session->get()->StartBlocking();
3753 
3754   TRACE_EVENT1("foo", "Event1", "arg1",
3755                TRACE_STR_COPY(std::string("arg1_value1")));
3756   const char* value2 = "arg1_value2";
3757   TRACE_EVENT1("foo", "Event2", "arg1", value2);
3758   const char* value4 = "arg1_value4";
3759   TRACE_EVENT1("foo", "Event3", "arg1",
3760                perfetto::DynamicString(std::string("arg1_value3")));
3761   TRACE_EVENT1("foo", "Event4", "arg1", perfetto::StaticString(value4));
3762 
3763   TRACE_EVENT_BEGIN("foo", "Event5", "arg1",
3764                     TRACE_STR_COPY(std::string("arg1_value5")));
3765   TRACE_EVENT_BEGIN("foo", "Event6", "arg1",
3766                     perfetto::DynamicString(std::string("arg1_value6")));
3767   const char* value7 = "arg1_value7";
3768   TRACE_EVENT_BEGIN("foo", "Event7", "arg1", perfetto::StaticString(value7));
3769   const char* arg_name = "new_arg1";
3770   TRACE_EVENT_BEGIN("foo", "Event8", perfetto::DynamicString{arg_name}, 5);
3771 
3772   auto slices = StopSessionAndReadSlicesFromTrace(tracing_session);
3773   ASSERT_EQ(8u, slices.size());
3774   EXPECT_EQ("B:foo.Event1(arg1=(string)arg1_value1)", slices[0]);
3775   EXPECT_EQ("B:foo.Event2(arg1=(string)arg1_value2)", slices[1]);
3776   EXPECT_EQ("B:foo.Event3(arg1=(string)arg1_value3)", slices[2]);
3777   EXPECT_EQ("B:foo.Event4(arg1=(string)arg1_value4)", slices[3]);
3778   EXPECT_EQ("B:foo.Event5(arg1=(string)arg1_value5)", slices[4]);
3779   EXPECT_EQ("B:foo.Event6(arg1=(string)arg1_value6)", slices[5]);
3780   EXPECT_EQ("B:foo.Event7(arg1=(string)arg1_value7)", slices[6]);
3781   EXPECT_EQ("B:foo.Event8(new_arg1=(int)5)", slices[7]);
3782 }
3783 
TEST_P(PerfettoApiTest,TrackEventLegacyNullStringInArgs)3784 TEST_P(PerfettoApiTest, TrackEventLegacyNullStringInArgs) {
3785   auto* tracing_session = NewTraceWithCategories({"foo"});
3786   tracing_session->get()->StartBlocking();
3787 
3788   const char* null_str = nullptr;
3789 
3790   TRACE_EVENT1("foo", "Event1", "arg1", null_str);
3791   TRACE_EVENT1("foo", "Event2", "arg1", TRACE_STR_COPY(null_str));
3792 
3793   auto slices = StopSessionAndReadSlicesFromTrace(tracing_session);
3794   ASSERT_EQ(2u, slices.size());
3795   EXPECT_EQ("B:foo.Event1(arg1=(string)NULL)", slices[0]);
3796   EXPECT_EQ("B:foo.Event2(arg1=(string)NULL)", slices[1]);
3797 }
3798 
TEST_P(PerfettoApiTest,FilterDynamicEventName)3799 TEST_P(PerfettoApiTest, FilterDynamicEventName) {
3800   for (auto filter_dynamic_names : {false, true}) {
3801     // Create a new trace session.
3802     perfetto::protos::gen::TrackEventConfig te_cfg;
3803     te_cfg.set_filter_dynamic_event_names(filter_dynamic_names);
3804     auto* tracing_session = NewTraceWithCategories({"test"}, te_cfg);
3805     tracing_session->get()->StartBlocking();
3806 
3807     TRACE_EVENT_BEGIN("test", "Event1");
3808     TRACE_EVENT_BEGIN("test", perfetto::DynamicString("Event2"));
3809     const char* event3 = "Event3";
3810     TRACE_EVENT_BEGIN("test", perfetto::StaticString(event3));
3811     auto slices = StopSessionAndReadSlicesFromTrace(tracing_session);
3812     ASSERT_EQ(3u, slices.size());
3813     EXPECT_EQ("B:test.Event1", slices[0]);
3814     EXPECT_EQ(filter_dynamic_names ? "B:test.FILTERED" : "B:test.Event2",
3815               slices[1]);
3816     EXPECT_EQ("B:test.Event3", slices[2]);
3817   }
3818 }
3819 
TEST_P(PerfettoApiTest,TrackEventArgumentsNotEvaluatedWhenDisabled)3820 TEST_P(PerfettoApiTest, TrackEventArgumentsNotEvaluatedWhenDisabled) {
3821   // Create a new trace session.
3822   auto* tracing_session = NewTraceWithCategories({"foo"});
3823   tracing_session->get()->StartBlocking();
3824 
3825   bool called = false;
3826   auto ArgumentFunction = [&] {
3827     called = true;
3828     return 123;
3829   };
3830 
3831   TRACE_EVENT_BEGIN("test", "DisabledEvent", "arg", ArgumentFunction());
3832   { TRACE_EVENT("test", "DisabledScopedEvent", "arg", ArgumentFunction()); }
3833   perfetto::TrackEvent::Flush();
3834 
3835   tracing_session->get()->StopBlocking();
3836   EXPECT_FALSE(called);
3837 
3838   ArgumentFunction();
3839   EXPECT_TRUE(called);
3840 }
3841 
TEST_P(PerfettoApiTest,TrackEventConfig)3842 TEST_P(PerfettoApiTest, TrackEventConfig) {
3843   auto check_config = [&](perfetto::protos::gen::TrackEventConfig te_cfg) {
3844     perfetto::TraceConfig cfg;
3845     cfg.set_duration_ms(500);
3846     cfg.add_buffers()->set_size_kb(1024);
3847     auto* ds_cfg = cfg.add_data_sources()->mutable_config();
3848     ds_cfg->set_name("track_event");
3849     ds_cfg->set_track_event_config_raw(te_cfg.SerializeAsString());
3850 
3851     auto* tracing_session = NewTrace(cfg);
3852     tracing_session->get()->StartBlocking();
3853 
3854     TRACE_EVENT_BEGIN("foo", "FooEvent");
3855     TRACE_EVENT_BEGIN("bar", "BarEvent");
3856     TRACE_EVENT_BEGIN("foo,bar", "MultiFooBar");
3857     TRACE_EVENT_BEGIN("baz,bar,quux", "MultiBar");
3858     TRACE_EVENT_BEGIN("red,green,blue,foo", "MultiFoo");
3859     TRACE_EVENT_BEGIN("red,green,blue,yellow", "MultiNone");
3860     TRACE_EVENT_BEGIN("cat", "SlowEvent");
3861     TRACE_EVENT_BEGIN("cat.verbose", "DebugEvent");
3862     TRACE_EVENT_BEGIN("test", "TagEvent");
3863     TRACE_EVENT_BEGIN(TRACE_DISABLED_BY_DEFAULT("cat"), "SlowDisabledEvent");
3864     TRACE_EVENT_BEGIN("dynamic,foo", "DynamicGroupFooEvent");
3865     perfetto::DynamicCategory dyn{"dynamic,bar"};
3866     TRACE_EVENT_BEGIN(dyn, "DynamicGroupBarEvent");
3867 
3868     auto slices = StopSessionAndReadSlicesFromTrace(tracing_session);
3869     tracing_session->session.reset();
3870     return slices;
3871   };
3872 
3873   // Empty config should enable all categories except slow ones.
3874   {
3875     perfetto::protos::gen::TrackEventConfig te_cfg;
3876     auto slices = check_config(te_cfg);
3877     EXPECT_THAT(
3878         slices,
3879         ElementsAre("B:foo.FooEvent", "B:bar.BarEvent", "B:foo,bar.MultiFooBar",
3880                     "B:baz,bar,quux.MultiBar", "B:red,green,blue,foo.MultiFoo",
3881                     "B:red,green,blue,yellow.MultiNone", "B:test.TagEvent",
3882                     "B:$dynamic,$foo.DynamicGroupFooEvent",
3883                     "B:$dynamic,$bar.DynamicGroupBarEvent"));
3884   }
3885 
3886   // Enable exactly one category.
3887   {
3888     perfetto::protos::gen::TrackEventConfig te_cfg;
3889     te_cfg.add_disabled_categories("*");
3890     te_cfg.add_enabled_categories("foo");
3891     auto slices = check_config(te_cfg);
3892     EXPECT_THAT(slices, ElementsAre("B:foo.FooEvent", "B:foo,bar.MultiFooBar",
3893                                     "B:red,green,blue,foo.MultiFoo",
3894                                     "B:$dynamic,$foo.DynamicGroupFooEvent"));
3895   }
3896 
3897   // Enable exactly one dynamic category.
3898   {
3899     perfetto::protos::gen::TrackEventConfig te_cfg;
3900     te_cfg.add_disabled_categories("*");
3901     te_cfg.add_enabled_categories("dynamic");
3902     auto slices = check_config(te_cfg);
3903     EXPECT_THAT(slices, ElementsAre("B:$dynamic,$foo.DynamicGroupFooEvent",
3904                                     "B:$dynamic,$bar.DynamicGroupBarEvent"));
3905   }
3906 
3907   // Enable two categories.
3908   {
3909     perfetto::protos::gen::TrackEventConfig te_cfg;
3910     te_cfg.add_disabled_categories("*");
3911     te_cfg.add_enabled_categories("foo");
3912     te_cfg.add_enabled_categories("baz");
3913     te_cfg.add_enabled_categories("bar");
3914     auto slices = check_config(te_cfg);
3915     EXPECT_THAT(
3916         slices,
3917         ElementsAre("B:foo.FooEvent", "B:bar.BarEvent", "B:foo,bar.MultiFooBar",
3918                     "B:baz,bar,quux.MultiBar", "B:red,green,blue,foo.MultiFoo",
3919                     "B:$dynamic,$foo.DynamicGroupFooEvent",
3920                     "B:$dynamic,$bar.DynamicGroupBarEvent"));
3921   }
3922 
3923   // Enabling all categories with a pattern doesn't enable slow ones.
3924   {
3925     perfetto::protos::gen::TrackEventConfig te_cfg;
3926     te_cfg.add_enabled_categories("*");
3927     auto slices = check_config(te_cfg);
3928     EXPECT_THAT(
3929         slices,
3930         ElementsAre("B:foo.FooEvent", "B:bar.BarEvent", "B:foo,bar.MultiFooBar",
3931                     "B:baz,bar,quux.MultiBar", "B:red,green,blue,foo.MultiFoo",
3932                     "B:red,green,blue,yellow.MultiNone", "B:test.TagEvent",
3933                     "B:$dynamic,$foo.DynamicGroupFooEvent",
3934                     "B:$dynamic,$bar.DynamicGroupBarEvent"));
3935   }
3936 
3937   // Enable with a pattern.
3938   {
3939     perfetto::protos::gen::TrackEventConfig te_cfg;
3940     te_cfg.add_disabled_categories("*");
3941     te_cfg.add_enabled_categories("fo*");
3942     auto slices = check_config(te_cfg);
3943     EXPECT_THAT(slices, ElementsAre("B:foo.FooEvent", "B:foo,bar.MultiFooBar",
3944                                     "B:red,green,blue,foo.MultiFoo",
3945                                     "B:$dynamic,$foo.DynamicGroupFooEvent"));
3946   }
3947 
3948   // Enable with a tag.
3949   {
3950     perfetto::protos::gen::TrackEventConfig te_cfg;
3951     te_cfg.add_disabled_categories("*");
3952     te_cfg.add_enabled_tags("tag");
3953     auto slices = check_config(te_cfg);
3954     EXPECT_THAT(slices, ElementsAre("B:test.TagEvent"));
3955   }
3956 
3957   // Enable just slow categories.
3958   {
3959     perfetto::protos::gen::TrackEventConfig te_cfg;
3960     te_cfg.add_disabled_categories("*");
3961     te_cfg.add_enabled_tags("slow");
3962     auto slices = check_config(te_cfg);
3963     EXPECT_THAT(slices,
3964                 ElementsAre("B:cat.SlowEvent",
3965                             "B:disabled-by-default-cat.SlowDisabledEvent"));
3966   }
3967 
3968   // Enable all legacy disabled-by-default categories by a pattern
3969   {
3970     perfetto::protos::gen::TrackEventConfig te_cfg;
3971     te_cfg.add_disabled_categories("*");
3972     te_cfg.add_enabled_categories("disabled-by-default-*");
3973     auto slices = check_config(te_cfg);
3974     EXPECT_THAT(slices,
3975                 ElementsAre("B:disabled-by-default-cat.SlowDisabledEvent"));
3976   }
3977 
3978   // Enable everything including slow/debug categories.
3979   {
3980     perfetto::protos::gen::TrackEventConfig te_cfg;
3981     te_cfg.add_enabled_categories("*");
3982     te_cfg.add_enabled_tags("slow");
3983     te_cfg.add_enabled_tags("debug");
3984     auto slices = check_config(te_cfg);
3985     EXPECT_THAT(
3986         slices,
3987         ElementsAre("B:foo.FooEvent", "B:bar.BarEvent", "B:foo,bar.MultiFooBar",
3988                     "B:baz,bar,quux.MultiBar", "B:red,green,blue,foo.MultiFoo",
3989                     "B:red,green,blue,yellow.MultiNone", "B:cat.SlowEvent",
3990                     "B:cat.verbose.DebugEvent", "B:test.TagEvent",
3991                     "B:disabled-by-default-cat.SlowDisabledEvent",
3992                     "B:$dynamic,$foo.DynamicGroupFooEvent",
3993                     "B:$dynamic,$bar.DynamicGroupBarEvent"));
3994   }
3995 }
3996 
TEST_P(PerfettoApiTest,OneDataSourceOneEvent)3997 TEST_P(PerfettoApiTest, OneDataSourceOneEvent) {
3998   auto* data_source = &data_sources_["my_data_source"];
3999 
4000   // Setup the trace config.
4001   perfetto::TraceConfig cfg;
4002   cfg.set_duration_ms(500);
4003   cfg.add_buffers()->set_size_kb(1024);
4004   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
4005   ds_cfg->set_name("my_data_source");
4006   ds_cfg->set_legacy_config("test config");
4007 
4008   // Create a new trace session.
4009   auto* tracing_session = NewTrace(cfg);
4010 
4011   MockDataSource::Trace([](MockDataSource::TraceContext) {
4012     FAIL() << "Should not be called because the trace was not started";
4013   });
4014   MockDataSource::CallIfEnabled([](uint32_t) {
4015     FAIL() << "Should not be called because the trace was not started";
4016   });
4017 
4018   tracing_session->get()->Start();
4019   data_source->on_setup.Wait();
4020   EXPECT_EQ(data_source->config.legacy_config(), "test config");
4021   data_source->on_start.Wait();
4022 
4023   // Emit one trace event.
4024   std::atomic<int> trace_lambda_calls{0};
4025   MockDataSource::Trace(
4026       [&trace_lambda_calls](MockDataSource::TraceContext ctx) {
4027         auto packet = ctx.NewTracePacket();
4028         packet->set_timestamp(42);
4029         packet->set_for_testing()->set_str("event 1");
4030         trace_lambda_calls++;
4031         packet->Finalize();
4032 
4033         // The SMB scraping logic will skip the last packet because it cannot
4034         // guarantee it's finalized. Create an empty packet so we get the
4035         // previous one and this empty one is ignored.
4036         packet = ctx.NewTracePacket();
4037       });
4038 
4039   uint32_t active_instances = 0;
4040   MockDataSource::CallIfEnabled([&active_instances](uint32_t instances) {
4041     active_instances = instances;
4042   });
4043   EXPECT_EQ(1u, active_instances);
4044 
4045   data_source->on_stop.Wait();
4046   tracing_session->on_stop.Wait();
4047   EXPECT_EQ(trace_lambda_calls, 1);
4048 
4049   MockDataSource::Trace([](MockDataSource::TraceContext) {
4050     FAIL() << "Should not be called because the trace is now stopped";
4051   });
4052   MockDataSource::CallIfEnabled([](uint32_t) {
4053     FAIL() << "Should not be called because the trace is now stopped";
4054   });
4055 
4056   std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
4057   ASSERT_GE(raw_trace.size(), 0u);
4058 
4059   perfetto::protos::gen::Trace trace;
4060   ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
4061   bool test_packet_found = false;
4062   for (const auto& packet : trace.packet()) {
4063     if (!packet.has_for_testing())
4064       continue;
4065     EXPECT_FALSE(test_packet_found);
4066     EXPECT_EQ(packet.timestamp(), 42U);
4067     EXPECT_EQ(packet.for_testing().str(), "event 1");
4068     test_packet_found = true;
4069   }
4070   EXPECT_TRUE(test_packet_found);
4071 }
4072 
TEST_P(PerfettoApiTest,ReentrantTracing)4073 TEST_P(PerfettoApiTest, ReentrantTracing) {
4074   auto* data_source = &data_sources_["my_data_source"];
4075 
4076   // Setup the trace config.
4077   perfetto::TraceConfig cfg;
4078   cfg.set_duration_ms(500);
4079   cfg.add_buffers()->set_size_kb(1024);
4080   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
4081   ds_cfg->set_name("my_data_source");
4082 
4083   // Create a new trace session.
4084   auto* tracing_session = NewTrace(cfg);
4085   tracing_session->get()->Start();
4086   data_source->on_start.Wait();
4087 
4088   // Check that only one level of trace lambda calls is allowed.
4089   std::atomic<int> trace_lambda_calls{0};
4090   MockDataSource::Trace([&trace_lambda_calls](MockDataSource::TraceContext) {
4091     trace_lambda_calls++;
4092     MockDataSource::Trace([&trace_lambda_calls](MockDataSource::TraceContext) {
4093       trace_lambda_calls++;
4094     });
4095   });
4096 
4097   tracing_session->get()->StopBlocking();
4098   EXPECT_EQ(trace_lambda_calls, 1);
4099 }
4100 
TEST_P(PerfettoApiTest,ConsumerFlush)4101 TEST_P(PerfettoApiTest, ConsumerFlush) {
4102   auto* data_source = &data_sources_["my_data_source"];
4103 
4104   // Setup the trace config.
4105   perfetto::TraceConfig cfg;
4106   cfg.add_buffers()->set_size_kb(1024);
4107   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
4108   ds_cfg->set_name("my_data_source");
4109   ds_cfg->set_legacy_config("test config");
4110 
4111   // Create a new trace session.
4112   auto* tracing_session = NewTrace(cfg);
4113 
4114   tracing_session->get()->Start();
4115   data_source->on_start.Wait();
4116 
4117   MockDataSource::Trace([&](MockDataSource::TraceContext ctx) {
4118     auto packet = ctx.NewTracePacket();
4119     packet->set_timestamp(42);
4120     packet->set_for_testing()->set_str("flushed event");
4121     packet->Finalize();
4122 
4123     // The SMB scraping logic will skip the last packet because it cannot
4124     // guarantee it's finalized. Create an empty packet so we get the
4125     // previous one and this empty one is ignored.
4126     packet = ctx.NewTracePacket();
4127   });
4128 
4129   auto trace = StopSessionAndReturnParsedTrace(tracing_session);
4130 
4131   bool test_packet_found = false;
4132   for (const auto& packet : trace.packet()) {
4133     if (!packet.has_for_testing())
4134       continue;
4135     EXPECT_FALSE(test_packet_found);
4136     EXPECT_EQ(packet.timestamp(), 42U);
4137     EXPECT_EQ(packet.for_testing().str(), "flushed event");
4138     test_packet_found = true;
4139   }
4140   EXPECT_TRUE(test_packet_found);
4141 }
4142 
TEST_P(PerfettoApiTest,WithBatching)4143 TEST_P(PerfettoApiTest, WithBatching) {
4144   auto* data_source = &data_sources_["my_data_source"];
4145 
4146   // Setup the trace config.
4147   perfetto::TraceConfig cfg;
4148   cfg.set_duration_ms(500);
4149   cfg.add_buffers()->set_size_kb(1024);
4150   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
4151   ds_cfg->set_name("my_data_source");
4152   ds_cfg->set_legacy_config("test config");
4153 
4154   // Create a new trace session.
4155   auto* tracing_session = NewTrace(cfg);
4156 
4157   tracing_session->get()->Start();
4158   data_source->on_setup.Wait();
4159   data_source->on_start.Wait();
4160 
4161   std::stringstream first_large_message;
4162   for (size_t i = 0; i < 512; i++)
4163     first_large_message << i << ". Something wicked this way comes. ";
4164   auto first_large_message_str = first_large_message.str();
4165 
4166   // Emit one trace event before we begin batching.
4167   MockDataSource::Trace(
4168       [&first_large_message_str](MockDataSource::TraceContext ctx) {
4169         auto packet = ctx.NewTracePacket();
4170         packet->set_timestamp(42);
4171         packet->set_for_testing()->set_str(first_large_message_str);
4172         packet->Finalize();
4173       });
4174 
4175   // Simulate the start of a batching cycle by first setting the batching period
4176   // to a very large value and then force-flushing when we are done writing
4177   // data.
4178   ASSERT_TRUE(
4179       perfetto::test::EnableDirectSMBPatching(/*BackendType=*/GetParam()));
4180   perfetto::test::SetBatchCommitsDuration(UINT32_MAX,
4181                                           /*BackendType=*/GetParam());
4182 
4183   std::stringstream second_large_message;
4184   for (size_t i = 0; i < 512; i++)
4185     second_large_message << i << ". Something else wicked this way comes. ";
4186   auto second_large_message_str = second_large_message.str();
4187 
4188   // Emit another trace event.
4189   MockDataSource::Trace(
4190       [&second_large_message_str](MockDataSource::TraceContext ctx) {
4191         auto packet = ctx.NewTracePacket();
4192         packet->set_timestamp(43);
4193         packet->set_for_testing()->set_str(second_large_message_str);
4194         packet->Finalize();
4195 
4196         // Simulate the end of the batching cycle.
4197         ctx.Flush();
4198       });
4199 
4200   data_source->on_stop.Wait();
4201   tracing_session->on_stop.Wait();
4202 
4203   std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
4204   ASSERT_GE(raw_trace.size(), 0u);
4205 
4206   perfetto::protos::gen::Trace trace;
4207   ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
4208   bool test_packet_1_found = false;
4209   bool test_packet_2_found = false;
4210   for (const auto& packet : trace.packet()) {
4211     if (!packet.has_for_testing())
4212       continue;
4213     EXPECT_TRUE(packet.timestamp() == 42U || packet.timestamp() == 43U);
4214     if (packet.timestamp() == 42U) {
4215       EXPECT_FALSE(test_packet_1_found);
4216       EXPECT_EQ(packet.for_testing().str(), first_large_message_str);
4217       test_packet_1_found = true;
4218     } else {
4219       EXPECT_FALSE(test_packet_2_found);
4220       EXPECT_EQ(packet.for_testing().str(), second_large_message_str);
4221       test_packet_2_found = true;
4222     }
4223   }
4224   EXPECT_TRUE(test_packet_1_found && test_packet_2_found);
4225 }
4226 
TEST_P(PerfettoApiTest,BlockingStartAndStop)4227 TEST_P(PerfettoApiTest, BlockingStartAndStop) {
4228   auto* data_source = &data_sources_["my_data_source"];
4229 
4230   // Register a second data source to get a bit more coverage.
4231   perfetto::DataSourceDescriptor dsd;
4232   dsd.set_name("my_data_source2");
4233   MockDataSource2::Register(dsd, kTestDataSourceArg);
4234   perfetto::test::SyncProducers();
4235 
4236   // Setup the trace config.
4237   perfetto::TraceConfig cfg;
4238   cfg.set_duration_ms(500);
4239   cfg.add_buffers()->set_size_kb(1024);
4240   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
4241   ds_cfg->set_name("my_data_source");
4242   ds_cfg = cfg.add_data_sources()->mutable_config();
4243   ds_cfg->set_name("my_data_source2");
4244 
4245   // Create a new trace session.
4246   auto* tracing_session = NewTrace(cfg);
4247 
4248   tracing_session->get()->StartBlocking();
4249   EXPECT_TRUE(data_source->on_setup.notified());
4250   EXPECT_TRUE(data_source->on_start.notified());
4251 
4252   tracing_session->get()->StopBlocking();
4253   EXPECT_TRUE(data_source->on_stop.notified());
4254   EXPECT_TRUE(tracing_session->on_stop.notified());
4255   perfetto::test::TracingMuxerImplInternalsForTest::
4256       ClearDataSourceTlsStateOnReset<MockDataSource2>();
4257 }
4258 
TEST_P(PerfettoApiTest,BlockingStartAndStopOnEmptySession)4259 TEST_P(PerfettoApiTest, BlockingStartAndStopOnEmptySession) {
4260   // Setup the trace config.
4261   perfetto::TraceConfig cfg;
4262   cfg.set_duration_ms(500);
4263   cfg.add_buffers()->set_size_kb(1024);
4264   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
4265   ds_cfg->set_name("non_existent_data_source");
4266 
4267   // Create a new trace session.
4268   auto* tracing_session = NewTrace(cfg);
4269   tracing_session->get()->StartBlocking();
4270   tracing_session->get()->StopBlocking();
4271   EXPECT_TRUE(tracing_session->on_stop.notified());
4272 }
4273 
TEST_P(PerfettoApiTest,WriteEventsAfterDeferredStop)4274 TEST_P(PerfettoApiTest, WriteEventsAfterDeferredStop) {
4275   auto* data_source = &data_sources_["my_data_source"];
4276   data_source->handle_stop_asynchronously = true;
4277 
4278   // Setup the trace config and start the tracing session.
4279   perfetto::TraceConfig cfg;
4280   cfg.set_duration_ms(500);
4281   cfg.add_buffers()->set_size_kb(1024);
4282   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
4283   ds_cfg->set_name("my_data_source");
4284   auto* tracing_session = NewTrace(cfg);
4285   tracing_session->get()->StartBlocking();
4286 
4287   // Stop and wait for the producer to have seen the stop event.
4288   WaitableTestEvent consumer_stop_signal;
4289   tracing_session->get()->SetOnStopCallback(
4290       [&consumer_stop_signal] { consumer_stop_signal.Notify(); });
4291   tracing_session->get()->Stop();
4292   data_source->on_stop.Wait();
4293 
4294   // At this point tracing should be still allowed because of the
4295   // HandleStopAsynchronously() call.
4296   bool lambda_called = false;
4297 
4298   // This usleep is here just to prevent that we accidentally pass the test
4299   // just by virtue of hitting some race. We should be able to trace up until
4300   // 5 seconds after seeing the stop when using the deferred stop mechanism.
4301   std::this_thread::sleep_for(std::chrono::milliseconds(250));
4302 
4303   MockDataSource::Trace([&lambda_called](MockDataSource::TraceContext ctx) {
4304     auto packet = ctx.NewTracePacket();
4305     packet->set_for_testing()->set_str("event written after OnStop");
4306     packet->Finalize();
4307     ctx.Flush();
4308     lambda_called = true;
4309   });
4310   ASSERT_TRUE(lambda_called);
4311 
4312   // Now call the async stop closure. This acks the stop to the service and
4313   // disallows further Trace() calls.
4314   EXPECT_TRUE(data_source->async_stop_closure);
4315   data_source->async_stop_closure();
4316 
4317   // Wait that the stop is propagated to the consumer.
4318   consumer_stop_signal.Wait();
4319 
4320   MockDataSource::Trace([](MockDataSource::TraceContext) {
4321     FAIL() << "Should not be called after the stop is acked";
4322   });
4323 
4324   // Check the contents of the trace.
4325   std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
4326   ASSERT_GE(raw_trace.size(), 0u);
4327   perfetto::protos::gen::Trace trace;
4328   ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
4329   int test_packet_found = 0;
4330   for (const auto& packet : trace.packet()) {
4331     if (!packet.has_for_testing())
4332       continue;
4333     EXPECT_EQ(packet.for_testing().str(), "event written after OnStop");
4334     test_packet_found++;
4335   }
4336   EXPECT_EQ(test_packet_found, 1);
4337 }
4338 
TEST_P(PerfettoApiTest,RepeatedStartAndStop)4339 TEST_P(PerfettoApiTest, RepeatedStartAndStop) {
4340   perfetto::TraceConfig cfg;
4341   cfg.set_duration_ms(500);
4342   cfg.add_buffers()->set_size_kb(1024);
4343   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
4344   ds_cfg->set_name("my_data_source");
4345 
4346   for (int i = 0; i < 5; i++) {
4347     auto* tracing_session = NewTrace(cfg);
4348     tracing_session->get()->Start();
4349     std::atomic<bool> stop_called{false};
4350     tracing_session->get()->SetOnStopCallback(
4351         [&stop_called] { stop_called = true; });
4352     tracing_session->get()->StopBlocking();
4353     EXPECT_TRUE(stop_called);
4354   }
4355 }
4356 
TEST_P(PerfettoApiTest,SetupWithFile)4357 TEST_P(PerfettoApiTest, SetupWithFile) {
4358 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
4359   if (GetParam() == perfetto::kSystemBackend)
4360     GTEST_SKIP() << "write_into_file + system mode is not supported on Windows";
4361 #endif
4362   auto temp_file = perfetto::test::CreateTempFile();
4363   perfetto::TraceConfig cfg;
4364   cfg.set_duration_ms(500);
4365   cfg.add_buffers()->set_size_kb(1024);
4366   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
4367   ds_cfg->set_name("my_data_source");
4368   // Write a trace into |fd|.
4369   auto* tracing_session = NewTrace(cfg, temp_file.fd);
4370   tracing_session->get()->StartBlocking();
4371   tracing_session->get()->StopBlocking();
4372 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
4373   // Check that |fd| didn't get closed.
4374   EXPECT_EQ(0, fcntl(temp_file.fd, F_GETFD, 0));
4375 #endif
4376   // Check that the trace got written.
4377   EXPECT_GT(lseek(temp_file.fd, 0, SEEK_END), 0);
4378   EXPECT_EQ(0, close(temp_file.fd));
4379   // Clean up.
4380   EXPECT_EQ(0, remove(temp_file.path.c_str()));
4381 }
4382 
TEST_P(PerfettoApiTest,MultipleRegistrations)4383 TEST_P(PerfettoApiTest, MultipleRegistrations) {
4384   // Attempt to register the same data source again.
4385   perfetto::DataSourceDescriptor dsd;
4386   dsd.set_name("my_data_source");
4387   EXPECT_TRUE(MockDataSource::Register(dsd));
4388   perfetto::test::SyncProducers();
4389 
4390   // Setup the trace config.
4391   perfetto::TraceConfig cfg;
4392   cfg.set_duration_ms(500);
4393   cfg.add_buffers()->set_size_kb(1024);
4394   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
4395   ds_cfg->set_name("my_data_source");
4396 
4397   // Create a new trace session.
4398   auto* tracing_session = NewTrace(cfg);
4399   tracing_session->get()->StartBlocking();
4400 
4401   // Emit one trace event.
4402   std::atomic<int> trace_lambda_calls{0};
4403   MockDataSource::Trace([&trace_lambda_calls](MockDataSource::TraceContext) {
4404     trace_lambda_calls++;
4405   });
4406 
4407   // Make sure the data source got called only once.
4408   tracing_session->get()->StopBlocking();
4409   EXPECT_EQ(trace_lambda_calls, 1);
4410 }
4411 
TEST_P(PerfettoApiTest,CustomIncrementalState)4412 TEST_P(PerfettoApiTest, CustomIncrementalState) {
4413   perfetto::DataSourceDescriptor dsd;
4414   dsd.set_name("incr_data_source");
4415   TestIncrementalDataSource::Register(dsd);
4416   perfetto::test::SyncProducers();
4417 
4418   // Setup the trace config.
4419   perfetto::TraceConfig cfg;
4420   cfg.set_duration_ms(500);
4421   cfg.add_buffers()->set_size_kb(1024);
4422   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
4423   ds_cfg->set_name("incr_data_source");
4424 
4425   // Create a new trace session.
4426   auto* tracing_session = NewTrace(cfg);
4427   tracing_session->get()->StartBlocking();
4428 
4429   // First emit a no-op trace event that initializes the incremental state as a
4430   // side effect.
4431   TestIncrementalDataSource::Trace(
4432       [](TestIncrementalDataSource::TraceContext) {});
4433   EXPECT_TRUE(TestIncrementalState::constructed);
4434 
4435   // Check that the incremental state is carried across trace events.
4436   TestIncrementalDataSource::Trace(
4437       [](TestIncrementalDataSource::TraceContext ctx) {
4438         auto* state = ctx.GetIncrementalState();
4439         EXPECT_TRUE(state);
4440         EXPECT_EQ(100, state->count);
4441         state->count++;
4442       });
4443 
4444   TestIncrementalDataSource::Trace(
4445       [](TestIncrementalDataSource::TraceContext ctx) {
4446         auto* state = ctx.GetIncrementalState();
4447         EXPECT_EQ(101, state->count);
4448       });
4449 
4450   // Make sure the incremental state gets cleaned up between sessions.
4451   tracing_session->get()->StopBlocking();
4452   tracing_session = NewTrace(cfg);
4453   tracing_session->get()->StartBlocking();
4454   TestIncrementalDataSource::Trace(
4455       [](TestIncrementalDataSource::TraceContext ctx) {
4456         auto* state = ctx.GetIncrementalState();
4457         EXPECT_TRUE(TestIncrementalState::destroyed);
4458         EXPECT_TRUE(state);
4459         EXPECT_EQ(100, state->count);
4460       });
4461   tracing_session->get()->StopBlocking();
4462   perfetto::test::TracingMuxerImplInternalsForTest::
4463       ClearDataSourceTlsStateOnReset<TestIncrementalDataSource>();
4464 }
4465 
4466 const void* const kKey1 = &kKey1;
4467 const void* const kKey2 = &kKey2;
4468 
TEST_P(PerfettoApiTest,TrackEventUserData)4469 TEST_P(PerfettoApiTest, TrackEventUserData) {
4470   // Create a new trace session.
4471   auto* tracing_session = NewTraceWithCategories({"foo"});
4472   tracing_session->get()->StartBlocking();
4473   perfetto::TrackEventTlsStateUserData* data_1_ptr = nullptr;
4474   perfetto::TrackEventTlsStateUserData* data_2_ptr = nullptr;
4475 
4476   TRACE_EVENT_BEGIN(
4477       "foo", "E", [&data_1_ptr, &data_2_ptr](perfetto::EventContext& ctx) {
4478         EXPECT_EQ(nullptr, ctx.GetTlsUserData(kKey1));
4479         EXPECT_EQ(nullptr, ctx.GetTlsUserData(kKey2));
4480         std::unique_ptr<perfetto::TrackEventTlsStateUserData> data_1 =
4481             std::make_unique<perfetto::TrackEventTlsStateUserData>();
4482         data_1_ptr = data_1.get();
4483         std::unique_ptr<perfetto::TrackEventTlsStateUserData> data_2 =
4484             std::make_unique<perfetto::TrackEventTlsStateUserData>();
4485         data_2_ptr = data_2.get();
4486         ctx.SetTlsUserData(kKey1, std::move(data_1));
4487         ctx.SetTlsUserData(kKey2, std::move(data_2));
4488         EXPECT_EQ(data_1_ptr, ctx.GetTlsUserData(kKey1));
4489         EXPECT_EQ(data_2_ptr, ctx.GetTlsUserData(kKey2));
4490       });
4491   TRACE_EVENT_END("foo");
4492   TRACE_EVENT_BEGIN("foo", "F",
4493                     [&data_1_ptr, &data_2_ptr](perfetto::EventContext& ctx) {
4494                       EXPECT_EQ(data_1_ptr, ctx.GetTlsUserData(kKey1));
4495                       EXPECT_EQ(data_2_ptr, ctx.GetTlsUserData(kKey2));
4496                     });
4497   TRACE_EVENT_END("foo");
4498 
4499   std::vector<char> raw_trace = StopSessionAndReturnBytes(tracing_session);
4500 
4501   EXPECT_THAT(ReadSlicesFromTrace(raw_trace),
4502               ElementsAre("B:foo.E", "E", "B:foo.F", "E"));
4503 
4504   // Expect that the TLS User Data is cleared between tracing sessions.
4505   tracing_session = NewTraceWithCategories({"foo"});
4506   tracing_session->get()->StartBlocking();
4507 
4508   TRACE_EVENT_BEGIN("foo", "E", [](perfetto::EventContext& ctx) {
4509     EXPECT_EQ(nullptr, ctx.GetTlsUserData(kKey1));
4510     EXPECT_EQ(nullptr, ctx.GetTlsUserData(kKey2));
4511   });
4512   TRACE_EVENT_END("foo");
4513 
4514   raw_trace = StopSessionAndReturnBytes(tracing_session);
4515   EXPECT_THAT(ReadSlicesFromTrace(raw_trace), ElementsAre("B:foo.E", "E"));
4516 }
4517 
TEST_P(PerfettoApiTest,OnFlush)4518 TEST_P(PerfettoApiTest, OnFlush) {
4519   auto* data_source = &data_sources_["my_data_source"];
4520 
4521   // Setup the trace config.
4522   perfetto::TraceConfig cfg;
4523   cfg.add_buffers()->set_size_kb(1024);
4524   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
4525   ds_cfg->set_name("my_data_source");
4526 
4527   // Create a new trace session.
4528   auto* tracing_session = NewTrace(cfg);
4529 
4530   tracing_session->get()->StartBlocking();
4531 
4532   WaitableTestEvent producer_on_flush;
4533   WaitableTestEvent consumer_flush_done;
4534 
4535   data_source->on_flush_callback = [&](perfetto::FlushFlags flush_flags) {
4536     EXPECT_FALSE(consumer_flush_done.notified());
4537     EXPECT_EQ(flush_flags.initiator(),
4538               perfetto::FlushFlags::Initiator::kConsumerSdk);
4539     EXPECT_EQ(flush_flags.reason(), perfetto::FlushFlags::Reason::kExplicit);
4540     producer_on_flush.Notify();
4541     MockDataSource::Trace([](MockDataSource::TraceContext ctx) {
4542       ctx.NewTracePacket()->set_for_testing()->set_str("on-flush");
4543       ctx.Flush();
4544     });
4545   };
4546 
4547   tracing_session->get()->Flush([&](bool success) {
4548     EXPECT_TRUE(success);
4549     EXPECT_TRUE(producer_on_flush.notified());
4550     consumer_flush_done.Notify();
4551   });
4552 
4553   producer_on_flush.Wait();
4554   consumer_flush_done.Wait();
4555 
4556   tracing_session->get()->StopBlocking();
4557 
4558   data_source->on_stop.Wait();
4559 
4560   std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
4561   ASSERT_GE(raw_trace.size(), 0u);
4562 
4563   perfetto::protos::gen::Trace trace;
4564   ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
4565   EXPECT_THAT(
4566       trace.packet(),
4567       Contains(Property(
4568           &perfetto::protos::gen::TracePacket::for_testing,
4569           Property(&perfetto::protos::gen::TestEvent::str, "on-flush"))));
4570 }
4571 
TEST_P(PerfettoApiTest,OnFlushAsync)4572 TEST_P(PerfettoApiTest, OnFlushAsync) {
4573   auto* data_source = &data_sources_["my_data_source"];
4574 
4575   // Setup the trace config.
4576   perfetto::TraceConfig cfg;
4577   cfg.add_buffers()->set_size_kb(1024);
4578   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
4579   ds_cfg->set_name("my_data_source");
4580 
4581   // Create a new trace session.
4582   auto* tracing_session = NewTrace(cfg);
4583 
4584   tracing_session->get()->StartBlocking();
4585 
4586   WaitableTestEvent consumer_flush_done;
4587 
4588   data_source->handle_flush_asynchronously = true;
4589   data_source->on_flush_callback = [&](perfetto::FlushFlags) {
4590     EXPECT_FALSE(consumer_flush_done.notified());
4591   };
4592 
4593   tracing_session->get()->Flush([&](bool success) {
4594     EXPECT_TRUE(success);
4595     consumer_flush_done.Notify();
4596   });
4597 
4598   data_source->on_flush.Wait();
4599   perfetto::test::SyncProducers();
4600   EXPECT_FALSE(consumer_flush_done.notified());
4601 
4602   // Finish the flush asynchronously
4603   MockDataSource::Trace([](MockDataSource::TraceContext ctx) {
4604     ctx.NewTracePacket()->set_for_testing()->set_str("on-flush");
4605     ctx.Flush();
4606   });
4607   data_source->async_flush_closure();
4608 
4609   consumer_flush_done.Wait();
4610 
4611   tracing_session->get()->StopBlocking();
4612 
4613   data_source->on_stop.Wait();
4614 
4615   std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
4616   ASSERT_GE(raw_trace.size(), 0u);
4617 
4618   perfetto::protos::gen::Trace trace;
4619   ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
4620   EXPECT_THAT(
4621       trace.packet(),
4622       Contains(Property(
4623           &perfetto::protos::gen::TracePacket::for_testing,
4624           Property(&perfetto::protos::gen::TestEvent::str, "on-flush"))));
4625 }
4626 
4627 // Regression test for b/139110180. Checks that GetDataSourceLocked() can be
4628 // called from OnStart() and OnStop() callbacks without deadlocking.
TEST_P(PerfettoApiTest,GetDataSourceLockedFromCallbacks)4629 TEST_P(PerfettoApiTest, GetDataSourceLockedFromCallbacks) {
4630   auto* data_source = &data_sources_["my_data_source"];
4631 
4632   // Setup the trace config.
4633   perfetto::TraceConfig cfg;
4634   cfg.set_duration_ms(1);
4635   cfg.add_buffers()->set_size_kb(1024);
4636   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
4637   ds_cfg->set_name("my_data_source");
4638 
4639   // Create a new trace session.
4640   auto* tracing_session = NewTrace(cfg);
4641 
4642   data_source->on_start_callback = [] {
4643     MockDataSource::Trace([](MockDataSource::TraceContext ctx) {
4644       ctx.NewTracePacket()->set_for_testing()->set_str("on-start");
4645       auto ds = ctx.GetDataSourceLocked();
4646       ASSERT_TRUE(!!ds);
4647       ctx.NewTracePacket()->set_for_testing()->set_str("on-start-locked");
4648     });
4649   };
4650 
4651   data_source->on_stop_callback = [] {
4652     MockDataSource::Trace([](MockDataSource::TraceContext ctx) {
4653       ctx.NewTracePacket()->set_for_testing()->set_str("on-stop");
4654       auto ds = ctx.GetDataSourceLocked();
4655       ASSERT_TRUE(!!ds);
4656       ctx.NewTracePacket()->set_for_testing()->set_str("on-stop-locked");
4657       ctx.Flush();
4658     });
4659   };
4660 
4661   tracing_session->get()->Start();
4662   data_source->on_stop.Wait();
4663   tracing_session->on_stop.Wait();
4664 
4665   std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
4666   ASSERT_GE(raw_trace.size(), 0u);
4667 
4668   perfetto::protos::gen::Trace trace;
4669   ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
4670   int packets_found = 0;
4671   for (const auto& packet : trace.packet()) {
4672     if (!packet.has_for_testing())
4673       continue;
4674     packets_found |= packet.for_testing().str() == "on-start" ? 1 : 0;
4675     packets_found |= packet.for_testing().str() == "on-start-locked" ? 2 : 0;
4676     packets_found |= packet.for_testing().str() == "on-stop" ? 4 : 0;
4677     packets_found |= packet.for_testing().str() == "on-stop-locked" ? 8 : 0;
4678   }
4679   EXPECT_EQ(packets_found, 1 | 2 | 4 | 8);
4680 }
4681 
TEST_P(PerfettoApiTest,OnStartCallback)4682 TEST_P(PerfettoApiTest, OnStartCallback) {
4683   perfetto::TraceConfig cfg;
4684   cfg.set_duration_ms(60000);
4685   cfg.add_buffers()->set_size_kb(1024);
4686   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
4687   ds_cfg->set_name("track_event");
4688   auto* tracing_session = NewTrace(cfg);
4689 
4690   WaitableTestEvent got_start;
4691   tracing_session->get()->SetOnStartCallback([&] { got_start.Notify(); });
4692   tracing_session->get()->Start();
4693   got_start.Wait();
4694 
4695   tracing_session->get()->StopBlocking();
4696 }
4697 
TEST_P(PerfettoApiTest,OnErrorCallback)4698 TEST_P(PerfettoApiTest, OnErrorCallback) {
4699   perfetto::TraceConfig cfg;
4700 
4701   // Requesting too long |duration_ms| will cause EnableTracing() to fail.
4702   cfg.set_duration_ms(static_cast<uint32_t>(-1));
4703   cfg.add_buffers()->set_size_kb(1024);
4704   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
4705   ds_cfg->set_name("track_event");
4706   auto* tracing_session = NewTrace(cfg);
4707 
4708   WaitableTestEvent got_error;
4709   tracing_session->get()->SetOnErrorCallback([&](perfetto::TracingError error) {
4710     EXPECT_EQ(perfetto::TracingError::kTracingFailed, error.code);
4711     EXPECT_FALSE(error.message.empty());
4712     got_error.Notify();
4713   });
4714 
4715   tracing_session->get()->Start();
4716   got_error.Wait();
4717 
4718   // Registered error callback will be triggered also by OnDisconnect()
4719   // function. This may happen after exiting this test what would result in
4720   // system crash (|got_error| will not exist at that time). To prevent that
4721   // scenario, error callback has to be cleared.
4722   tracing_session->get()->SetOnErrorCallback(nullptr);
4723   tracing_session->get()->StopBlocking();
4724 }
4725 
TEST_P(PerfettoApiTest,UnsupportedBackend)4726 TEST_P(PerfettoApiTest, UnsupportedBackend) {
4727   // Create a new trace session with an invalid backend type specified.
4728   // Specifically, the custom backend isn't initialized for these tests.
4729   perfetto::TraceConfig cfg;
4730   cfg.add_buffers()->set_size_kb(1024);
4731   auto* tracing_session = NewTrace(cfg, perfetto::BackendType::kCustomBackend);
4732 
4733   // Creating the consumer should cause an asynchronous disconnect error.
4734   WaitableTestEvent got_error;
4735   tracing_session->get()->SetOnErrorCallback([&](perfetto::TracingError error) {
4736     EXPECT_EQ(perfetto::TracingError::kDisconnected, error.code);
4737     EXPECT_FALSE(error.message.empty());
4738     got_error.Notify();
4739   });
4740   got_error.Wait();
4741 
4742   // Clear the callback for test tear down.
4743   tracing_session->get()->SetOnErrorCallback(nullptr);
4744   // Synchronize the consumer channel to ensure the callback has propagated.
4745   tracing_session->get()->StopBlocking();
4746 }
4747 
TEST_P(PerfettoApiTest,ForbiddenConsumer)4748 TEST_P(PerfettoApiTest, ForbiddenConsumer) {
4749   g_test_tracing_policy->should_allow_consumer_connection = false;
4750 
4751   // Create a new trace session while consumer connections are forbidden.
4752   perfetto::TraceConfig cfg;
4753   cfg.add_buffers()->set_size_kb(1024);
4754   auto* tracing_session = NewTrace(cfg);
4755 
4756   // Creating the consumer should cause an asynchronous disconnect error.
4757   WaitableTestEvent got_error;
4758   tracing_session->get()->SetOnErrorCallback([&](perfetto::TracingError error) {
4759     EXPECT_EQ(perfetto::TracingError::kDisconnected, error.code);
4760     EXPECT_FALSE(error.message.empty());
4761     got_error.Notify();
4762   });
4763   got_error.Wait();
4764 
4765   // Clear the callback for test tear down.
4766   tracing_session->get()->SetOnErrorCallback(nullptr);
4767   // Synchronize the consumer channel to ensure the callback has propagated.
4768   tracing_session->get()->StopBlocking();
4769 
4770   g_test_tracing_policy->should_allow_consumer_connection = true;
4771 }
4772 
TEST_P(PerfettoApiTest,GetTraceStats)4773 TEST_P(PerfettoApiTest, GetTraceStats) {
4774   perfetto::TraceConfig cfg;
4775   cfg.set_duration_ms(500);
4776   cfg.add_buffers()->set_size_kb(1024);
4777   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
4778   ds_cfg->set_name("track_event");
4779   auto* tracing_session = NewTrace(cfg);
4780   tracing_session->get()->StartBlocking();
4781 
4782   // Asynchronous read.
4783   WaitableTestEvent got_stats;
4784   tracing_session->get()->GetTraceStats(
4785       [&got_stats](perfetto::TracingSession::GetTraceStatsCallbackArgs args) {
4786         perfetto::protos::gen::TraceStats trace_stats;
4787         EXPECT_TRUE(args.success);
4788         EXPECT_TRUE(trace_stats.ParseFromArray(args.trace_stats_data.data(),
4789                                                args.trace_stats_data.size()));
4790         EXPECT_EQ(1, trace_stats.buffer_stats_size());
4791         got_stats.Notify();
4792       });
4793   got_stats.Wait();
4794 
4795   // Blocking read.
4796   auto stats = tracing_session->get()->GetTraceStatsBlocking();
4797   perfetto::protos::gen::TraceStats trace_stats;
4798   EXPECT_TRUE(stats.success);
4799   EXPECT_TRUE(trace_stats.ParseFromArray(stats.trace_stats_data.data(),
4800                                          stats.trace_stats_data.size()));
4801   EXPECT_EQ(1, trace_stats.buffer_stats_size());
4802 
4803   tracing_session->get()->StopBlocking();
4804 }
4805 
TEST_P(PerfettoApiTest,CustomDataSource)4806 TEST_P(PerfettoApiTest, CustomDataSource) {
4807   perfetto::TraceConfig cfg;
4808   cfg.add_buffers()->set_size_kb(1024);
4809   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
4810   ds_cfg->set_name("CustomDataSource");
4811   auto* tracing_session = NewTrace(cfg);
4812   tracing_session->get()->StartBlocking();
4813   CustomDataSource::Trace([](CustomDataSource::TraceContext ctx) {
4814     auto packet = ctx.NewTracePacket();
4815     packet->set_timestamp(4200000);
4816     packet->set_for_testing()->set_str("Test String");
4817   });
4818   CustomDataSource::Trace(
4819       [](CustomDataSource::TraceContext ctx) { ctx.Flush(); });
4820 
4821   tracing_session->get()->StopBlocking();
4822   auto bytes = tracing_session->get()->ReadTraceBlocking();
4823   perfetto::protos::gen::Trace parsed_trace;
4824   EXPECT_TRUE(parsed_trace.ParseFromArray(bytes.data(), bytes.size()));
4825   bool found_for_testing = false;
4826   for (auto& packet : parsed_trace.packet()) {
4827     if (packet.has_for_testing()) {
4828       EXPECT_FALSE(found_for_testing);
4829       found_for_testing = true;
4830       EXPECT_EQ(4200000u, packet.timestamp());
4831       EXPECT_EQ("Test String", packet.for_testing().str());
4832     }
4833   }
4834   EXPECT_TRUE(found_for_testing);
4835 }
4836 
TEST_P(PerfettoApiTest,QueryServiceState)4837 TEST_P(PerfettoApiTest, QueryServiceState) {
4838   class QueryTestDataSource : public perfetto::DataSource<QueryTestDataSource> {
4839   };
4840   RegisterDataSource<QueryTestDataSource>("query_test_data_source");
4841   perfetto::test::SyncProducers();
4842 
4843   auto tracing_session =
4844       perfetto::Tracing::NewTrace(/*BackendType=*/GetParam());
4845   // Asynchronous read.
4846   WaitableTestEvent got_state;
4847   tracing_session->QueryServiceState(
4848       [&got_state](
4849           perfetto::TracingSession::QueryServiceStateCallbackArgs result) {
4850         perfetto::protos::gen::TracingServiceState state;
4851         EXPECT_TRUE(result.success);
4852         EXPECT_TRUE(state.ParseFromArray(result.service_state_data.data(),
4853                                          result.service_state_data.size()));
4854         EXPECT_EQ(1, state.producers_size());
4855         EXPECT_NE(std::string::npos,
4856                   state.producers()[0].name().find("integrationtest"));
4857         bool found_ds = false;
4858         for (const auto& ds : state.data_sources())
4859           found_ds |= ds.ds_descriptor().name() == "query_test_data_source";
4860         EXPECT_TRUE(found_ds);
4861         got_state.Notify();
4862       });
4863   got_state.Wait();
4864 
4865   // Blocking read.
4866   auto result = tracing_session->QueryServiceStateBlocking();
4867   perfetto::protos::gen::TracingServiceState state;
4868   EXPECT_TRUE(result.success);
4869   EXPECT_TRUE(state.ParseFromArray(result.service_state_data.data(),
4870                                    result.service_state_data.size()));
4871   EXPECT_EQ(1, state.producers_size());
4872   EXPECT_NE(std::string::npos,
4873             state.producers()[0].name().find("integrationtest"));
4874   bool found_ds = false;
4875   for (const auto& ds : state.data_sources())
4876     found_ds |= ds.ds_descriptor().name() == "query_test_data_source";
4877   EXPECT_TRUE(found_ds);
4878   perfetto::test::TracingMuxerImplInternalsForTest::
4879       ClearDataSourceTlsStateOnReset<QueryTestDataSource>();
4880 }
4881 
TEST_P(PerfettoApiTest,UpdateDataSource)4882 TEST_P(PerfettoApiTest, UpdateDataSource) {
4883   class UpdateTestDataSource
4884       : public perfetto::DataSource<UpdateTestDataSource> {};
4885 
4886   perfetto::DataSourceDescriptor dsd;
4887   dsd.set_name("update_test_data_source");
4888 
4889   RegisterDataSource<UpdateTestDataSource>(dsd);
4890 
4891   {
4892     protozero::HeapBuffered<perfetto::protos::pbzero::TrackEventDescriptor> ted;
4893     auto cat = ted->add_available_categories();
4894     cat->set_name("new_cat");
4895     dsd.set_track_event_descriptor_raw(ted.SerializeAsString());
4896   }
4897 
4898   UpdateDataSource<UpdateTestDataSource>(dsd);
4899 
4900   perfetto::test::SyncProducers();
4901 
4902   auto tracing_session =
4903       perfetto::Tracing::NewTrace(/*BackendType=*/GetParam());
4904   // Blocking read.
4905   auto result = tracing_session->QueryServiceStateBlocking();
4906   perfetto::protos::gen::TracingServiceState state;
4907   EXPECT_TRUE(result.success);
4908   EXPECT_TRUE(state.ParseFromArray(result.service_state_data.data(),
4909                                    result.service_state_data.size()));
4910   EXPECT_EQ(1, state.producers_size());
4911   EXPECT_NE(std::string::npos,
4912             state.producers()[0].name().find("integrationtest"));
4913   bool found_ds = false;
4914   for (const auto& ds : state.data_sources()) {
4915     if (ds.ds_descriptor().name() == "update_test_data_source") {
4916       found_ds = true;
4917       perfetto::protos::gen::TrackEventDescriptor ted;
4918       auto desc_raw = ds.ds_descriptor().track_event_descriptor_raw();
4919       EXPECT_TRUE(ted.ParseFromArray(desc_raw.data(), desc_raw.size()));
4920       EXPECT_EQ(ted.available_categories_size(), 1);
4921       EXPECT_EQ(ted.available_categories()[0].name(), "new_cat");
4922     }
4923   }
4924   EXPECT_TRUE(found_ds);
4925   perfetto::test::TracingMuxerImplInternalsForTest::
4926       ClearDataSourceTlsStateOnReset<UpdateTestDataSource>();
4927 }
4928 
TEST_P(PerfettoApiTest,NoFlushFlag)4929 TEST_P(PerfettoApiTest, NoFlushFlag) {
4930   class NoFlushDataSource : public perfetto::DataSource<NoFlushDataSource> {};
4931 
4932   class FlushDataSource : public perfetto::DataSource<FlushDataSource> {
4933    public:
4934     void OnFlush(const FlushArgs&) override {}
4935   };
4936 
4937   perfetto::DataSourceDescriptor dsd_no_flush;
4938   dsd_no_flush.set_name("no_flush_data_source");
4939   RegisterDataSource<NoFlushDataSource>(dsd_no_flush);
4940 
4941   perfetto::DataSourceDescriptor dsd_flush;
4942   dsd_flush.set_name("flush_data_source");
4943   RegisterDataSource<FlushDataSource>(dsd_flush);
4944 
4945   auto cleanup = MakeCleanup([&] {
4946     perfetto::test::TracingMuxerImplInternalsForTest::
4947         ClearDataSourceTlsStateOnReset<FlushDataSource>();
4948     perfetto::test::TracingMuxerImplInternalsForTest::
4949         ClearDataSourceTlsStateOnReset<NoFlushDataSource>();
4950   });
4951 
4952   auto tracing_session = perfetto::Tracing::NewTrace(/*backend=*/GetParam());
4953 
4954   perfetto::test::SyncProducers();
4955 
4956   auto result = tracing_session->QueryServiceStateBlocking();
4957   perfetto::protos::gen::TracingServiceState state;
4958   ASSERT_TRUE(result.success);
4959   ASSERT_TRUE(state.ParseFromArray(result.service_state_data.data(),
4960                                    result.service_state_data.size()));
4961   size_t ds_count_no_flush = 0;
4962   size_t ds_count_flush = 0;
4963   size_t ds_count_track_event = 0;
4964   for (const auto& ds : state.data_sources()) {
4965     if (ds.ds_descriptor().name() == "no_flush_data_source") {
4966       EXPECT_TRUE(ds.ds_descriptor().no_flush());
4967       ds_count_no_flush++;
4968     } else if (ds.ds_descriptor().name() == "flush_data_source") {
4969       EXPECT_FALSE(ds.ds_descriptor().no_flush());
4970       ds_count_flush++;
4971     } else if (ds.ds_descriptor().name() == "track_event") {
4972       EXPECT_TRUE(ds.ds_descriptor().no_flush());
4973       ds_count_track_event++;
4974     }
4975   }
4976   EXPECT_EQ(ds_count_no_flush, 1u);
4977   EXPECT_EQ(ds_count_flush, 1u);
4978   EXPECT_EQ(ds_count_track_event, 1u);
4979 
4980   dsd_no_flush.set_track_event_descriptor_raw("DESC_NO");
4981   UpdateDataSource<NoFlushDataSource>(dsd_no_flush);
4982   dsd_flush.set_track_event_descriptor_raw("DESC_");
4983   UpdateDataSource<FlushDataSource>(dsd_flush);
4984 
4985   result = tracing_session->QueryServiceStateBlocking();
4986   ASSERT_TRUE(result.success);
4987   ASSERT_TRUE(state.ParseFromArray(result.service_state_data.data(),
4988                                    result.service_state_data.size()));
4989   ds_count_no_flush = 0;
4990   ds_count_flush = 0;
4991   for (const auto& ds : state.data_sources()) {
4992     if (ds.ds_descriptor().name() == "no_flush_data_source") {
4993       EXPECT_TRUE(ds.ds_descriptor().no_flush());
4994       EXPECT_EQ(ds.ds_descriptor().track_event_descriptor_raw(), "DESC_NO");
4995       ds_count_no_flush++;
4996     } else if (ds.ds_descriptor().name() == "flush_data_source") {
4997       EXPECT_FALSE(ds.ds_descriptor().no_flush());
4998       EXPECT_EQ(ds.ds_descriptor().track_event_descriptor_raw(), "DESC_");
4999       ds_count_flush++;
5000     }
5001   }
5002   EXPECT_EQ(ds_count_no_flush, 1u);
5003   EXPECT_EQ(ds_count_flush, 1u);
5004 }
5005 
TEST_P(PerfettoApiTest,LegacyTraceEventsCopyDynamicString)5006 TEST_P(PerfettoApiTest, LegacyTraceEventsCopyDynamicString) {
5007   char ptr1[] = "A1";
5008   char ptr2[] = "B1";
5009   char arg_name1[] = "C1";
5010   char arg_name2[] = "D1";
5011   auto* tracing_session = NewTraceWithCategories({"cat"});
5012   tracing_session->get()->StartBlocking();
5013   {
5014     TRACE_EVENT_MARK_WITH_TIMESTAMP0("cat", ptr1, MyTimestamp{0});
5015     ptr1[1] = '3';
5016     // Old value of event name ("A1") is recorded here in trace.
5017     // The reason being, in legacy macros, event name was expected to be static
5018     // by default unless `_COPY` version of these macro is used.
5019     // Perfetto is caching pointer values and if a event-name-pointer matches an
5020     // existing pointer, it ASSUMES the string-value of new pointer is same as
5021     // string-value of the cached pointer when it was cached.
5022     // and hence it assign the same intern-id to second event.
5023     TRACE_EVENT_MARK_WITH_TIMESTAMP0("cat", ptr1, MyTimestamp{0});
5024   }
5025   {
5026     TRACE_EVENT_COPY_MARK_WITH_TIMESTAMP("cat", ptr2, MyTimestamp{0});
5027     ptr2[1] = '4';
5028     TRACE_EVENT_COPY_MARK_WITH_TIMESTAMP("cat", ptr2, MyTimestamp{0});
5029   }
5030   {
5031     TRACE_EVENT_INSTANT1("cat", "event_name", TRACE_EVENT_FLAG_NONE, arg_name1,
5032                          /*arg_value=*/5);
5033     arg_name1[1] = '5';
5034     // Since we don't use the _COPY version here, this event will record the old
5035     // value of arg_name1 (see earlier comment for full explanation).
5036     TRACE_EVENT_INSTANT1("cat", "event_name", TRACE_EVENT_FLAG_NONE, arg_name1,
5037                          /*arg_value=*/5);
5038   }
5039   {
5040     TRACE_EVENT_COPY_INSTANT1("cat", "event_name", TRACE_EVENT_FLAG_NONE,
5041                               arg_name2, /*arg_value=*/5);
5042     arg_name2[1] = '6';
5043     TRACE_EVENT_COPY_INSTANT1("cat", "event_name", TRACE_EVENT_FLAG_NONE,
5044                               arg_name2, /*arg_value=*/5);
5045   }
5046   auto slices = StopSessionAndReadSlicesFromTrace(tracing_session);
5047   EXPECT_THAT(
5048       slices,
5049       ElementsAre("[track=0]Legacy_R:cat.A1", "[track=0]Legacy_R:cat.A1",
5050                   "[track=0]Legacy_R:cat.B1", "[track=0]Legacy_R:cat.B4",
5051                   "[track=0]I:cat.event_name(C1=(int)5)",
5052                   "[track=0]I:cat.event_name(C1=(int)5)",
5053                   "[track=0]I:cat.event_name(D1=(int)5)",
5054                   "[track=0]I:cat.event_name(D6=(int)5)"));
5055 }
5056 
TEST_P(PerfettoApiTest,LegacyTraceEvents)5057 TEST_P(PerfettoApiTest, LegacyTraceEvents) {
5058   auto is_new_session = [] {
5059     bool result;
5060     TRACE_EVENT_IS_NEW_TRACE(&result);
5061     return result;
5062   };
5063 
5064   // Create a new trace session.
5065   EXPECT_FALSE(is_new_session());
5066   auto* tracing_session =
5067       NewTraceWithCategories({"cat", TRACE_DISABLED_BY_DEFAULT("cat")});
5068   tracing_session->get()->StartBlocking();
5069   EXPECT_TRUE(is_new_session());
5070   EXPECT_FALSE(is_new_session());
5071 
5072   // Basic events.
5073   TRACE_EVENT_INSTANT0("cat", "LegacyEvent", TRACE_EVENT_SCOPE_GLOBAL);
5074   TRACE_EVENT_BEGIN1("cat", "LegacyEvent", "arg", 123);
5075   TRACE_EVENT_END2("cat", "LegacyEvent", "arg", "string", "arg2", 0.123f);
5076 
5077   // Scoped event.
5078   { TRACE_EVENT0("cat", "ScopedLegacyEvent"); }
5079 
5080   // Event with flow (and disabled category).
5081   TRACE_EVENT_WITH_FLOW0(TRACE_DISABLED_BY_DEFAULT("cat"), "LegacyFlowEvent",
5082                          0xdadacafe, TRACE_EVENT_FLAG_FLOW_IN);
5083 
5084   // Event with timestamp.
5085   TRACE_EVENT_INSTANT_WITH_TIMESTAMP0("cat", "LegacyInstantEvent",
5086                                       TRACE_EVENT_SCOPE_GLOBAL,
5087                                       MyTimestamp{123456789ul});
5088 
5089   // Event with id.
5090   TRACE_COUNTER1("cat", "LegacyCounter", 1234);
5091   TRACE_COUNTER_ID1("cat", "LegacyCounterWithId", 1234, 9000);
5092 
5093   // Metadata event.
5094   TRACE_EVENT_METADATA1("cat", "LegacyMetadata", "obsolete", true);
5095 
5096   // Async events.
5097   TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP_AND_FLAGS0(
5098       "cat", "LegacyAsync", 5678, MyTimestamp{4}, TRACE_EVENT_FLAG_NONE);
5099   TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP0("cat", "LegacyAsync", 5678,
5100                                                  MyTimestamp{5});
5101   TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_FLAGS0("cat", "LegacyAsync2", 9000,
5102                                                TRACE_EVENT_FLAG_NONE);
5103   TRACE_EVENT_NESTABLE_ASYNC_END_WITH_FLAGS0("cat", "LegacyAsync2", 9000,
5104                                              TRACE_EVENT_FLAG_NONE);
5105   TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_FLAGS0("cat", "LegacyAsync3", 9001,
5106                                                TRACE_EVENT_FLAG_NONE);
5107   TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP_AND_FLAGS0(
5108       "cat", "LegacyAsync3", 9001, MyTimestamp{6}, TRACE_EVENT_FLAG_NONE);
5109 
5110   auto slices = StopSessionAndReadSlicesFromTrace(tracing_session);
5111   EXPECT_THAT(
5112       slices,
5113       ElementsAre(
5114           "[track=0]I:cat.LegacyEvent", "B:cat.LegacyEvent(arg=(int)123)",
5115           "E(arg=(string)string,arg2=(double)0.123)", "B:cat.ScopedLegacyEvent",
5116           "E",
5117           "B(bind_id=3671771902)(flow_direction=1):disabled-by-default-cat."
5118           "LegacyFlowEvent",
5119           "[track=0]I:cat.LegacyInstantEvent",
5120           "[track=0]Legacy_C:cat.LegacyCounter(value=(int)1234)",
5121           "[track=0]Legacy_C(unscoped_id=1234):cat.LegacyCounterWithId(value=("
5122           "int)9000)",
5123           "[track=0]Legacy_M:cat.LegacyMetadata",
5124           "[track=0]Legacy_b(unscoped_id=5678):cat.LegacyAsync",
5125           "[track=0]Legacy_e(unscoped_id=5678):cat.LegacyAsync",
5126           "[track=0]Legacy_b(unscoped_id=9000):cat.LegacyAsync2",
5127           "[track=0]Legacy_e(unscoped_id=9000):cat.LegacyAsync2",
5128           "[track=0]Legacy_b(unscoped_id=9001):cat.LegacyAsync3",
5129           "[track=0]Legacy_e(unscoped_id=9001):cat.LegacyAsync3"));
5130 }
5131 
TEST_P(PerfettoApiTest,LegacyTraceEventsAndClockSnapshots)5132 TEST_P(PerfettoApiTest, LegacyTraceEventsAndClockSnapshots) {
5133   auto* tracing_session = NewTraceWithCategories({"cat"});
5134   tracing_session->get()->StartBlocking();
5135 
5136   {
5137     TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("cat", "LegacyAsync", 5678);
5138 
5139     perfetto::test::TracingMuxerImplInternalsForTest::ClearIncrementalState();
5140 
5141     TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0(
5142         "cat", "LegacyAsyncWithTimestamp", 5678, MyTimestamp{1});
5143     TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP0(
5144         "cat", "LegacyAsyncWithTimestamp", 5678, MyTimestamp{2});
5145 
5146     perfetto::test::TracingMuxerImplInternalsForTest::ClearIncrementalState();
5147 
5148     TRACE_EVENT_NESTABLE_ASYNC_END0("cat", "LegacyAsync", 5678);
5149   }
5150 
5151   auto trace = StopSessionAndReturnParsedTrace(tracing_session);
5152 
5153   // Check that clock snapshots are monotonic (per sequence) and don't contain
5154   // timestamps from trace events with explicit timestamps.
5155   struct ClockPerSequence {
5156     uint64_t seq_id = 0;
5157     uint64_t clock_id = 0;
5158     bool operator<(const struct ClockPerSequence& other) const {
5159       return std::tie(seq_id, clock_id) <
5160              std::tie(other.seq_id, other.clock_id);
5161     }
5162   };
5163   std::map<ClockPerSequence, uint64_t> last_clock_ts;
5164   for (const auto& packet : trace.packet()) {
5165     if (packet.has_clock_snapshot()) {
5166       for (auto& clock : packet.clock_snapshot().clocks()) {
5167         if (!clock.is_incremental()) {
5168           uint64_t ts = clock.timestamp();
5169           ClockPerSequence c;
5170           c.seq_id = packet.trusted_packet_sequence_id();
5171           c.clock_id = clock.clock_id();
5172 
5173           uint64_t& last = last_clock_ts[c];
5174 
5175           EXPECT_LE(last, ts)
5176               << "This sequence:" << c.seq_id << " clock_id:" << c.clock_id;
5177           last = ts;
5178         }
5179       }
5180 
5181       // Events that don't use explicit timestamps should have exactly the same
5182       // timestamp as in the snapshot (i.e. the relative ts of 0).
5183       // Here we assume that timestamps are incremental by default.
5184       if (!packet.has_timestamp_clock_id()) {
5185         EXPECT_EQ(packet.timestamp(), 0u);
5186       }
5187     }
5188   }
5189 }
5190 
TEST_P(PerfettoApiTest,LegacyTraceEventsWithCustomAnnotation)5191 TEST_P(PerfettoApiTest, LegacyTraceEventsWithCustomAnnotation) {
5192   // Create a new trace session.
5193   auto* tracing_session = NewTraceWithCategories({"cat"});
5194   tracing_session->get()->StartBlocking();
5195 
5196   MyDebugAnnotation annotation;
5197   TRACE_EVENT_BEGIN1("cat", "LegacyEvent", "arg", annotation);
5198 
5199   std::unique_ptr<MyDebugAnnotation> owned_annotation(new MyDebugAnnotation());
5200   TRACE_EVENT_BEGIN1("cat", "LegacyEvent", "arg", std::move(owned_annotation));
5201 
5202   auto slices = StopSessionAndReadSlicesFromTrace(tracing_session);
5203   EXPECT_THAT(slices,
5204               ElementsAre("B:cat.LegacyEvent(arg=(json){\"key\": 123})",
5205                           "B:cat.LegacyEvent(arg=(json){\"key\": 123})"));
5206 }
5207 
TEST_P(PerfettoApiTest,LegacyTraceEventsWithConcurrentSessions)5208 TEST_P(PerfettoApiTest, LegacyTraceEventsWithConcurrentSessions) {
5209   // Make sure that a uniquely owned debug annotation can be written into
5210   // multiple concurrent tracing sessions.
5211 
5212   auto* tracing_session = NewTraceWithCategories({"cat"});
5213   tracing_session->get()->StartBlocking();
5214 
5215   auto* tracing_session2 = NewTraceWithCategories({"cat"});
5216   tracing_session2->get()->StartBlocking();
5217 
5218   std::unique_ptr<MyDebugAnnotation> owned_annotation(new MyDebugAnnotation());
5219   TRACE_EVENT_BEGIN1("cat", "LegacyEvent", "arg", std::move(owned_annotation));
5220 
5221   auto slices = StopSessionAndReadSlicesFromTrace(tracing_session);
5222   EXPECT_THAT(slices,
5223               ElementsAre("B:cat.LegacyEvent(arg=(json){\"key\": 123})"));
5224 
5225   slices = StopSessionAndReadSlicesFromTrace(tracing_session2);
5226   EXPECT_THAT(slices,
5227               ElementsAre("B:cat.LegacyEvent(arg=(json){\"key\": 123})"));
5228 }
5229 
TEST_P(PerfettoApiTest,LegacyTraceEventsWithId)5230 TEST_P(PerfettoApiTest, LegacyTraceEventsWithId) {
5231   auto* tracing_session = NewTraceWithCategories({"cat"});
5232   tracing_session->get()->StartBlocking();
5233 
5234   TRACE_EVENT_ASYNC_BEGIN0("cat", "UnscopedId", 0x1000);
5235   TRACE_EVENT_ASYNC_BEGIN0("cat", "LocalId", TRACE_ID_LOCAL(0x2000));
5236   TRACE_EVENT_ASYNC_BEGIN0("cat", "GlobalId", TRACE_ID_GLOBAL(0x3000));
5237   TRACE_EVENT_ASYNC_BEGIN0(
5238       "cat", "WithScope",
5239       TRACE_ID_WITH_SCOPE("scope string", TRACE_ID_GLOBAL(0x4000)));
5240 
5241   auto slices = StopSessionAndReadSlicesFromTrace(tracing_session);
5242   EXPECT_THAT(slices,
5243               ElementsAre("[track=0]Legacy_S(unscoped_id=4096):cat.UnscopedId",
5244                           "[track=0]Legacy_S(local_id=8192):cat.LocalId",
5245                           "[track=0]Legacy_S(global_id=12288):cat.GlobalId",
5246                           "[track=0]Legacy_S(global_id=16384)(id_scope=\"scope "
5247                           "string\"):cat.WithScope"));
5248 }
5249 
TEST_P(PerfettoApiTest,NestableAsyncTraceEvent)5250 TEST_P(PerfettoApiTest, NestableAsyncTraceEvent) {
5251   auto* tracing_session = NewTraceWithCategories({"cat"});
5252   tracing_session->get()->StartBlocking();
5253   TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("cat", "foo",
5254                                     TRACE_ID_WITH_SCOPE("foo", 1));
5255   // Same id, different scope.
5256   TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("cat", "bar",
5257                                     TRACE_ID_WITH_SCOPE("bar", 1));
5258   // Same scope, different id.
5259   TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("cat", "bar",
5260                                     TRACE_ID_WITH_SCOPE("bar", 2));
5261 
5262   TRACE_EVENT_NESTABLE_ASYNC_END0("cat", "bar", TRACE_ID_WITH_SCOPE("bar", 2));
5263   TRACE_EVENT_NESTABLE_ASYNC_END0("cat", "bar", TRACE_ID_WITH_SCOPE("bar", 1));
5264   TRACE_EVENT_NESTABLE_ASYNC_END0("cat", "foo", TRACE_ID_WITH_SCOPE("foo", 1));
5265   auto trace = StopSessionAndReturnParsedTrace(tracing_session);
5266   using LegacyEvent = perfetto::protos::gen::TrackEvent::LegacyEvent;
5267   std::vector<const LegacyEvent*> legacy_events;
5268   for (const auto& packet : trace.packet()) {
5269     if (packet.has_track_event() && packet.track_event().has_legacy_event()) {
5270       legacy_events.push_back(&packet.track_event().legacy_event());
5271     }
5272   }
5273   ASSERT_EQ(6u, legacy_events.size());
5274   EXPECT_EQ("foo", legacy_events[0]->id_scope());
5275   EXPECT_EQ("bar", legacy_events[1]->id_scope());
5276   EXPECT_EQ("bar", legacy_events[2]->id_scope());
5277   EXPECT_EQ("bar", legacy_events[3]->id_scope());
5278   EXPECT_EQ("bar", legacy_events[4]->id_scope());
5279   EXPECT_EQ("foo", legacy_events[5]->id_scope());
5280 
5281   EXPECT_EQ(legacy_events[0]->unscoped_id(), legacy_events[5]->unscoped_id());
5282   EXPECT_EQ(legacy_events[1]->unscoped_id(), legacy_events[4]->unscoped_id());
5283   EXPECT_EQ(legacy_events[2]->unscoped_id(), legacy_events[3]->unscoped_id());
5284 
5285   EXPECT_NE(legacy_events[0]->unscoped_id(), legacy_events[1]->unscoped_id());
5286   EXPECT_NE(legacy_events[1]->unscoped_id(), legacy_events[2]->unscoped_id());
5287   EXPECT_NE(legacy_events[2]->unscoped_id(), legacy_events[0]->unscoped_id());
5288 }
5289 
TEST_P(PerfettoApiTest,LegacyTraceEventsWithFlow)5290 TEST_P(PerfettoApiTest, LegacyTraceEventsWithFlow) {
5291   auto* tracing_session = NewTraceWithCategories({"cat"});
5292   tracing_session->get()->StartBlocking();
5293 
5294   const uint64_t flow_id = 1234;
5295   {
5296     TRACE_EVENT_WITH_FLOW1("cat", "LatencyInfo.Flow", TRACE_ID_GLOBAL(flow_id),
5297                            TRACE_EVENT_FLAG_FLOW_OUT, "step", "Begin");
5298   }
5299 
5300   {
5301     TRACE_EVENT_WITH_FLOW2("cat", "LatencyInfo.Flow", TRACE_ID_GLOBAL(flow_id),
5302                            TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
5303                            "step", "Middle", "value", false);
5304   }
5305 
5306   {
5307     TRACE_EVENT_WITH_FLOW1("cat", "LatencyInfo.Flow", TRACE_ID_GLOBAL(flow_id),
5308                            TRACE_EVENT_FLAG_FLOW_IN, "step", "End");
5309   }
5310 
5311   auto slices = StopSessionAndReadSlicesFromTrace(tracing_session);
5312   EXPECT_THAT(slices,
5313               ElementsAre("B(bind_id=1234)(flow_direction=2):cat.LatencyInfo."
5314                           "Flow(step=(string)Begin)",
5315                           "E",
5316                           "B(bind_id=1234)(flow_direction=3):cat.LatencyInfo."
5317                           "Flow(step=(string)Middle,value=(bool)0)",
5318                           "E",
5319                           "B(bind_id=1234)(flow_direction=1):cat.LatencyInfo."
5320                           "Flow(step=(string)End)",
5321                           "E"));
5322 }
5323 
TEST_P(PerfettoApiTest,LegacyCategoryGroupEnabledState)5324 TEST_P(PerfettoApiTest, LegacyCategoryGroupEnabledState) {
5325   bool foo_status;
5326   bool bar_status;
5327   bool dynamic_status;
5328   TRACE_EVENT_CATEGORY_GROUP_ENABLED("foo", &foo_status);
5329   TRACE_EVENT_CATEGORY_GROUP_ENABLED("bar", &bar_status);
5330   TRACE_EVENT_CATEGORY_GROUP_ENABLED("dynamic", &dynamic_status);
5331   EXPECT_FALSE(foo_status);
5332   EXPECT_FALSE(bar_status);
5333   EXPECT_FALSE(dynamic_status);
5334 
5335   const uint8_t* foo_enabled =
5336       TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED("foo");
5337   const uint8_t* bar_enabled =
5338       TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED("bar");
5339   EXPECT_FALSE(*foo_enabled);
5340   EXPECT_FALSE(*bar_enabled);
5341 
5342   // The category group enabled pointer can also be retrieved with a
5343   // runtime-computed category name.
5344   std::string computed_cat("cat");
5345   const uint8_t* computed_enabled =
5346       TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(computed_cat.c_str());
5347   EXPECT_FALSE(*computed_enabled);
5348 
5349   // The enabled pointers can be converted back to category names.
5350   EXPECT_EQ("foo", TRACE_EVENT_API_GET_CATEGORY_GROUP_NAME(foo_enabled));
5351   EXPECT_EQ("bar", TRACE_EVENT_API_GET_CATEGORY_GROUP_NAME(bar_enabled));
5352   EXPECT_EQ("cat", TRACE_EVENT_API_GET_CATEGORY_GROUP_NAME(computed_enabled));
5353 
5354   auto* tracing_session = NewTraceWithCategories({"foo", "dynamic", "cat"});
5355   tracing_session->get()->StartBlocking();
5356   TRACE_EVENT_CATEGORY_GROUP_ENABLED("foo", &foo_status);
5357   TRACE_EVENT_CATEGORY_GROUP_ENABLED("bar", &bar_status);
5358   TRACE_EVENT_CATEGORY_GROUP_ENABLED("dynamic", &dynamic_status);
5359   EXPECT_TRUE(foo_status);
5360   EXPECT_FALSE(bar_status);
5361   EXPECT_TRUE(dynamic_status);
5362 
5363   EXPECT_TRUE(*foo_enabled);
5364   EXPECT_FALSE(*bar_enabled);
5365   EXPECT_TRUE(*computed_enabled);
5366 
5367   tracing_session->get()->StopBlocking();
5368   TRACE_EVENT_CATEGORY_GROUP_ENABLED("foo", &foo_status);
5369   TRACE_EVENT_CATEGORY_GROUP_ENABLED("bar", &bar_status);
5370   TRACE_EVENT_CATEGORY_GROUP_ENABLED("dynamic", &dynamic_status);
5371   EXPECT_FALSE(foo_status);
5372   EXPECT_FALSE(bar_status);
5373   EXPECT_FALSE(dynamic_status);
5374   EXPECT_FALSE(*foo_enabled);
5375   EXPECT_FALSE(*bar_enabled);
5376   EXPECT_FALSE(*computed_enabled);
5377 }
5378 
TEST_P(PerfettoApiTest,CategoryEnabledState)5379 TEST_P(PerfettoApiTest, CategoryEnabledState) {
5380   perfetto::DynamicCategory dynamic{"dynamic"};
5381   EXPECT_FALSE(TRACE_EVENT_CATEGORY_ENABLED("foo"));
5382   EXPECT_FALSE(TRACE_EVENT_CATEGORY_ENABLED("bar"));
5383   EXPECT_FALSE(TRACE_EVENT_CATEGORY_ENABLED("red,green,blue,foo"));
5384   EXPECT_FALSE(TRACE_EVENT_CATEGORY_ENABLED("dynamic"));
5385   EXPECT_FALSE(TRACE_EVENT_CATEGORY_ENABLED("dynamic_2"));
5386   EXPECT_FALSE(TRACE_EVENT_CATEGORY_ENABLED(dynamic));
5387 
5388   auto* tracing_session = NewTraceWithCategories({"foo", "dynamic"});
5389   tracing_session->get()->StartBlocking();
5390   EXPECT_TRUE(TRACE_EVENT_CATEGORY_ENABLED("foo"));
5391   EXPECT_FALSE(TRACE_EVENT_CATEGORY_ENABLED("bar"));
5392   EXPECT_TRUE(TRACE_EVENT_CATEGORY_ENABLED("red,green,blue,foo"));
5393   EXPECT_TRUE(TRACE_EVENT_CATEGORY_ENABLED("dynamic"));
5394   EXPECT_FALSE(TRACE_EVENT_CATEGORY_ENABLED("dynamic_2"));
5395   EXPECT_TRUE(TRACE_EVENT_CATEGORY_ENABLED(dynamic));
5396 
5397   tracing_session->get()->StopBlocking();
5398   EXPECT_FALSE(TRACE_EVENT_CATEGORY_ENABLED("foo"));
5399   EXPECT_FALSE(TRACE_EVENT_CATEGORY_ENABLED("bar"));
5400   EXPECT_FALSE(TRACE_EVENT_CATEGORY_ENABLED("red,green,blue,foo"));
5401   EXPECT_FALSE(TRACE_EVENT_CATEGORY_ENABLED("dynamic"));
5402   EXPECT_FALSE(TRACE_EVENT_CATEGORY_ENABLED("dynamic_2"));
5403   EXPECT_FALSE(TRACE_EVENT_CATEGORY_ENABLED(dynamic));
5404 }
5405 
5406 class TestInterceptor : public perfetto::Interceptor<TestInterceptor> {
5407  public:
5408   static TestInterceptor* instance;
5409 
5410   struct ThreadLocalState : public perfetto::InterceptorBase::ThreadLocalState {
ThreadLocalState__anonfc73210d0111::TestInterceptor::ThreadLocalState5411     ThreadLocalState(ThreadLocalStateArgs& args) {
5412       // Test accessing instance state from the TLS constructor.
5413       if (auto self = args.GetInterceptorLocked()) {
5414         self->tls_initialized = true;
5415       }
5416     }
5417 
5418     std::map<uint64_t, std::string> event_names;
5419   };
5420 
TestInterceptor(const std::string & constructor_arg)5421   TestInterceptor(const std::string& constructor_arg) {
5422     EXPECT_EQ(constructor_arg, "Constructor argument");
5423     // Note: some tests in this suite register multiple track event data
5424     // sources. We only track data for the first in this test.
5425     if (!instance)
5426       instance = this;
5427   }
5428 
~TestInterceptor()5429   ~TestInterceptor() override {
5430     if (instance != this)
5431       return;
5432     instance = nullptr;
5433     EXPECT_TRUE(setup_called);
5434     EXPECT_TRUE(start_called);
5435     EXPECT_TRUE(stop_called);
5436     EXPECT_TRUE(tls_initialized);
5437   }
5438 
OnSetup(const SetupArgs &)5439   void OnSetup(const SetupArgs&) override {
5440     EXPECT_FALSE(setup_called);
5441     EXPECT_FALSE(start_called);
5442     EXPECT_FALSE(stop_called);
5443     setup_called = true;
5444   }
5445 
OnStart(const StartArgs &)5446   void OnStart(const StartArgs&) override {
5447     EXPECT_TRUE(setup_called);
5448     EXPECT_FALSE(start_called);
5449     EXPECT_FALSE(stop_called);
5450     start_called = true;
5451   }
5452 
OnStop(const StopArgs &)5453   void OnStop(const StopArgs&) override {
5454     EXPECT_TRUE(setup_called);
5455     EXPECT_TRUE(start_called);
5456     EXPECT_FALSE(stop_called);
5457     stop_called = true;
5458   }
5459 
OnTracePacket(InterceptorContext context)5460   static void OnTracePacket(InterceptorContext context) {
5461     perfetto::protos::pbzero::TracePacket::Decoder packet(
5462         context.packet_data.data, context.packet_data.size);
5463     EXPECT_TRUE(packet.trusted_packet_sequence_id() > 0);
5464     {
5465       auto self = context.GetInterceptorLocked();
5466       ASSERT_TRUE(self);
5467       EXPECT_TRUE(self->setup_called);
5468       EXPECT_TRUE(self->start_called);
5469       EXPECT_FALSE(self->stop_called);
5470       EXPECT_TRUE(self->tls_initialized);
5471     }
5472 
5473     auto& tls = context.GetThreadLocalState();
5474     if (packet.sequence_flags() &
5475         perfetto::protos::pbzero::TracePacket::SEQ_INCREMENTAL_STATE_CLEARED) {
5476       tls.event_names.clear();
5477     }
5478     if (packet.has_interned_data()) {
5479       perfetto::protos::pbzero::InternedData::Decoder interned_data(
5480           packet.interned_data());
5481       for (auto it = interned_data.event_names(); it; it++) {
5482         perfetto::protos::pbzero::EventName::Decoder entry(*it);
5483         tls.event_names[entry.iid()] = entry.name().ToStdString();
5484       }
5485     }
5486     if (packet.has_track_event()) {
5487       perfetto::protos::pbzero::TrackEvent::Decoder track_event(
5488           packet.track_event());
5489       uint64_t name_iid = track_event.name_iid();
5490       auto self = context.GetInterceptorLocked();
5491       self->events.push_back(tls.event_names[name_iid].c_str());
5492     }
5493   }
5494 
5495   bool setup_called = false;
5496   bool start_called = false;
5497   bool stop_called = false;
5498   bool tls_initialized = false;
5499   std::vector<std::string> events;
5500 };
5501 
5502 TestInterceptor* TestInterceptor::instance;
5503 
TEST_P(PerfettoApiTest,TracePacketInterception)5504 TEST_P(PerfettoApiTest, TracePacketInterception) {
5505   perfetto::InterceptorDescriptor desc;
5506   desc.set_name("test_interceptor");
5507   TestInterceptor::Register(desc, std::string("Constructor argument"));
5508 
5509   perfetto::TraceConfig cfg;
5510   cfg.set_duration_ms(500);
5511   cfg.add_buffers()->set_size_kb(1024);
5512   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
5513   ds_cfg->set_name("track_event");
5514   ds_cfg->mutable_interceptor_config()->set_name("test_interceptor");
5515 
5516   auto* tracing_session = NewTrace(cfg);
5517   tracing_session->get()->StartBlocking();
5518   EXPECT_EQ(0u, TestInterceptor::instance->events.size());
5519 
5520   // The interceptor should see an event immediately without any explicit
5521   // flushing.
5522   TRACE_EVENT_BEGIN("foo", "Hip");
5523   EXPECT_THAT(TestInterceptor::instance->events, ElementsAre("Hip"));
5524 
5525   // Emit another event with the same title to test interning.
5526   TRACE_EVENT_BEGIN("foo", "Hip");
5527   EXPECT_THAT(TestInterceptor::instance->events, ElementsAre("Hip", "Hip"));
5528 
5529   // Emit an event from another thread. It should still reach the same
5530   // interceptor instance.
5531   std::thread thread([] { TRACE_EVENT_BEGIN("foo", "Hooray"); });
5532   thread.join();
5533   EXPECT_THAT(TestInterceptor::instance->events,
5534               ElementsAre("Hip", "Hip", "Hooray"));
5535 
5536   // Emit a packet that spans multiple segments and must be stitched together.
5537   TestInterceptor::instance->events.clear();
5538   static char long_title[8192];
5539   memset(long_title, 'a', sizeof(long_title) - 1);
5540   long_title[sizeof(long_title) - 1] = 0;
5541   TRACE_EVENT_BEGIN("foo", long_title);
5542   EXPECT_THAT(TestInterceptor::instance->events, ElementsAre(long_title));
5543 
5544   tracing_session->get()->StopBlocking();
5545 }
5546 
EmitConsoleEvents()5547 void EmitConsoleEvents() {
5548   TRACE_EVENT_INSTANT("foo", "Instant event");
5549   TRACE_EVENT("foo", "Scoped event");
5550   TRACE_EVENT_BEGIN("foo", "Nested event");
5551   TRACE_EVENT_INSTANT("foo", "Instant event");
5552   TRACE_EVENT_INSTANT("foo", "Annotated event", "foo", 1, "bar", "hello");
5553   TRACE_EVENT_END("foo");
5554   uint64_t async_id = 4004;
5555   auto track = perfetto::Track(async_id, perfetto::ThreadTrack::Current());
5556   auto desc = track.Serialize();
5557   desc.set_name("AsyncTrack");
5558   perfetto::TrackEvent::SetTrackDescriptor(track, std::move(desc));
5559   TRACE_EVENT_BEGIN("test", "AsyncEvent", track);
5560 
5561   std::thread thread([&] {
5562     TRACE_EVENT("foo", "EventFromAnotherThread");
5563     TRACE_EVENT_INSTANT("foo", "Instant event");
5564     TRACE_EVENT_END("test", track);
5565   });
5566   thread.join();
5567 
5568   TRACE_EVENT_INSTANT(
5569       "foo", "More annotations", "dict",
5570       [](perfetto::TracedValue context) {
5571         auto dict = std::move(context).WriteDictionary();
5572         dict.Add("key", 123);
5573       },
5574       "array",
5575       [](perfetto::TracedValue context) {
5576         auto array = std::move(context).WriteArray();
5577         array.Append("first");
5578         array.Append("second");
5579       });
5580 }
5581 
TEST_P(PerfettoApiTest,ConsoleInterceptorPrint)5582 TEST_P(PerfettoApiTest, ConsoleInterceptorPrint) {
5583   perfetto::ConsoleInterceptor::Register();
5584 
5585   perfetto::TraceConfig cfg;
5586   cfg.set_duration_ms(500);
5587   cfg.add_buffers()->set_size_kb(1024);
5588   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
5589   ds_cfg->set_name("track_event");
5590   ds_cfg->mutable_interceptor_config()->set_name("console");
5591 
5592   auto* tracing_session = NewTrace(cfg);
5593   tracing_session->get()->StartBlocking();
5594   EmitConsoleEvents();
5595   tracing_session->get()->StopBlocking();
5596 }
5597 
TEST_P(PerfettoApiTest,ConsoleInterceptorVerify)5598 TEST_P(PerfettoApiTest, ConsoleInterceptorVerify) {
5599   perfetto::ConsoleInterceptor::Register();
5600   auto temp_file = perfetto::test::CreateTempFile();
5601   perfetto::ConsoleInterceptor::SetOutputFdForTesting(temp_file.fd);
5602 
5603   perfetto::TraceConfig cfg;
5604   cfg.set_duration_ms(500);
5605   cfg.add_buffers()->set_size_kb(1024);
5606   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
5607   ds_cfg->set_name("track_event");
5608   ds_cfg->mutable_interceptor_config()->set_name("console");
5609 
5610   auto* tracing_session = NewTrace(cfg);
5611   tracing_session->get()->StartBlocking();
5612   EmitConsoleEvents();
5613   tracing_session->get()->StopBlocking();
5614   perfetto::ConsoleInterceptor::SetOutputFdForTesting(0);
5615 
5616   std::vector<std::string> lines;
5617   FILE* f = fdopen(temp_file.fd, "r");
5618   fseek(f, 0u, SEEK_SET);
5619   std::array<char, 128> line{};
5620   while (fgets(line.data(), line.size(), f)) {
5621     // Ignore timestamps and process/thread ids.
5622     std::string s(line.data() + 28);
5623     // Filter out durations.
5624     s = std::regex_replace(s, std::regex(" [+][0-9]*ms"), "");
5625     lines.push_back(std::move(s));
5626   }
5627   fclose(f);
5628   EXPECT_EQ(0, remove(temp_file.path.c_str()));
5629 
5630   // clang-format off
5631   std::vector<std::string> golden_lines = {
5632       "foo   Instant event\n",
5633       "foo   Scoped event {\n",
5634       "foo   -  Nested event {\n",
5635       "foo   -  -  Instant event\n",
5636       "foo   -  -  Annotated event(foo:1, bar:hello)\n",
5637       "foo   -  } Nested event\n",
5638       "test  AsyncEvent {\n",
5639       "foo   EventFromAnotherThread {\n",
5640       "foo   -  Instant event\n",
5641       "test  } AsyncEvent\n",
5642       "foo   } EventFromAnotherThread\n",
5643       "foo   -  More annotations(dict:{key:123}, array:[first, second])\n",
5644       "foo   } Scoped event\n",
5645   };
5646   // clang-format on
5647   EXPECT_THAT(lines, ContainerEq(golden_lines));
5648 }
5649 
TEST_P(PerfettoApiTest,TrackEventObserver)5650 TEST_P(PerfettoApiTest, TrackEventObserver) {
5651   class Observer : public perfetto::TrackEventSessionObserver {
5652    public:
5653     ~Observer() override = default;
5654 
5655     void OnSetup(const perfetto::DataSourceBase::SetupArgs&) {
5656       // Since other tests here register multiple track event data sources,
5657       // ignore all but the first notifications.
5658       if (setup_called)
5659         return;
5660       setup_called = true;
5661       if (unsubscribe_at_setup)
5662         perfetto::TrackEvent::RemoveSessionObserver(this);
5663       // This event isn't recorded in the trace because tracing isn't active yet
5664       // when OnSetup is called.
5665       TRACE_EVENT_INSTANT("foo", "OnSetup");
5666       // However the active tracing categories have already been updated at this
5667       // point.
5668       EXPECT_TRUE(perfetto::TrackEvent::IsEnabled());
5669       EXPECT_TRUE(TRACE_EVENT_CATEGORY_ENABLED("foo"));
5670     }
5671 
5672     void OnStart(const perfetto::DataSourceBase::StartArgs&) {
5673       if (start_called)
5674         return;
5675       start_called = true;
5676       EXPECT_TRUE(perfetto::TrackEvent::IsEnabled());
5677       EXPECT_TRUE(TRACE_EVENT_CATEGORY_ENABLED("foo"));
5678       TRACE_EVENT_INSTANT("foo", "OnStart");
5679     }
5680 
5681     void OnStop(const perfetto::DataSourceBase::StopArgs&) {
5682       if (stop_called)
5683         return;
5684       stop_called = true;
5685       EXPECT_TRUE(perfetto::TrackEvent::IsEnabled());
5686       EXPECT_TRUE(TRACE_EVENT_CATEGORY_ENABLED("foo"));
5687       TRACE_EVENT_INSTANT("foo", "OnStop");
5688       perfetto::TrackEvent::Flush();
5689     }
5690 
5691     bool setup_called{};
5692     bool start_called{};
5693     bool stop_called{};
5694     bool unsubscribe_at_setup{};
5695   };
5696 
5697   EXPECT_FALSE(perfetto::TrackEvent::IsEnabled());
5698   {
5699     Observer observer;
5700     perfetto::TrackEvent::AddSessionObserver(&observer);
5701 
5702     auto* tracing_session = NewTraceWithCategories({"foo"});
5703     tracing_session->get()->StartBlocking();
5704     EXPECT_TRUE(observer.setup_called);
5705     EXPECT_TRUE(observer.start_called);
5706     tracing_session->get()->StopBlocking();
5707     EXPECT_TRUE(observer.stop_called);
5708     perfetto::TrackEvent::RemoveSessionObserver(&observer);
5709     auto slices = ReadSlicesFromTraceSession(tracing_session->get());
5710     EXPECT_THAT(slices, ElementsAre("I:foo.OnStart", "I:foo.OnStop"));
5711   }
5712 
5713   // No notifications after removing observer.
5714   {
5715     Observer observer;
5716     perfetto::TrackEvent::AddSessionObserver(&observer);
5717     perfetto::TrackEvent::RemoveSessionObserver(&observer);
5718     auto* tracing_session = NewTraceWithCategories({"foo"});
5719     tracing_session->get()->StartBlocking();
5720     EXPECT_FALSE(observer.setup_called);
5721     EXPECT_FALSE(observer.start_called);
5722     tracing_session->get()->StopBlocking();
5723     EXPECT_FALSE(observer.stop_called);
5724   }
5725 
5726   // Removing observer in a callback.
5727   {
5728     Observer observer;
5729     observer.unsubscribe_at_setup = true;
5730     perfetto::TrackEvent::AddSessionObserver(&observer);
5731     auto* tracing_session = NewTraceWithCategories({"foo"});
5732     tracing_session->get()->StartBlocking();
5733     EXPECT_TRUE(observer.setup_called);
5734     EXPECT_FALSE(observer.start_called);
5735     tracing_session->get()->StopBlocking();
5736     EXPECT_FALSE(observer.stop_called);
5737     perfetto::TrackEvent::RemoveSessionObserver(&observer);
5738   }
5739 
5740   // Multiple observers.
5741   {
5742     Observer observer1;
5743     Observer observer2;
5744     perfetto::TrackEvent::AddSessionObserver(&observer1);
5745     perfetto::TrackEvent::AddSessionObserver(&observer2);
5746     auto* tracing_session = NewTraceWithCategories({"foo"});
5747     tracing_session->get()->StartBlocking();
5748     tracing_session->get()->StopBlocking();
5749     perfetto::TrackEvent::RemoveSessionObserver(&observer1);
5750     perfetto::TrackEvent::RemoveSessionObserver(&observer2);
5751     auto slices = ReadSlicesFromTraceSession(tracing_session->get());
5752     EXPECT_THAT(slices, ElementsAre("I:foo.OnStart", "I:foo.OnStart",
5753                                     "I:foo.OnStop", "I:foo.OnStop"));
5754   }
5755 
5756   // Multiple observers with one being removed midway.
5757   {
5758     Observer observer1;
5759     Observer observer2;
5760     perfetto::TrackEvent::AddSessionObserver(&observer1);
5761     perfetto::TrackEvent::AddSessionObserver(&observer2);
5762     auto* tracing_session = NewTraceWithCategories({"foo"});
5763     tracing_session->get()->StartBlocking();
5764     perfetto::TrackEvent::RemoveSessionObserver(&observer1);
5765     tracing_session->get()->StopBlocking();
5766     perfetto::TrackEvent::RemoveSessionObserver(&observer2);
5767     auto slices = ReadSlicesFromTraceSession(tracing_session->get());
5768     EXPECT_THAT(slices,
5769                 ElementsAre("I:foo.OnStart", "I:foo.OnStart", "I:foo.OnStop"));
5770   }
5771   EXPECT_FALSE(perfetto::TrackEvent::IsEnabled());
5772 }
5773 
TEST_P(PerfettoApiTest,TrackEventObserver_ClearIncrementalState)5774 TEST_P(PerfettoApiTest, TrackEventObserver_ClearIncrementalState) {
5775   class Observer : public perfetto::TrackEventSessionObserver {
5776    public:
5777     ~Observer() override = default;
5778 
5779     void OnStart(const perfetto::DataSourceBase::StartArgs&) {
5780       EXPECT_TRUE(perfetto::TrackEvent::IsEnabled());
5781       EXPECT_TRUE(TRACE_EVENT_CATEGORY_ENABLED("foo"));
5782       TRACE_EVENT_INSTANT("foo", "OnStart");
5783     }
5784 
5785     void WillClearIncrementalState(
5786         const perfetto::DataSourceBase::ClearIncrementalStateArgs&) {
5787       if (clear_incremental_state_called)
5788         return;
5789       clear_incremental_state_called = true;
5790       EXPECT_TRUE(perfetto::TrackEvent::IsEnabled());
5791       EXPECT_TRUE(TRACE_EVENT_CATEGORY_ENABLED("foo"));
5792       TRACE_EVENT_INSTANT("foo", "WillClearIncrementalState");
5793       perfetto::TrackEvent::Flush();
5794     }
5795 
5796     bool clear_incremental_state_called{};
5797   };
5798 
5799   EXPECT_FALSE(perfetto::TrackEvent::IsEnabled());
5800   {
5801     Observer observer;
5802     perfetto::TrackEvent::AddSessionObserver(&observer);
5803 
5804     perfetto::TraceConfig cfg;
5805     cfg.mutable_incremental_state_config()->set_clear_period_ms(100);
5806     auto* tracing_session = NewTraceWithCategories({"foo"}, {}, cfg);
5807 
5808     tracing_session->get()->StartBlocking();
5809     tracing_session->on_stop.Wait();
5810 
5811     EXPECT_TRUE(observer.clear_incremental_state_called);
5812     perfetto::TrackEvent::RemoveSessionObserver(&observer);
5813     auto slices = ReadSlicesFromTraceSession(tracing_session->get());
5814     EXPECT_THAT(slices, ElementsAre("I:foo.OnStart",
5815                                     "I:foo.WillClearIncrementalState"));
5816   }
5817   EXPECT_FALSE(perfetto::TrackEvent::IsEnabled());
5818 }
5819 
TEST_P(PerfettoApiTest,TrackEventObserver_TwoDataSources)5820 TEST_P(PerfettoApiTest, TrackEventObserver_TwoDataSources) {
5821   class Observer : public perfetto::TrackEventSessionObserver {
5822    public:
5823     ~Observer() override = default;
5824 
5825     void OnStart(const perfetto::DataSourceBase::StartArgs&) {
5826       EXPECT_FALSE(start_called);
5827       start_called = true;
5828     }
5829 
5830     bool start_called{};
5831   };
5832 
5833   EXPECT_FALSE(perfetto::TrackEvent::IsEnabled());
5834   EXPECT_FALSE(tracing_module::IsEnabled());
5835 
5836   {
5837     Observer observer1, observer2;
5838     perfetto::TrackEvent::AddSessionObserver(&observer1);
5839     tracing_module::AddSessionObserver(&observer2);
5840 
5841     perfetto::TraceConfig cfg;
5842     auto* tracing_session = NewTraceWithCategories({"foo"}, {}, cfg);
5843 
5844     tracing_session->get()->StartBlocking();
5845     tracing_session->on_stop.Wait();
5846 
5847     // The tracing_module hasn't registered its data source yet, so observer2
5848     // should not be notified.
5849     EXPECT_TRUE(observer1.start_called);
5850     EXPECT_FALSE(observer2.start_called);
5851     perfetto::TrackEvent::RemoveSessionObserver(&observer1);
5852     tracing_module::RemoveSessionObserver(&observer2);
5853   }
5854 
5855   tracing_module::InitializeCategories();
5856 
5857   {
5858     Observer observer1, observer2;
5859     perfetto::TrackEvent::AddSessionObserver(&observer1);
5860     tracing_module::AddSessionObserver(&observer2);
5861 
5862     perfetto::TraceConfig cfg;
5863     auto* tracing_session = NewTraceWithCategories({"foo"}, {}, cfg);
5864 
5865     tracing_session->get()->StartBlocking();
5866     tracing_session->on_stop.Wait();
5867 
5868     // Each observer should be notified exactly once.
5869     EXPECT_TRUE(observer1.start_called);
5870     EXPECT_TRUE(observer2.start_called);
5871     perfetto::TrackEvent::RemoveSessionObserver(&observer1);
5872     tracing_module::RemoveSessionObserver(&observer2);
5873   }
5874 
5875   EXPECT_FALSE(perfetto::TrackEvent::IsEnabled());
5876   EXPECT_FALSE(tracing_module::IsEnabled());
5877 }
5878 
TEST_P(PerfettoApiTest,TrackEventObserver_AsyncStop)5879 TEST_P(PerfettoApiTest, TrackEventObserver_AsyncStop) {
5880   class Observer : public perfetto::TrackEventSessionObserver {
5881    public:
5882     ~Observer() override = default;
5883 
5884     void OnStop(const perfetto::DataSourceBase::StopArgs& args) {
5885       async_stop_closure_ = args.HandleStopAsynchronously();
5886     }
5887 
5888     void EmitFinalEvents() {
5889       EXPECT_TRUE(perfetto::TrackEvent::IsEnabled());
5890       EXPECT_TRUE(TRACE_EVENT_CATEGORY_ENABLED("foo"));
5891       TRACE_EVENT_INSTANT("foo", "FinalEvent");
5892       perfetto::TrackEvent::Flush();
5893       async_stop_closure_();
5894     }
5895 
5896    private:
5897     std::function<void()> async_stop_closure_;
5898   };
5899 
5900   EXPECT_FALSE(perfetto::TrackEvent::IsEnabled());
5901   {
5902     Observer observer;
5903     perfetto::TrackEvent::AddSessionObserver(&observer);
5904 
5905     auto* tracing_session = NewTraceWithCategories({"foo"});
5906     WaitableTestEvent consumer_stop_signal;
5907     tracing_session->get()->SetOnStopCallback(
5908         [&consumer_stop_signal] { consumer_stop_signal.Notify(); });
5909     tracing_session->get()->StartBlocking();
5910 
5911     // Stop and wait for the producer to have seen the stop event.
5912     tracing_session->get()->Stop();
5913 
5914     // At this point tracing should be still allowed because of the
5915     // HandleStopAsynchronously() call. This usleep is here just to prevent that
5916     // we accidentally pass the test just by virtue of hitting some race. We
5917     // should be able to trace up until 5 seconds after seeing the stop when
5918     // using the deferred stop mechanism.
5919     std::this_thread::sleep_for(std::chrono::milliseconds(250));
5920     observer.EmitFinalEvents();
5921 
5922     // Wait that the stop is propagated to the consumer.
5923     consumer_stop_signal.Wait();
5924 
5925     perfetto::TrackEvent::RemoveSessionObserver(&observer);
5926     auto slices = ReadSlicesFromTraceSession(tracing_session->get());
5927     EXPECT_THAT(slices, ElementsAre("I:foo.FinalEvent"));
5928   }
5929   EXPECT_FALSE(perfetto::TrackEvent::IsEnabled());
5930 }
5931 
5932 #if PERFETTO_BUILDFLAG(PERFETTO_COMPILER_CLANG)
5933 struct __attribute__((capability("mutex"))) MockMutex {
Lock__anonfc73210d0111::MockMutex5934   void Lock() __attribute__((acquire_capability())) {}
Unlock__anonfc73210d0111::MockMutex5935   void Unlock() __attribute__((release_capability())) {}
5936 };
5937 
5938 struct AnnotatedObject {
5939   MockMutex mutex;
5940   int value __attribute__((guarded_by(mutex))) = {};
5941 };
5942 
TEST_P(PerfettoApiTest,ThreadSafetyAnnotation)5943 TEST_P(PerfettoApiTest, ThreadSafetyAnnotation) {
5944   AnnotatedObject obj;
5945 
5946   // Access to the locked field is only allowed while holding the mutex.
5947   obj.mutex.Lock();
5948   obj.value = 1;
5949   obj.mutex.Unlock();
5950 
5951   auto* tracing_session = NewTraceWithCategories({"cat"});
5952   tracing_session->get()->StartBlocking();
5953 
5954   // It should be possible to trace the field while holding the lock.
5955   obj.mutex.Lock();
5956   TRACE_EVENT_INSTANT("cat", "Instant", "value", obj.value);
5957   TRACE_EVENT_INSTANT1("cat", "InstantLegacy", 0, "value", obj.value);
5958   { TRACE_EVENT("cat", "Scoped", "value", obj.value); }
5959   { TRACE_EVENT1("cat", "ScopedLegacy", "value", obj.value); }
5960   obj.mutex.Unlock();
5961 
5962   auto slices = StopSessionAndReadSlicesFromTrace(tracing_session);
5963   EXPECT_THAT(slices, ElementsAre("I:cat.Instant(value=(int)1)",
5964                                   "[track=0]I:cat.InstantLegacy(value=(int)1)",
5965                                   "B:cat.Scoped(value=(int)1)", "E",
5966                                   "B:cat.ScopedLegacy(value=(int)1)", "E"));
5967 }
5968 #endif  // PERFETTO_BUILDFLAG(PERFETTO_COMPILER_CLANG)
5969 
TEST_P(PerfettoApiTest,CountersDeltaEncoding)5970 TEST_P(PerfettoApiTest, CountersDeltaEncoding) {
5971   auto* tracing_session = NewTraceWithCategories({"cat"});
5972   tracing_session->get()->StartBlocking();
5973 
5974   // Describe a counter track.
5975   perfetto::CounterTrack track1 =
5976       perfetto::CounterTrack("Framerate1", "fps1").set_is_incremental(true);
5977   // Global tracks can be constructed at build time.
5978   constexpr perfetto::CounterTrack track2 =
5979       perfetto::CounterTrack::Global("Framerate2", "fps2")
5980           .set_is_incremental(true);
5981   perfetto::CounterTrack track3 = perfetto::CounterTrack("Framerate3", "fps3");
5982 
5983   TRACE_COUNTER("cat", track1, 120);
5984   TRACE_COUNTER("cat", track2, 1000);
5985   TRACE_COUNTER("cat", track3, 10009);
5986 
5987   TRACE_COUNTER("cat", track1, 10);
5988   TRACE_COUNTER("cat", track1, 1200);
5989   TRACE_COUNTER("cat", track1, 34);
5990 
5991   TRACE_COUNTER("cat", track3, 975);
5992   TRACE_COUNTER("cat", track2, 449);
5993   TRACE_COUNTER("cat", track2, 2);
5994 
5995   TRACE_COUNTER("cat", track3, 1091);
5996   TRACE_COUNTER("cat", track3, 110);
5997   TRACE_COUNTER("cat", track3, 1081);
5998 
5999   TRACE_COUNTER("cat", track1, 98);
6000   TRACE_COUNTER("cat", track2, 1084);
6001 
6002   auto trace = StopSessionAndReturnParsedTrace(tracing_session);
6003   std::unordered_map<uint64_t, std::string> counter_names;
6004   // Map(Counter name -> counter values)
6005   std::unordered_map<std::string, std::vector<int64_t>> values;
6006   for (const auto& packet : trace.packet()) {
6007     if (packet.has_track_descriptor()) {
6008       auto& desc = packet.track_descriptor();
6009       if (!desc.has_counter())
6010         continue;
6011       counter_names[desc.uuid()] =
6012           desc.has_name() ? desc.name() : desc.static_name();
6013       EXPECT_EQ((desc.static_name() != "Framerate3"),
6014                 desc.counter().is_incremental());
6015     }
6016     if (packet.has_track_event()) {
6017       auto event = packet.track_event();
6018       EXPECT_EQ(perfetto::protos::gen::TrackEvent_Type_TYPE_COUNTER,
6019                 event.type());
6020       auto& counter_name = counter_names.at(event.track_uuid());
6021       values[counter_name].push_back(event.counter_value());
6022     }
6023   }
6024   ASSERT_EQ(3u, values.size());
6025   using IntVector = std::vector<int64_t>;
6026   EXPECT_EQ((IntVector{120, -110, 1190, -1166, 64}), values.at("Framerate1"));
6027   EXPECT_EQ((IntVector{1000, -551, -447, 1082}), values.at("Framerate2"));
6028   EXPECT_EQ((IntVector{10009, 975, 1091, 110, 1081}), values.at("Framerate3"));
6029 }
6030 
TEST_P(PerfettoApiTest,Counters)6031 TEST_P(PerfettoApiTest, Counters) {
6032   auto* tracing_session = NewTraceWithCategories({"cat"});
6033   tracing_session->get()->StartBlocking();
6034 
6035   // Describe a counter track.
6036   perfetto::CounterTrack fps_track = perfetto::CounterTrack("Framerate", "fps");
6037 
6038   // Emit an integer sample.
6039   TRACE_COUNTER("cat", fps_track, 120);
6040 
6041   // Global tracks can be constructed at build time.
6042   constexpr auto goats_track =
6043       perfetto::CounterTrack::Global("Goats teleported", "goats x 1000")
6044           .set_unit_multiplier(1000);
6045   static_assert(goats_track.uuid == 0x6072fc234f82df11,
6046                 "Counter track uuid mismatch");
6047 
6048   // Emit some floating point samples.
6049   TRACE_COUNTER("cat", goats_track, 0.25);
6050   TRACE_COUNTER("cat", goats_track, 0.5);
6051   TRACE_COUNTER("cat", goats_track, 0.75);
6052 
6053   // Emit a sample using an inline track name.
6054   TRACE_COUNTER("cat", "Voltage", 220);
6055 
6056   // Emit sample with a custom timestamp.
6057   TRACE_COUNTER("cat",
6058                 perfetto::CounterTrack("Power", "GW").set_category("dmc"),
6059                 MyTimestamp(1985u), 1.21f);
6060   auto trace = StopSessionAndReturnParsedTrace(tracing_session);
6061   std::map<uint64_t, std::string> counter_names;
6062   std::vector<std::string> counter_samples;
6063   for (const auto& packet : trace.packet()) {
6064     if (packet.has_track_event()) {
6065       auto event = packet.track_event();
6066       EXPECT_EQ(perfetto::protos::gen::TrackEvent_Type_TYPE_COUNTER,
6067                 event.type());
6068       std::stringstream sample;
6069       std::string counter_name = counter_names[event.track_uuid()];
6070       sample << counter_name << " = ";
6071       if (event.has_counter_value()) {
6072         sample << event.counter_value();
6073       } else if (event.has_double_counter_value()) {
6074         sample << event.double_counter_value();
6075       }
6076       if (counter_name == "Power") {
6077         EXPECT_EQ(1985u, packet.timestamp());
6078       }
6079       counter_samples.push_back(sample.str());
6080     }
6081 
6082     if (!packet.has_track_descriptor() ||
6083         !packet.track_descriptor().has_counter()) {
6084       continue;
6085     }
6086     auto desc = packet.track_descriptor();
6087     counter_names[desc.uuid()] =
6088         desc.has_name() ? desc.name() : desc.static_name();
6089     if (desc.name() == "Framerate") {
6090       EXPECT_EQ("fps", desc.counter().unit_name());
6091     } else if (desc.name() == "Goats teleported") {
6092       EXPECT_EQ("goats x 1000", desc.counter().unit_name());
6093       EXPECT_EQ(1000, desc.counter().unit_multiplier());
6094     } else if (desc.name() == "Power") {
6095       EXPECT_EQ("GW", desc.counter().unit_name());
6096       EXPECT_EQ("dmc", desc.counter().categories()[0]);
6097     }
6098   }
6099   EXPECT_EQ(4u, counter_names.size());
6100   EXPECT_THAT(counter_samples,
6101               ElementsAre("Framerate = 120", "Goats teleported = 0.25",
6102                           "Goats teleported = 0.5", "Goats teleported = 0.75",
6103                           "Voltage = 220", "Power = 1.21"));
6104 }
6105 
TEST_P(PerfettoApiTest,ScrapingTrackEventBegin)6106 TEST_P(PerfettoApiTest, ScrapingTrackEventBegin) {
6107   auto* tracing_session = NewTraceWithCategories({"test"});
6108   tracing_session->get()->StartBlocking();
6109 
6110   TRACE_EVENT_BEGIN("test", "MainEvent");
6111 
6112   // Stop tracing but don't flush. Rely on scraping to get the chunk contents.
6113   tracing_session->get()->StopBlocking();
6114 
6115   auto slices = ReadSlicesFromTraceSession(tracing_session->get());
6116 
6117   EXPECT_THAT(slices, ElementsAre("B:test.MainEvent"));
6118 }
6119 
TEST_P(PerfettoApiTest,ScrapingTrackEventEnd)6120 TEST_P(PerfettoApiTest, ScrapingTrackEventEnd) {
6121   auto* tracing_session = NewTraceWithCategories({"test"});
6122   tracing_session->get()->StartBlocking();
6123 
6124   TRACE_EVENT_BEGIN("test", "MainEvent");
6125   TRACE_EVENT_END("test");
6126 
6127   // Stop tracing but don't flush. Rely on scraping to get the chunk contents.
6128   tracing_session->get()->StopBlocking();
6129 
6130   auto slices = ReadSlicesFromTraceSession(tracing_session->get());
6131 
6132   EXPECT_THAT(slices, ElementsAre("B:test.MainEvent", "E"));
6133 }
6134 
TEST_P(PerfettoApiTest,EmptyEvent)6135 TEST_P(PerfettoApiTest, EmptyEvent) {
6136   auto* tracing_session = NewTraceWithCategories({"test"});
6137   tracing_session->get()->StartBlocking();
6138 
6139   TRACE_EVENT_BEGIN("test", "MainEvent");
6140 
6141   // An empty event will allow the previous track packet to be scraped.
6142   PERFETTO_INTERNAL_ADD_EMPTY_EVENT();
6143 
6144   // Stop tracing but don't flush. Rely on scraping to get the chunk contents.
6145   tracing_session->get()->StopBlocking();
6146 
6147   auto slices = ReadSlicesFromTraceSession(tracing_session->get());
6148 
6149   EXPECT_THAT(slices, ElementsAre("B:test.MainEvent"));
6150 }
6151 
TEST_P(PerfettoApiTest,ConsecutiveEmptyEventsSkipped)6152 TEST_P(PerfettoApiTest, ConsecutiveEmptyEventsSkipped) {
6153   auto* tracing_session = NewTraceWithCategories({"test"});
6154   tracing_session->get()->StartBlocking();
6155 
6156   TRACE_EVENT_BEGIN("test", "MainEvent");
6157 
6158   // Emit many empty events that wouldn't fit into one chunk.
6159   constexpr int kNumEvents = 10000;
6160   for (int i = 0; i < kNumEvents; ++i) {
6161     PERFETTO_INTERNAL_ADD_EMPTY_EVENT();
6162   }
6163   auto trace = StopSessionAndReturnParsedTrace(tracing_session);
6164   auto it = std::find_if(trace.packet().begin(), trace.packet().end(),
6165                          [](const perfetto::protos::gen::TracePacket& packet) {
6166                            return packet.has_trace_stats();
6167                          });
6168   EXPECT_NE(it, trace.packet().end());
6169   // Extra empty events should be skipped so only one chunk should be allocated.
6170   EXPECT_EQ(it->trace_stats().buffer_stats()[0].chunks_read(), 1u);
6171 }
6172 
6173 // Make sure that we set correct track_uuid for legacy events
6174 // of type TrackEvent::TYPE_UNSPECIFIED.
6175 // For such events we set fields of `track_event.legacy_event` and
6176 // we set `track_event.track_uuid` to zero to dissociate it with
6177 // default track.
TEST_P(PerfettoApiTest,CorrectTrackUUIDForLegacyEvents)6178 TEST_P(PerfettoApiTest, CorrectTrackUUIDForLegacyEvents) {
6179   auto* tracing_session = NewTraceWithCategories({"cat"});
6180   tracing_session->get()->StartBlocking();
6181   TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("cat", "foo",
6182                                     TRACE_ID_WITH_SCOPE("foo", 1));
6183 
6184   auto slices = StopSessionAndReadSlicesFromTrace(tracing_session);
6185   EXPECT_THAT(slices,
6186               ElementsAre("[track=0]Legacy_b(unscoped_id=11250026935264495724)("
6187                           "id_scope=\"foo\"):cat.foo"));
6188 }
6189 
TEST_P(PerfettoApiTest,ActivateTriggers)6190 TEST_P(PerfettoApiTest, ActivateTriggers) {
6191   perfetto::TraceConfig cfg;
6192   cfg.add_buffers()->set_size_kb(1024);
6193   perfetto::TraceConfig::TriggerConfig* tr_cfg = cfg.mutable_trigger_config();
6194   tr_cfg->set_trigger_mode(perfetto::TraceConfig::TriggerConfig::STOP_TRACING);
6195   tr_cfg->set_trigger_timeout_ms(5000);
6196   perfetto::TraceConfig::TriggerConfig::Trigger* trigger =
6197       tr_cfg->add_triggers();
6198   trigger->set_name("trigger1");
6199   auto* tracing_session = NewTrace(cfg);
6200   tracing_session->get()->StartBlocking();
6201 
6202   perfetto::Tracing::ActivateTriggers({"trigger2", "trigger1"}, 10000);
6203 
6204   tracing_session->on_stop.Wait();
6205 
6206   std::vector<char> bytes = tracing_session->get()->ReadTraceBlocking();
6207   perfetto::protos::gen::Trace parsed_trace;
6208   ASSERT_TRUE(parsed_trace.ParseFromArray(bytes.data(), bytes.size()));
6209   EXPECT_THAT(
6210       parsed_trace,
6211       Property(&perfetto::protos::gen::Trace::packet,
6212                Contains(Property(
6213                    &perfetto::protos::gen::TracePacket::trigger,
6214                    Property(&perfetto::protos::gen::Trigger::trigger_name,
6215                             "trigger1")))));
6216 }
6217 
TEST_P(PerfettoApiTest,StartTracingWhileExecutingTracepoint)6218 TEST_P(PerfettoApiTest, StartTracingWhileExecutingTracepoint) {
6219   perfetto::TraceConfig cfg;
6220   auto* buffer = cfg.add_buffers();
6221   buffer->set_size_kb(64);
6222   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
6223   ds_cfg->set_name("my_data_source");
6224 
6225   std::atomic<bool> quit{false};
6226   WaitableTestEvent outside_tracing;
6227   WaitableTestEvent tracing;
6228   std::thread t([&] {
6229     while (!quit) {
6230       MockDataSource::Trace([&](MockDataSource::TraceContext ctx) {
6231         {
6232           auto packet = ctx.NewTracePacket();
6233           packet->set_for_testing()->set_str("My String");
6234         }
6235         { auto packet = ctx.NewTracePacket(); }
6236         tracing.Notify();
6237       });
6238       outside_tracing.Notify();
6239       std::this_thread::yield();
6240     }
6241   });
6242   outside_tracing.Wait();
6243 
6244   auto* tracing_session = NewTrace(cfg);
6245   tracing_session->get()->StartBlocking();
6246   tracing.Wait();
6247   tracing_session->get()->StopBlocking();
6248 
6249   // The data source instance should be stopped.
6250   auto* data_source = &data_sources_["my_data_source"];
6251   data_source->on_stop.Wait();
6252 
6253   quit = true;
6254   t.join();
6255 
6256   auto trace = StopSessionAndReturnParsedTrace(tracing_session);
6257   std::vector<std::string> test_strings;
6258   for (auto& trace_packet : trace.packet()) {
6259     if (trace_packet.has_for_testing()) {
6260       test_strings.push_back(trace_packet.for_testing().str());
6261     }
6262   }
6263   EXPECT_THAT(test_strings, AllOf(Not(IsEmpty()), Each("My String")));
6264 }
6265 
TEST_P(PerfettoApiTest,SystemDisconnect)6266 TEST_P(PerfettoApiTest, SystemDisconnect) {
6267   if (GetParam() != perfetto::kSystemBackend) {
6268     GTEST_SKIP();
6269   }
6270   auto* data_source = &data_sources_["my_data_source"];
6271   data_source->handle_stop_asynchronously = true;
6272 
6273   perfetto::TraceConfig cfg;
6274   auto* buffer = cfg.add_buffers();
6275   buffer->set_size_kb(64);
6276   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
6277   ds_cfg->set_name("my_data_source");
6278   auto* tracing_session = NewTrace(cfg);
6279   tracing_session->get()->StartBlocking();
6280 
6281   std::atomic<bool> quit1{false};
6282   WaitableTestEvent tracing1;
6283   std::atomic<bool> quit2{false};
6284   WaitableTestEvent tracing2;
6285   std::thread t([&] {
6286     while (!quit1) {
6287       MockDataSource::Trace(
6288           [&](MockDataSource::TraceContext) { tracing1.Notify(); });
6289       std::this_thread::yield();
6290     }
6291     while (!quit2) {
6292       MockDataSource::Trace([&](MockDataSource::TraceContext ctx) {
6293         {
6294           auto packet = ctx.NewTracePacket();
6295           packet->set_for_testing()->set_str("New session");
6296         }
6297         { auto packet = ctx.NewTracePacket(); }
6298         tracing2.Notify();
6299       });
6300       std::this_thread::yield();
6301     }
6302   });
6303   auto cleanup = MakeCleanup([&] {
6304     if (t.joinable()) {
6305       quit1 = true;
6306       quit2 = true;
6307       t.join();
6308     }
6309   });
6310   tracing1.Wait();
6311 
6312   // Restarts the system service. This will cause the producer and consumer to
6313   // disconnect.
6314   system_service_.Restart();
6315 
6316   // The data source instance should be stopped.
6317   data_source->on_stop.Wait();
6318 
6319   // The stop is not finalized yet. Test that creating a new trace writer
6320   // doesn't cause any problem.
6321   MockDataSource::Trace([&](MockDataSource::TraceContext ctx) {
6322     {
6323       auto packet = ctx.NewTracePacket();
6324       packet->set_for_testing()->set_str("Content");
6325     }
6326     { auto packet = ctx.NewTracePacket(); }
6327   });
6328 
6329   data_source->async_stop_closure();
6330 
6331   tracing_session->on_stop.Wait();
6332 
6333   std::unique_ptr<perfetto::TracingSession> new_session =
6334       perfetto::Tracing::NewTrace(/*backend=*/GetParam());
6335   // Wait for reconnection
6336   ASSERT_TRUE(WaitForOneProducerConnected(new_session.get()));
6337 
6338   auto* tracing_session2 = NewTrace(cfg);
6339   tracing_session2->get()->StartBlocking();
6340 
6341   quit1 = true;
6342   tracing2.Wait();
6343   quit2 = true;
6344   t.join();
6345 
6346   data_source->handle_stop_asynchronously = false;
6347 
6348   auto trace = StopSessionAndReturnParsedTrace(tracing_session2);
6349   std::vector<std::string> test_strings;
6350   for (auto& trace_packet : trace.packet()) {
6351     if (trace_packet.has_for_testing()) {
6352       test_strings.push_back(trace_packet.for_testing().str());
6353     }
6354   }
6355   EXPECT_THAT(test_strings, AllOf(Not(IsEmpty()), Each("New session")));
6356 }
6357 
TEST_P(PerfettoApiTest,SystemDisconnectAsyncOnStopNoTracing)6358 TEST_P(PerfettoApiTest, SystemDisconnectAsyncOnStopNoTracing) {
6359   if (GetParam() != perfetto::kSystemBackend) {
6360     GTEST_SKIP();
6361   }
6362   auto* data_source = &data_sources_["my_data_source"];
6363   data_source->handle_stop_asynchronously = true;
6364 
6365   perfetto::TraceConfig cfg;
6366   auto* buffer = cfg.add_buffers();
6367   buffer->set_size_kb(64);
6368   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
6369   ds_cfg->set_name("my_data_source");
6370   auto* tracing_session = NewTrace(cfg);
6371   tracing_session->get()->StartBlocking();
6372 
6373   std::atomic<bool> quit1{false};
6374   WaitableTestEvent tracing1;
6375   std::thread t([&] {
6376     while (!quit1) {
6377       MockDataSource::Trace(
6378           [&](MockDataSource::TraceContext) { tracing1.Notify(); });
6379       std::this_thread::yield();
6380     }
6381   });
6382   auto cleanup = MakeCleanup([&] {
6383     if (t.joinable()) {
6384       quit1 = true;
6385       t.join();
6386     }
6387   });
6388   tracing1.Wait();
6389 
6390   // Restarts the system service. This will cause the producer and consumer to
6391   // disconnect.
6392   system_service_.Restart();
6393 
6394   // The data source instance should be stopped. Don't acknowledge the stop yet.
6395   data_source->on_stop.Wait();
6396 
6397   tracing_session->on_stop.Wait();
6398 
6399   std::unique_ptr<perfetto::TracingSession> new_session =
6400       perfetto::Tracing::NewTrace(/*backend=*/GetParam());
6401   // Wait for reconnection
6402   ASSERT_TRUE(WaitForOneProducerConnected(new_session.get()));
6403 
6404   data_source->async_stop_closure();
6405 
6406   data_source->handle_stop_asynchronously = false;
6407 }
6408 
TEST_P(PerfettoApiTest,SystemDisconnectAsyncOnStopRestartTracing)6409 TEST_P(PerfettoApiTest, SystemDisconnectAsyncOnStopRestartTracing) {
6410   if (GetParam() != perfetto::kSystemBackend) {
6411     GTEST_SKIP();
6412   }
6413   auto* data_source = &data_sources_["my_data_source"];
6414   data_source->handle_stop_asynchronously = true;
6415 
6416   perfetto::TraceConfig cfg;
6417   auto* buffer = cfg.add_buffers();
6418   buffer->set_size_kb(64);
6419   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
6420   ds_cfg->set_name("my_data_source");
6421   auto* tracing_session = NewTrace(cfg);
6422   tracing_session->get()->StartBlocking();
6423 
6424   std::atomic<bool> quit1{false};
6425   WaitableTestEvent tracing1;
6426   std::atomic<bool> quit2{false};
6427   WaitableTestEvent tracing2;
6428   std::thread t([&] {
6429     while (!quit1) {
6430       MockDataSource::Trace(
6431           [&](MockDataSource::TraceContext) { tracing1.Notify(); });
6432       std::this_thread::yield();
6433     }
6434     while (!quit2) {
6435       MockDataSource::Trace([&](MockDataSource::TraceContext ctx) {
6436         {
6437           auto packet = ctx.NewTracePacket();
6438           packet->set_for_testing()->set_str("New session");
6439         }
6440         { auto packet = ctx.NewTracePacket(); }
6441         tracing2.Notify();
6442       });
6443       std::this_thread::yield();
6444     }
6445   });
6446   auto cleanup = MakeCleanup([&] {
6447     if (t.joinable()) {
6448       quit1 = true;
6449       quit2 = true;
6450       t.join();
6451     }
6452   });
6453   tracing1.Wait();
6454 
6455   // Restarts the system service. This will cause the producer and consumer to
6456   // disconnect.
6457   system_service_.Restart();
6458 
6459   // The data source instance should be stopped. Don't acknowledge the stop yet.
6460   data_source->on_stop.Wait();
6461 
6462   tracing_session->on_stop.Wait();
6463 
6464   std::unique_ptr<perfetto::TracingSession> new_session =
6465       perfetto::Tracing::NewTrace(/*backend=*/GetParam());
6466   // Wait for reconnection
6467   ASSERT_TRUE(WaitForOneProducerConnected(new_session.get()));
6468 
6469   auto* tracing_session2 = NewTrace(cfg);
6470   tracing_session2->get()->StartBlocking();
6471 
6472   data_source->async_stop_closure();
6473 
6474   quit1 = true;
6475   tracing2.Wait();
6476   quit2 = true;
6477   t.join();
6478 
6479   data_source->handle_stop_asynchronously = false;
6480 
6481   auto trace = StopSessionAndReturnParsedTrace(tracing_session2);
6482   std::vector<std::string> test_strings;
6483   for (auto& trace_packet : trace.packet()) {
6484     if (trace_packet.has_for_testing()) {
6485       test_strings.push_back(trace_packet.for_testing().str());
6486     }
6487   }
6488   EXPECT_THAT(test_strings, AllOf(Not(IsEmpty()), Each("New session")));
6489 }
6490 
TEST_P(PerfettoApiTest,SystemDisconnectWhileStopping)6491 TEST_P(PerfettoApiTest, SystemDisconnectWhileStopping) {
6492   if (GetParam() != perfetto::kSystemBackend) {
6493     GTEST_SKIP();
6494   }
6495   auto* data_source = &data_sources_["my_data_source"];
6496   data_source->handle_stop_asynchronously = true;
6497 
6498   perfetto::TraceConfig cfg;
6499   auto* buffer = cfg.add_buffers();
6500   buffer->set_size_kb(64);
6501   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
6502   ds_cfg->set_name("my_data_source");
6503   auto* tracing_session = NewTrace(cfg);
6504   tracing_session->get()->StartBlocking();
6505   data_source->on_start.Wait();
6506 
6507   // Stop the session and wait until DataSource::OnStop is called. Don't
6508   // complete the async stop yet.
6509   tracing_session->get()->Stop();
6510   data_source->on_stop.Wait();
6511 
6512   // Restart the service. This should not call DataSource::OnStop again while
6513   // another async stop is in progress.
6514   system_service_.Restart();
6515   tracing_session->on_stop.Wait();
6516 
6517   data_source->async_stop_closure();
6518   data_source->handle_stop_asynchronously = false;
6519 }
6520 
TEST_P(PerfettoApiTest,CloneSession)6521 TEST_P(PerfettoApiTest, CloneSession) {
6522   perfetto::TraceConfig cfg;
6523   cfg.set_unique_session_name("test_session");
6524   auto* tracing_session = NewTraceWithCategories({"test"}, {}, cfg);
6525   tracing_session->get()->StartBlocking();
6526 
6527   TRACE_EVENT_BEGIN("test", "TestEvent");
6528   TRACE_EVENT_END("test");
6529 
6530   sessions_.emplace_back();
6531   TestTracingSessionHandle* other_tracing_session = &sessions_.back();
6532   other_tracing_session->session =
6533       perfetto::Tracing::NewTrace(/*backend_type=*/GetParam());
6534 
6535   WaitableTestEvent session_cloned;
6536   other_tracing_session->get()->CloneTrace(
6537       {"test_session"}, [&](perfetto::TracingSession::CloneTraceCallbackArgs) {
6538         session_cloned.Notify();
6539       });
6540   session_cloned.Wait();
6541 
6542   {
6543     std::vector<char> raw_trace =
6544         other_tracing_session->get()->ReadTraceBlocking();
6545     std::string trace(raw_trace.data(), raw_trace.size());
6546     EXPECT_THAT(trace, HasSubstr("TestEvent"));
6547   }
6548 
6549   {
6550     std::vector<char> raw_trace = StopSessionAndReturnBytes(tracing_session);
6551     std::string trace(raw_trace.data(), raw_trace.size());
6552     EXPECT_THAT(trace, HasSubstr("TestEvent"));
6553   }
6554 }
6555 
6556 class PerfettoStartupTracingApiTest : public PerfettoApiTest {
6557  public:
6558   using SetupStartupTracingOpts = perfetto::Tracing::SetupStartupTracingOpts;
SetupStartupTracing(perfetto::TraceConfig cfg={},SetupStartupTracingOpts opts={})6559   void SetupStartupTracing(perfetto::TraceConfig cfg = {},
6560                            SetupStartupTracingOpts opts = {}) {
6561     // Setup startup tracing in the current process.
6562     cfg.set_duration_ms(500);
6563     cfg.add_buffers()->set_size_kb(1024);
6564     auto* ds_cfg = cfg.add_data_sources()->mutable_config();
6565     ds_cfg->set_name("track_event");
6566 
6567     perfetto::protos::gen::TrackEventConfig te_cfg;
6568     te_cfg.add_disabled_categories("*");
6569     te_cfg.add_enabled_categories("test");
6570     ds_cfg->set_track_event_config_raw(te_cfg.SerializeAsString());
6571 
6572     opts.backend = GetParam();
6573     session_ =
6574         perfetto::Tracing::SetupStartupTracingBlocking(cfg, std::move(opts));
6575     EXPECT_EQ(TRACE_EVENT_CATEGORY_ENABLED("test"), true);
6576   }
6577 
AbortStartupTracing()6578   void AbortStartupTracing() {
6579     session_->AbortBlocking();
6580     session_.reset();
6581   }
6582 
TearDown()6583   void TearDown() override {
6584     if (session_) {
6585       AbortStartupTracing();
6586     }
6587     // We need to sync producer because when we start StartupTracing, the
6588     // producer is disconnected to reconnect again. Note that
6589     // `SetupStartupTracingBlocking` returns right after data sources are
6590     // started. `SetupStartupTracingBlocking` doesn't wait for reconnection
6591     // to succeed before returning. Hence we need to wait for reconnection here
6592     // because `TracingMuxerImpl::ResetForTesting` will destroy the
6593     // producer if it find it is not connected to service. Which is problematic
6594     // because when reconnection happens (via service transport), it will be
6595     // referencing a deleted producer, which will lead to crash.
6596     perfetto::test::SyncProducers();
6597     this->PerfettoApiTest::TearDown();
6598   }
6599 
6600  protected:
6601   std::unique_ptr<perfetto::StartupTracingSession> session_;
6602 };
6603 
6604 // Test `SetupStartupTracing` API (non block version).
TEST_P(PerfettoStartupTracingApiTest,NonBlockingAPI)6605 TEST_P(PerfettoStartupTracingApiTest, NonBlockingAPI) {
6606   // Setup startup tracing in the current process.
6607   perfetto::TraceConfig cfg;
6608   cfg.set_duration_ms(500);
6609   cfg.add_buffers()->set_size_kb(1024);
6610   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
6611   ds_cfg->set_name("track_event");
6612 
6613   perfetto::protos::gen::TrackEventConfig te_cfg;
6614   te_cfg.add_disabled_categories("*");
6615   te_cfg.add_enabled_categories("test");
6616   ds_cfg->set_track_event_config_raw(te_cfg.SerializeAsString());
6617 
6618   SetupStartupTracingOpts opts;
6619   opts.backend = GetParam();
6620   session_ = perfetto::Tracing::SetupStartupTracing(cfg, std::move(opts));
6621   // We need perfetto::test::SyncProducers() to Round-trip to ensure that the
6622   // muxer has enabled startup tracing.
6623   perfetto::test::SyncProducers();
6624   EXPECT_EQ(TRACE_EVENT_CATEGORY_ENABLED("test"), true);
6625 
6626   TRACE_EVENT_BEGIN("test", "Event");
6627 
6628   // Create a new trace session.
6629   auto* tracing_session = NewTraceWithCategories({"test"});
6630   tracing_session->get()->StartBlocking();
6631 
6632   // Emit another event after starting.
6633   TRACE_EVENT_END("test");
6634   // Both events should be retained.
6635   auto slices = StopSessionAndReadSlicesFromTrace(tracing_session);
6636   EXPECT_THAT(slices, ElementsAre("B:test.Event", "E"));
6637 }
6638 
6639 // Test that a startup tracing session will be adopted even when the config
6640 // is not exactly identical (but still compatible).
TEST_P(PerfettoStartupTracingApiTest,CompatibleConfig)6641 TEST_P(PerfettoStartupTracingApiTest, CompatibleConfig) {
6642   perfetto::TraceConfig cfg;
6643   cfg.set_duration_ms(500);
6644   cfg.add_buffers()->set_size_kb(1024);
6645   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
6646   ds_cfg->set_name("track_event");
6647 
6648   perfetto::protos::gen::TrackEventConfig te_cfg;
6649   te_cfg.add_disabled_categories("*");
6650   te_cfg.add_enabled_categories("foo");
6651   te_cfg.add_enabled_categories("bar");
6652   ds_cfg->set_track_event_config_raw(te_cfg.SerializeAsString());
6653 
6654   SetupStartupTracingOpts opts;
6655   opts.backend = GetParam();
6656   session_ = perfetto::Tracing::SetupStartupTracing(cfg, std::move(opts));
6657   // We need perfetto::test::SyncProducers() to Round-trip to ensure that the
6658   // muxer has enabled startup tracing.
6659   perfetto::test::SyncProducers();
6660 
6661   TRACE_EVENT_BEGIN("foo", "Event");
6662 
6663   // Note the different order of categories. The config is essentially the same,
6664   // but is not byte-by-byte identical.
6665   auto* tracing_session = NewTraceWithCategories({"bar", "foo"});
6666   tracing_session->get()->StartBlocking();
6667 
6668   // Emit another event after starting.
6669   TRACE_EVENT_END("foo");
6670 
6671   // Both events should be retained.
6672   auto slices = StopSessionAndReadSlicesFromTrace(tracing_session);
6673   EXPECT_THAT(slices, ElementsAre("B:foo.Event", "E"));
6674 }
6675 
6676 // Test that a startup tracing session won't be adopted when the config is not
6677 // compatible (in this case, the privacy setting is different).
TEST_P(PerfettoStartupTracingApiTest,IncompatibleConfig)6678 TEST_P(PerfettoStartupTracingApiTest, IncompatibleConfig) {
6679   perfetto::TraceConfig cfg;
6680   cfg.set_duration_ms(500);
6681   cfg.add_buffers()->set_size_kb(1024);
6682   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
6683   ds_cfg->set_name("track_event");
6684 
6685   perfetto::protos::gen::TrackEventConfig te_cfg;
6686   te_cfg.add_disabled_categories("*");
6687   te_cfg.add_enabled_categories("foo");
6688   te_cfg.set_filter_debug_annotations(true);
6689   ds_cfg->set_track_event_config_raw(te_cfg.SerializeAsString());
6690 
6691   SetupStartupTracingOpts opts;
6692   opts.backend = GetParam();
6693   session_ = perfetto::Tracing::SetupStartupTracing(cfg, std::move(opts));
6694   // We need perfetto::test::SyncProducers() to Round-trip to ensure that the
6695   // muxer has enabled startup tracing.
6696   perfetto::test::SyncProducers();
6697 
6698   TRACE_EVENT_BEGIN("foo", "Event");
6699 
6700   // This config will have |filter_debug_annotations| set to false.
6701   auto* tracing_session = NewTraceWithCategories({"foo"});
6702   tracing_session->get()->StartBlocking();
6703 
6704   // Emit another event after starting.
6705   TRACE_EVENT_END("foo");
6706 
6707   // The startup session should not be adopted, so we should only see the end
6708   // event.
6709   auto slices = StopSessionAndReadSlicesFromTrace(tracing_session);
6710   EXPECT_THAT(slices, ElementsAre("E"));
6711 }
6712 
TEST_P(PerfettoStartupTracingApiTest,WithExistingSmb)6713 TEST_P(PerfettoStartupTracingApiTest, WithExistingSmb) {
6714   {
6715     // Start and tear down a first session, just to set up the SMB.
6716     auto* tracing_session = NewTraceWithCategories({"foo"});
6717     tracing_session->get()->StartBlocking();
6718     tracing_session->get()->StopBlocking();
6719   }
6720 
6721   SetupStartupTracing();
6722   TRACE_EVENT_BEGIN("test", "Event");
6723 
6724   // Create a new trace session.
6725   auto* tracing_session = NewTraceWithCategories({"test"});
6726   ASSERT_TRUE(WaitForOneProducerConnected(tracing_session->get()));
6727   tracing_session->get()->StartBlocking();
6728 
6729   // Emit another event after starting.
6730   TRACE_EVENT_END("test");
6731 
6732   // Both events should be retained.
6733   auto slices = StopSessionAndReadSlicesFromTrace(tracing_session);
6734   EXPECT_THAT(slices, ElementsAre("B:test.Event", "E"));
6735 }
6736 
TEST_P(PerfettoStartupTracingApiTest,WithProducerProvidedSmb)6737 TEST_P(PerfettoStartupTracingApiTest, WithProducerProvidedSmb) {
6738   ASSERT_FALSE(perfetto::test::TracingMuxerImplInternalsForTest::
6739                    DoesSystemBackendHaveSMB());
6740   // The backend has no SMB set up yet. Instead, the SDK will
6741   // reconnect to the backend with a producer-provided SMB.
6742   SetupStartupTracing();
6743   TRACE_EVENT_BEGIN("test", "Event");
6744 
6745   // Create a new trace session.
6746   auto* tracing_session = NewTraceWithCategories({"test"});
6747   ASSERT_TRUE(WaitForOneProducerConnected(tracing_session->get()));
6748   tracing_session->get()->StartBlocking();
6749 
6750   // Emit another event after starting.
6751   TRACE_EVENT_END("test");
6752 
6753   // Both events should be retained.
6754   auto slices = StopSessionAndReadSlicesFromTrace(tracing_session);
6755   EXPECT_THAT(slices, ElementsAre("B:test.Event", "E"));
6756 }
6757 
TEST_P(PerfettoStartupTracingApiTest,DontTraceBeforeStartupSetup)6758 TEST_P(PerfettoStartupTracingApiTest, DontTraceBeforeStartupSetup) {
6759   // This event should not be recorded.
6760   TRACE_EVENT_BEGIN("test", "EventBeforeStartupTrace");
6761   SetupStartupTracing();
6762   TRACE_EVENT_BEGIN("test", "Event");
6763 
6764   auto* tracing_session = NewTraceWithCategories({"test"});
6765   ASSERT_TRUE(WaitForOneProducerConnected(tracing_session->get()));
6766   tracing_session->get()->StartBlocking();
6767 
6768   TRACE_EVENT_END("test");
6769 
6770   auto slices = StopSessionAndReadSlicesFromTrace(tracing_session);
6771 
6772   EXPECT_THAT(slices, ElementsAre("B:test.Event", "E"));
6773 }
6774 
6775 // Test the StartupTracing when there are multiple data sources registered
6776 // (2 data sources in this test) but only a few of them contribute in startup
6777 // tracing.
TEST_P(PerfettoStartupTracingApiTest,MultipleDataSourceFewContributing)6778 TEST_P(PerfettoStartupTracingApiTest, MultipleDataSourceFewContributing) {
6779   perfetto::TraceConfig cfg;
6780   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
6781   ds_cfg->set_name("CustomDataSource");
6782   SetupStartupTracing(cfg);
6783   TRACE_EVENT_BEGIN("test", "TrackEvent.Startup");
6784 
6785   auto* tracing_session = NewTraceWithCategories({"test"}, {}, cfg);
6786   ASSERT_TRUE(WaitForOneProducerConnected(tracing_session->get()));
6787   tracing_session->get()->StartBlocking();
6788 
6789   TRACE_EVENT_BEGIN("test", "TrackEvent.Main");
6790   perfetto::TrackEvent::Flush();
6791   CustomDataSource::Trace([](CustomDataSource::TraceContext ctx) {
6792     {
6793       auto packet = ctx.NewTracePacket();
6794       packet->set_for_testing()->set_str("CustomDataSource.Main");
6795     }
6796     ctx.Flush();
6797   });
6798 
6799   auto trace = StopSessionAndReturnParsedTrace(tracing_session);
6800   auto slices = ReadSlicesFromTrace(trace);
6801   EXPECT_THAT(slices, ElementsAre("B:test.TrackEvent.Startup",
6802                                   "B:test.TrackEvent.Main"));
6803   std::vector<std::string> test_strings;
6804   for (auto& trace_packet : trace.packet()) {
6805     if (trace_packet.has_for_testing()) {
6806       test_strings.push_back(trace_packet.for_testing().str());
6807     }
6808   }
6809   EXPECT_THAT(test_strings, ElementsAre("CustomDataSource.Main"));
6810 }
6811 
6812 // Test the StartupTracing when there are multiple data sources registered
6813 // (2 data sources in this test) and all of them are contributing in startup
6814 // tracing.
TEST_P(PerfettoStartupTracingApiTest,MultipleDataSourceAllContributing)6815 TEST_P(PerfettoStartupTracingApiTest, MultipleDataSourceAllContributing) {
6816   perfetto::TraceConfig cfg;
6817   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
6818   ds_cfg->set_name("CustomDataSource");
6819   SetupStartupTracing(cfg);
6820   TRACE_EVENT_BEGIN("test", "TrackEvent.Startup");
6821   CustomDataSource::Trace([](CustomDataSource::TraceContext ctx) {
6822     auto packet = ctx.NewTracePacket();
6823     packet->set_for_testing()->set_str("CustomDataSource.Startup");
6824   });
6825 
6826   auto* tracing_session = NewTraceWithCategories({"test"}, {}, cfg);
6827   ASSERT_TRUE(WaitForOneProducerConnected(tracing_session->get()));
6828   tracing_session->get()->StartBlocking();
6829 
6830   TRACE_EVENT_BEGIN("test", "TrackEvent.Main");
6831   perfetto::TrackEvent::Flush();
6832   CustomDataSource::Trace([](CustomDataSource::TraceContext ctx) {
6833     {
6834       auto packet = ctx.NewTracePacket();
6835       packet->set_for_testing()->set_str("CustomDataSource.Main");
6836     }
6837     ctx.Flush();
6838   });
6839 
6840   auto trace = StopSessionAndReturnParsedTrace(tracing_session);
6841   auto slices = ReadSlicesFromTrace(trace);
6842   EXPECT_THAT(slices, ElementsAre("B:test.TrackEvent.Startup",
6843                                   "B:test.TrackEvent.Main"));
6844   std::vector<std::string> test_strings;
6845   for (auto& trace_packet : trace.packet()) {
6846     if (trace_packet.has_for_testing()) {
6847       test_strings.push_back(trace_packet.for_testing().str());
6848     }
6849   }
6850   EXPECT_THAT(test_strings,
6851               ElementsAre("CustomDataSource.Startup", "CustomDataSource.Main"));
6852 }
6853 
6854 // Startup tracing requires BufferExhaustedPolicy::kDrop, i.e. once the SMB is
6855 // filled with startup events, any further events should be dropped.
6856 // TODO(b/261493947): fix or remove. go/aosp_ci_failure23
TEST_P(PerfettoStartupTracingApiTest,DISABLED_DropPolicy)6857 TEST_P(PerfettoStartupTracingApiTest, DISABLED_DropPolicy) {
6858   SetupStartupTracing();
6859   constexpr int kNumEvents = 100000;
6860   for (int i = 0; i < kNumEvents; i++) {
6861     TRACE_EVENT_BEGIN("test", "StartupEvent");
6862   }
6863 
6864   auto* tracing_session = NewTraceWithCategories({"test"});
6865   tracing_session->get()->StartBlocking();
6866 
6867   auto slices = StopSessionAndReadSlicesFromTrace(tracing_session);
6868   std::unordered_map<std::string, int> freq_map;
6869   for (auto& slice : slices) {
6870     freq_map[slice]++;
6871   }
6872   EXPECT_GT(freq_map["B:test.StartupEvent"], 0);
6873   EXPECT_LT(freq_map["B:test.StartupEvent"], kNumEvents);
6874 }
6875 
6876 // TODO(b/261493947): fix or remove.
TEST_P(PerfettoStartupTracingApiTest,DISABLED_Abort)6877 TEST_P(PerfettoStartupTracingApiTest, DISABLED_Abort) {
6878   SetupStartupTracing();
6879   TRACE_EVENT_BEGIN("test", "StartupEvent");
6880   AbortStartupTracing();
6881 
6882   auto* tracing_session = NewTraceWithCategories({"test"});
6883   tracing_session->get()->StartBlocking();
6884 
6885   TRACE_EVENT_BEGIN("test", "MainEvent");
6886 
6887   auto slices = StopSessionAndReadSlicesFromTrace(tracing_session);
6888 
6889   EXPECT_THAT(slices, ElementsAre("B:test.MainEvent"));
6890 }
6891 
TEST_P(PerfettoStartupTracingApiTest,AbortAndRestart)6892 TEST_P(PerfettoStartupTracingApiTest, AbortAndRestart) {
6893   SetupStartupTracing();
6894   TRACE_EVENT_BEGIN("test", "StartupEvent1");
6895   AbortStartupTracing();
6896   SetupStartupTracing();
6897   TRACE_EVENT_BEGIN("test", "StartupEvent2");
6898 
6899   auto* tracing_session = NewTraceWithCategories({"test"});
6900   ASSERT_TRUE(WaitForOneProducerConnected(tracing_session->get()));
6901   tracing_session->get()->StartBlocking();
6902 
6903   TRACE_EVENT_BEGIN("test", "MainEvent");
6904   perfetto::TrackEvent::Flush();
6905 
6906   tracing_session->get()->StopBlocking();
6907 
6908   auto slices = ReadSlicesFromTraceSession(tracing_session->get());
6909 
6910   EXPECT_THAT(slices, ElementsAre("B:test.StartupEvent2", "B:test.MainEvent"));
6911 }
6912 
TEST_P(PerfettoStartupTracingApiTest,Timeout)6913 TEST_P(PerfettoStartupTracingApiTest, Timeout) {
6914   SetupStartupTracingOpts args;
6915   args.timeout_ms = 2000;
6916   SetupStartupTracing({}, args);
6917   for (int i = 0; i < 25; i++) {
6918     TRACE_EVENT_BEGIN("test", "StartupEvent");
6919     std::this_thread::sleep_for(std::chrono::milliseconds(100));
6920   }
6921 
6922   auto* tracing_session = NewTraceWithCategories({"test"});
6923   tracing_session->get()->StartBlocking();
6924   TRACE_EVENT_BEGIN("test", "MainEvent");
6925 
6926   perfetto::TrackEvent::Flush();
6927 
6928   tracing_session->get()->StopBlocking();
6929 
6930   auto slices = ReadSlicesFromTraceSession(tracing_session->get());
6931   EXPECT_THAT(slices, ElementsAre("B:test.MainEvent"));
6932 }
6933 
6934 // TODO(b/261493947): fix or remove.
TEST_P(PerfettoStartupTracingApiTest,DISABLED_Callbacks)6935 TEST_P(PerfettoStartupTracingApiTest, DISABLED_Callbacks) {
6936   for (bool abort : {true, false}) {
6937     SetupStartupTracingOpts args;
6938     std::vector<std::string> callback_events;
6939     using CallbackArgs = perfetto::Tracing::OnStartupTracingSetupCallbackArgs;
6940     args.on_setup = [&](CallbackArgs callback_arg) {
6941       callback_events.push_back(
6942           "OnSetup(num_data_sources_started=" +
6943           std::to_string(callback_arg.num_data_sources_started) + ")");
6944     };
6945     args.on_adopted = [&]() { callback_events.push_back("OnAdopted()"); };
6946     args.on_aborted = [&]() { callback_events.push_back("OnAborted()"); };
6947     SetupStartupTracing({}, args);
6948     TRACE_EVENT_BEGIN("test", "StartupEvent");
6949     if (abort) {
6950       AbortStartupTracing();
6951     }
6952     auto* tracing_session = NewTraceWithCategories({"test"});
6953     tracing_session->get()->StartBlocking();
6954 
6955     TRACE_EVENT_BEGIN("test", "MainEvent");
6956     perfetto::TrackEvent::Flush();
6957 
6958     tracing_session->get()->StopBlocking();
6959 
6960     auto slices = ReadSlicesFromTraceSession(tracing_session->get());
6961 
6962     ASSERT_EQ(2u, callback_events.size());
6963     EXPECT_EQ("OnSetup(num_data_sources_started=1)", callback_events.at(0));
6964     if (abort) {
6965       EXPECT_THAT(slices, ElementsAre("B:test.MainEvent"));
6966       EXPECT_EQ("OnAborted()", callback_events.at(1));
6967     } else {
6968       EXPECT_THAT(slices,
6969                   ElementsAre("B:test.StartupEvent", "B:test.MainEvent"));
6970       EXPECT_EQ("OnAdopted()", callback_events.at(1));
6971     }
6972   }
6973 }
6974 
6975 // Test that it's ok if main tracing is never started.
6976 // TODO(b/261493947): fix or remove.
TEST_P(PerfettoStartupTracingApiTest,DISABLED_MainTracingNeverStarted)6977 TEST_P(PerfettoStartupTracingApiTest, DISABLED_MainTracingNeverStarted) {
6978   SetupStartupTracing();
6979   TRACE_EVENT_BEGIN("test", "StartupEvent");
6980 }
6981 
6982 // Validates that Startup Trace works fine if we dont emit any event
6983 // during startup tracing session.
TEST_P(PerfettoStartupTracingApiTest,NoEventInStartupTracing)6984 TEST_P(PerfettoStartupTracingApiTest, NoEventInStartupTracing) {
6985   SetupStartupTracing();
6986 
6987   auto* tracing_session = NewTraceWithCategories({"test"});
6988   ASSERT_TRUE(WaitForOneProducerConnected(tracing_session->get()));
6989   tracing_session->get()->StartBlocking();
6990   // Emit an event now that the session was fully started. This should go
6991   // strait to the SMB.
6992   TRACE_EVENT_BEGIN("test", "MainEvent");
6993   perfetto::TrackEvent::Flush();
6994   tracing_session->get()->StopBlocking();
6995   auto slices = ReadSlicesFromTraceSession(tracing_session->get());
6996   EXPECT_THAT(slices, ElementsAre("B:test.MainEvent"));
6997 }
6998 
6999 class ConcurrentSessionTest : public ::testing::Test {
7000  public:
SetUp()7001   void SetUp() override {
7002     system_service_ = perfetto::test::SystemService::Start();
7003     if (!system_service_.valid()) {
7004       GTEST_SKIP();
7005     }
7006     ASSERT_FALSE(perfetto::Tracing::IsInitialized());
7007   }
7008 
InitPerfetto(bool supports_multiple_data_source_instances=true)7009   void InitPerfetto(bool supports_multiple_data_source_instances = true) {
7010     TracingInitArgs args;
7011     args.backends = perfetto::kInProcessBackend | perfetto::kSystemBackend;
7012     args.supports_multiple_data_source_instances =
7013         supports_multiple_data_source_instances;
7014     g_test_tracing_policy->should_allow_consumer_connection = true;
7015     args.tracing_policy = g_test_tracing_policy;
7016     perfetto::Tracing::Initialize(args);
7017     perfetto::TrackEvent::Register();
7018     perfetto::test::SyncProducers();
7019     perfetto::test::DisableReconnectLimit();
7020   }
7021 
TearDown()7022   void TearDown() override { perfetto::Tracing::ResetForTesting(); }
7023 
StartTracing(perfetto::BackendType backend_type,bool short_stop_timeout=false)7024   static std::unique_ptr<perfetto::TracingSession> StartTracing(
7025       perfetto::BackendType backend_type,
7026       bool short_stop_timeout = false) {
7027     perfetto::TraceConfig cfg;
7028     if (short_stop_timeout) {
7029       cfg.set_data_source_stop_timeout_ms(500);
7030     }
7031     cfg.add_buffers()->set_size_kb(1024);
7032     auto* ds_cfg = cfg.add_data_sources()->mutable_config();
7033     ds_cfg->set_name("track_event");
7034     auto tracing_session = perfetto::Tracing::NewTrace(backend_type);
7035     tracing_session->Setup(cfg);
7036     tracing_session->StartBlocking();
7037     return tracing_session;
7038   }
StopTracing(std::unique_ptr<perfetto::TracingSession> tracing_session,bool expect_incremental_state_cleared=true)7039   std::vector<std::string> StopTracing(
7040       std::unique_ptr<perfetto::TracingSession> tracing_session,
7041       bool expect_incremental_state_cleared = true) {
7042     perfetto::TrackEvent::Flush();
7043     tracing_session->StopBlocking();
7044     std::vector<char> trace_data(tracing_session->ReadTraceBlocking());
7045     return ReadSlicesFromTrace(trace_data, expect_incremental_state_cleared);
7046   }
7047 
7048   perfetto::test::SystemService system_service_;
7049 };
7050 
7051 // Verify that concurrent sessions works well by default.
7052 // (i.e. when `disallow_concurrent_sessions` param is not set)
TEST_F(ConcurrentSessionTest,ConcurrentBackends)7053 TEST_F(ConcurrentSessionTest, ConcurrentBackends) {
7054   InitPerfetto();
7055   auto tracing_session1 = StartTracing(perfetto::kSystemBackend);
7056   TRACE_EVENT_BEGIN("test", "DrawGame1");
7057 
7058   auto tracing_session2 = StartTracing(perfetto::kInProcessBackend);
7059   // Should be recorded by both sessions.
7060   TRACE_EVENT_BEGIN("test", "DrawGame2");
7061 
7062   auto slices1 = StopTracing(std::move(tracing_session1));
7063   EXPECT_THAT(slices1, ElementsAre("B:test.DrawGame1", "B:test.DrawGame2"));
7064 
7065   auto slices2 = StopTracing(std::move(tracing_session2));
7066   EXPECT_THAT(slices2, ElementsAre("B:test.DrawGame2"));
7067 
7068   auto tracing_session3 = StartTracing(perfetto::kInProcessBackend);
7069   TRACE_EVENT_BEGIN("test", "DrawGame3");
7070 
7071   auto slices3 = StopTracing(std::move(tracing_session3));
7072   EXPECT_THAT(slices3, ElementsAre("B:test.DrawGame3"));
7073 }
7074 
7075 // When `supports_multiple_data_source_instances = false`, second session
7076 // should not be started.
TEST_F(ConcurrentSessionTest,DisallowMultipleSessionBasic)7077 TEST_F(ConcurrentSessionTest, DisallowMultipleSessionBasic) {
7078   InitPerfetto(/* supports_multiple_data_source_instances = */ false);
7079   auto tracing_session1 = StartTracing(perfetto::kInProcessBackend);
7080   TRACE_EVENT_BEGIN("test", "DrawGame1");
7081 
7082   auto tracing_session2 =
7083       StartTracing(perfetto::kInProcessBackend, /*short_stop_timeout=*/true);
7084   TRACE_EVENT_BEGIN("test", "DrawGame2");
7085 
7086   auto slices1 = StopTracing(std::move(tracing_session1));
7087   EXPECT_THAT(slices1, ElementsAre("B:test.DrawGame1", "B:test.DrawGame2"));
7088 
7089   auto slices2 = StopTracing(std::move(tracing_session2),
7090                              false /* expect_incremental_state_cleared */);
7091   // Because `tracing_session2` was not really started.
7092   EXPECT_THAT(slices2, ElementsAre());
7093 
7094   auto tracing_session3 = StartTracing(perfetto::kInProcessBackend);
7095   TRACE_EVENT_BEGIN("test", "DrawGame3");
7096 
7097   auto slices3 = StopTracing(std::move(tracing_session3));
7098   EXPECT_THAT(slices3, ElementsAre("B:test.DrawGame3"));
7099 }
7100 
TEST(PerfettoApiInitTest,DisableSystemConsumer)7101 TEST(PerfettoApiInitTest, DisableSystemConsumer) {
7102   g_test_tracing_policy->should_allow_consumer_connection = true;
7103 
7104   auto system_service = perfetto::test::SystemService::Start();
7105   // If the system backend isn't supported, skip
7106   if (!system_service.valid()) {
7107     GTEST_SKIP();
7108   }
7109 
7110   EXPECT_FALSE(perfetto::Tracing::IsInitialized());
7111   TracingInitArgs args;
7112   args.backends = perfetto::kSystemBackend;
7113   args.tracing_policy = g_test_tracing_policy;
7114   args.enable_system_consumer = false;
7115   perfetto::Tracing::Initialize(args);
7116 
7117   // If this wasn't the first test to run in this process, any producers
7118   // connected to the old system service will have been disconnected by the
7119   // service restarting above. Wait for all producers to connect again before
7120   // proceeding with the test.
7121   perfetto::test::SyncProducers();
7122 
7123   perfetto::test::DisableReconnectLimit();
7124 
7125   // Creating the consumer with kUnspecifiedBackend should cause a connection
7126   // error: there's no consumer backend.
7127   {
7128     std::unique_ptr<perfetto::TracingSession> ts =
7129         perfetto::Tracing::NewTrace(perfetto::kUnspecifiedBackend);
7130 
7131     WaitableTestEvent got_error;
7132     ts->SetOnErrorCallback([&](perfetto::TracingError error) {
7133       EXPECT_EQ(perfetto::TracingError::kDisconnected, error.code);
7134       EXPECT_FALSE(error.message.empty());
7135       got_error.Notify();
7136     });
7137     got_error.Wait();
7138   }
7139 
7140   // Creating the consumer with kSystemBackend should create a system consumer
7141   // backend on the spot.
7142   EXPECT_TRUE(perfetto::Tracing::NewTrace(perfetto::kSystemBackend)
7143                   ->QueryServiceStateBlocking()
7144                   .success);
7145 
7146   // Now even a consumer with kUnspecifiedBackend should succeed, because the
7147   // backend has been created.
7148   EXPECT_TRUE(perfetto::Tracing::NewTrace(perfetto::kUnspecifiedBackend)
7149                   ->QueryServiceStateBlocking()
7150                   .success);
7151 
7152   perfetto::Tracing::ResetForTesting();
7153 }
7154 
TEST(PerfettoApiInitTest,SeparateInitializations)7155 TEST(PerfettoApiInitTest, SeparateInitializations) {
7156   auto system_service = perfetto::test::SystemService::Start();
7157   // If the system backend isn't supported, skip
7158   if (!system_service.valid()) {
7159     GTEST_SKIP();
7160   }
7161 
7162   {
7163     EXPECT_FALSE(perfetto::Tracing::IsInitialized());
7164     TracingInitArgs args;
7165     args.backends = perfetto::kInProcessBackend;
7166     perfetto::Tracing::Initialize(args);
7167   }
7168 
7169   // If this wasn't the first test to run in this process, any producers
7170   // connected to the old system service will have been disconnected by the
7171   // service restarting above. Wait for all producers to connect again before
7172   // proceeding with the test.
7173   perfetto::test::SyncProducers();
7174 
7175   perfetto::test::DisableReconnectLimit();
7176 
7177   {
7178     perfetto::DataSourceDescriptor dsd;
7179     dsd.set_name("CustomDataSource");
7180     CustomDataSource::Register(dsd);
7181   }
7182 
7183   {
7184     std::unique_ptr<perfetto::TracingSession> tracing_session =
7185         perfetto::Tracing::NewTrace(perfetto::kInProcessBackend);
7186     auto result = tracing_session->QueryServiceStateBlocking();
7187     perfetto::protos::gen::TracingServiceState state;
7188     ASSERT_TRUE(result.success);
7189     ASSERT_TRUE(state.ParseFromArray(result.service_state_data.data(),
7190                                      result.service_state_data.size()));
7191     EXPECT_THAT(state.data_sources(),
7192                 Contains(Property(
7193                     &perfetto::protos::gen::TracingServiceState::DataSource::
7194                         ds_descriptor,
7195                     Property(&perfetto::protos::gen::DataSourceDescriptor::name,
7196                              "CustomDataSource"))));
7197   }
7198 
7199   {
7200     EXPECT_TRUE(perfetto::Tracing::IsInitialized());
7201     TracingInitArgs args;
7202     args.backends = perfetto::kSystemBackend;
7203     args.enable_system_consumer = false;
7204     perfetto::Tracing::Initialize(args);
7205   }
7206 
7207   perfetto::test::SyncProducers();
7208 
7209   {
7210     std::unique_ptr<perfetto::TracingSession> tracing_session =
7211         perfetto::Tracing::NewTrace(perfetto::kSystemBackend);
7212     auto result = tracing_session->QueryServiceStateBlocking();
7213     perfetto::protos::gen::TracingServiceState state;
7214     ASSERT_TRUE(result.success);
7215     ASSERT_TRUE(state.ParseFromArray(result.service_state_data.data(),
7216                                      result.service_state_data.size()));
7217     EXPECT_THAT(state.data_sources(),
7218                 Contains(Property(
7219                     &perfetto::protos::gen::TracingServiceState::DataSource::
7220                         ds_descriptor,
7221                     Property(&perfetto::protos::gen::DataSourceDescriptor::name,
7222                              "CustomDataSource"))));
7223   }
7224   perfetto::test::TracingMuxerImplInternalsForTest::
7225       ClearDataSourceTlsStateOnReset<CustomDataSource>();
7226 
7227   perfetto::Tracing::ResetForTesting();
7228 }
7229 
7230 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
7231 namespace {
7232 
ConnectUnixSocket()7233 int ConnectUnixSocket() {
7234   std::string socket_name = perfetto::GetProducerSocket();
7235   int fd = socket(AF_UNIX, SOCK_STREAM, 0);
7236   struct sockaddr_un saddr;
7237   memset(&saddr, 0, sizeof(saddr));
7238   memcpy(saddr.sun_path, socket_name.data(), socket_name.size());
7239   saddr.sun_family = AF_UNIX;
7240   auto size = static_cast<socklen_t>(__builtin_offsetof(sockaddr_un, sun_path) +
7241                                      socket_name.size() + 1);
7242   connect(fd, reinterpret_cast<const struct sockaddr*>(&saddr), size);
7243   return fd;
7244 }
7245 
7246 using CreateSocketFunction =
7247     std::function<void(perfetto::CreateSocketCallback)>;
7248 
7249 CreateSocketFunction* g_std_function = nullptr;
7250 
SetCreateSocketFunction(CreateSocketFunction func)7251 void SetCreateSocketFunction(CreateSocketFunction func) {
7252   g_std_function = new CreateSocketFunction(func);
7253 }
7254 
ResetCreateSocketFunction()7255 void ResetCreateSocketFunction() {
7256   delete g_std_function;
7257 }
7258 
CallCreateSocketFunction(perfetto::CreateSocketCallback cb)7259 void CallCreateSocketFunction(perfetto::CreateSocketCallback cb) {
7260   PERFETTO_DCHECK(g_std_function);
7261   (*g_std_function)(cb);
7262 }
7263 
7264 }  // namespace
7265 
TEST(PerfettoApiInitTest,AsyncSocket)7266 TEST(PerfettoApiInitTest, AsyncSocket) {
7267   auto system_service = perfetto::test::SystemService::Start();
7268   // If the system backend isn't supported, skip
7269   if (!system_service.valid()) {
7270     GTEST_SKIP();
7271   }
7272 
7273   EXPECT_FALSE(perfetto::Tracing::IsInitialized());
7274 
7275   perfetto::CreateSocketCallback socket_callback;
7276   WaitableTestEvent create_socket_called;
7277 
7278   TracingInitArgs args;
7279   args.backends = perfetto::kSystemBackend;
7280   args.tracing_policy = g_test_tracing_policy;
7281   args.create_socket_async = &CallCreateSocketFunction;
7282   SetCreateSocketFunction([&socket_callback, &create_socket_called](
7283                               perfetto::CreateSocketCallback cb) {
7284     socket_callback = cb;
7285     create_socket_called.Notify();
7286   });
7287 
7288   perfetto::Tracing::Initialize(args);
7289   create_socket_called.Wait();
7290 
7291   int fd = ConnectUnixSocket();
7292   socket_callback(fd);
7293 
7294   perfetto::test::SyncProducers();
7295   EXPECT_TRUE(perfetto::Tracing::NewTrace(perfetto::kSystemBackend)
7296                   ->QueryServiceStateBlocking()
7297                   .success);
7298 
7299   perfetto::Tracing::ResetForTesting();
7300   ResetCreateSocketFunction();
7301 }
7302 
TEST(PerfettoApiInitTest,AsyncSocketDisconnect)7303 TEST(PerfettoApiInitTest, AsyncSocketDisconnect) {
7304   auto system_service = perfetto::test::SystemService::Start();
7305   // If the system backend isn't supported, skip
7306   if (!system_service.valid()) {
7307     GTEST_SKIP();
7308   }
7309 
7310   EXPECT_FALSE(perfetto::Tracing::IsInitialized());
7311 
7312   perfetto::CreateSocketCallback socket_callback;
7313   testing::MockFunction<CreateSocketFunction> mock_create_socket;
7314   WaitableTestEvent create_socket_called1, create_socket_called2;
7315 
7316   TracingInitArgs args;
7317   args.backends = perfetto::kSystemBackend;
7318   args.tracing_policy = g_test_tracing_policy;
7319   args.create_socket_async = &CallCreateSocketFunction;
7320   SetCreateSocketFunction(mock_create_socket.AsStdFunction());
7321 
7322   EXPECT_CALL(mock_create_socket, Call)
7323       .WillOnce(Invoke([&socket_callback, &create_socket_called1](
7324                            perfetto::CreateSocketCallback cb) {
7325         socket_callback = cb;
7326         create_socket_called1.Notify();
7327       }))
7328       .WillOnce(Invoke([&socket_callback, &create_socket_called2](
7329                            perfetto::CreateSocketCallback cb) {
7330         socket_callback = cb;
7331         create_socket_called2.Notify();
7332       }));
7333 
7334   perfetto::Tracing::Initialize(args);
7335   create_socket_called1.Wait();
7336   int fd = ConnectUnixSocket();
7337   socket_callback(fd);
7338 
7339   perfetto::test::SyncProducers();
7340   EXPECT_TRUE(perfetto::Tracing::NewTrace(perfetto::kSystemBackend)
7341                   ->QueryServiceStateBlocking()
7342                   .success);
7343 
7344   // Restart the system service. This will cause the producer and consumer to
7345   // disconnect and reconnect. The create_socket_async function should be called
7346   // for the second time.
7347   system_service.Restart();
7348   create_socket_called2.Wait();
7349   fd = ConnectUnixSocket();
7350   socket_callback(fd);
7351 
7352   perfetto::test::SyncProducers();
7353   EXPECT_TRUE(perfetto::Tracing::NewTrace(perfetto::kSystemBackend)
7354                   ->QueryServiceStateBlocking()
7355                   .success);
7356 
7357   perfetto::Tracing::ResetForTesting();
7358   ResetCreateSocketFunction();
7359 }
7360 
TEST(PerfettoApiInitTest,AsyncSocketStartupTracing)7361 TEST(PerfettoApiInitTest, AsyncSocketStartupTracing) {
7362   auto system_service = perfetto::test::SystemService::Start();
7363   // If the system backend isn't supported, skip
7364   if (!system_service.valid()) {
7365     GTEST_SKIP();
7366   }
7367 
7368   EXPECT_FALSE(perfetto::Tracing::IsInitialized());
7369 
7370   perfetto::CreateSocketCallback socket_callback;
7371   WaitableTestEvent create_socket_called;
7372 
7373   TracingInitArgs args;
7374   args.backends = perfetto::kSystemBackend;
7375   args.tracing_policy = g_test_tracing_policy;
7376   args.create_socket_async = &CallCreateSocketFunction;
7377   SetCreateSocketFunction([&socket_callback, &create_socket_called](
7378                               perfetto::CreateSocketCallback cb) {
7379     socket_callback = cb;
7380     create_socket_called.Notify();
7381   });
7382 
7383   perfetto::Tracing::Initialize(args);
7384   perfetto::TrackEvent::Register();
7385 
7386   perfetto::TraceConfig cfg;
7387   cfg.set_duration_ms(500);
7388   cfg.add_buffers()->set_size_kb(1024);
7389   auto* ds_cfg = cfg.add_data_sources()->mutable_config();
7390   ds_cfg->set_name("track_event");
7391 
7392   perfetto::protos::gen::TrackEventConfig te_cfg;
7393   te_cfg.add_disabled_categories("*");
7394   te_cfg.add_enabled_categories("test");
7395   ds_cfg->set_track_event_config_raw(te_cfg.SerializeAsString());
7396 
7397   perfetto::Tracing::SetupStartupTracingOpts opts;
7398   opts.backend = perfetto::kSystemBackend;
7399   auto startup_session =
7400       perfetto::Tracing::SetupStartupTracingBlocking(cfg, std::move(opts));
7401 
7402   // Emit a significant number of events to write >1 chunk of data.
7403   constexpr size_t kNumEvents = 1000;
7404   for (size_t i = 0; i < kNumEvents; i++) {
7405     TRACE_EVENT_INSTANT("test", "StartupEvent");
7406   }
7407 
7408   // Now proceed with the connection to the service and wait until it completes.
7409   int fd = ConnectUnixSocket();
7410   socket_callback(fd);
7411   perfetto::test::SyncProducers();
7412 
7413   auto session = perfetto::Tracing::NewTrace(perfetto::kSystemBackend);
7414   session->Setup(cfg);
7415   session->StartBlocking();
7416 
7417   // Write even more events, now with connection established.
7418   for (size_t i = 0; i < kNumEvents; i++) {
7419     TRACE_EVENT_INSTANT("test", "TraceEvent");
7420   }
7421 
7422   perfetto::TrackEvent::Flush();
7423   session->StopBlocking();
7424 
7425   auto raw_trace = session->ReadTraceBlocking();
7426   perfetto::protos::gen::Trace parsed_trace;
7427   EXPECT_TRUE(parsed_trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
7428 
7429   size_t n_track_events = 0;
7430   for (const auto& packet : parsed_trace.packet()) {
7431     if (packet.has_track_event()) {
7432       ++n_track_events;
7433     }
7434   }
7435 
7436   // Events from both startup and service-initiated sessions should be retained.
7437   EXPECT_EQ(n_track_events, kNumEvents * 2);
7438 
7439   startup_session.reset();
7440   session.reset();
7441   perfetto::Tracing::ResetForTesting();
7442   ResetCreateSocketFunction();
7443 }
7444 #endif  // !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
7445 
7446 struct BackendTypeAsString {
operator ()__anonfc73210d0111::BackendTypeAsString7447   std::string operator()(
7448       const ::testing::TestParamInfo<perfetto::BackendType>& info) const {
7449     switch (info.param) {
7450       case perfetto::kInProcessBackend:
7451         return "InProc";
7452       case perfetto::kSystemBackend:
7453         return "System";
7454       case perfetto::kCustomBackend:
7455         return "Custom";
7456       case perfetto::kUnspecifiedBackend:
7457         return "Unspec";
7458     }
7459     return nullptr;
7460   }
7461 };
7462 
7463 INSTANTIATE_TEST_SUITE_P(PerfettoApiTest,
7464                          PerfettoApiTest,
7465                          ::testing::Values(perfetto::kInProcessBackend,
7466                                            perfetto::kSystemBackend),
7467                          BackendTypeAsString());
7468 
7469 // In-process backend doesn't support startup tracing.
7470 INSTANTIATE_TEST_SUITE_P(PerfettoStartupTracingApiTest,
7471                          PerfettoStartupTracingApiTest,
7472                          ::testing::Values(perfetto::kSystemBackend),
7473                          BackendTypeAsString());
7474 
7475 class PerfettoApiEnvironment : public ::testing::Environment {
7476  public:
TearDown()7477   void TearDown() override {
7478     // Test shutting down Perfetto only when all other tests have been run and
7479     // no more tracing code will be executed.
7480     PERFETTO_CHECK(!perfetto::Tracing::IsInitialized());
7481     perfetto::TracingInitArgs args;
7482     args.backends = perfetto::kInProcessBackend;
7483     perfetto::Tracing::Initialize(args);
7484     perfetto::Tracing::Shutdown();
7485     PERFETTO_CHECK(!perfetto::Tracing::IsInitialized());
7486     // Shutting down again is a no-op.
7487     perfetto::Tracing::Shutdown();
7488     PERFETTO_CHECK(!perfetto::Tracing::IsInitialized());
7489   }
7490 };
7491 
7492 int PERFETTO_UNUSED initializer =
__anonfc73210d8602null7493     perfetto::integration_tests::RegisterApiIntegrationTestInitializer([] {
7494       ::testing::AddGlobalTestEnvironment(new PerfettoApiEnvironment);
7495     });
7496 
7497 }  // namespace
7498 
7499 PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS(CustomDataSource);
7500 PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS(MockDataSource);
7501 PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS(MockDataSource2);
7502 PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS(TestIncrementalDataSource,
7503                                             TestIncrementalDataSourceTraits);
7504 
7505 PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(CustomDataSource);
7506 PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(MockDataSource);
7507 PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(MockDataSource2);
7508 PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(TestIncrementalDataSource,
7509                                            TestIncrementalDataSourceTraits);
7510