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