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