1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/trace_event/trace_event.h"
6
7 #include <inttypes.h>
8 #include <math.h>
9 #include <stddef.h>
10 #include <stdint.h>
11
12 #include <cstdlib>
13 #include <limits>
14 #include <map>
15 #include <memory>
16 #include <string>
17 #include <utility>
18 #include <vector>
19
20 #include "base/at_exit.h"
21 #include "base/command_line.h"
22 #include "base/containers/cxx20_erase_vector.h"
23 #include "base/functional/bind.h"
24 #include "base/json/json_reader.h"
25 #include "base/json/json_writer.h"
26 #include "base/location.h"
27 #include "base/logging.h"
28 #include "base/memory/ptr_util.h"
29 #include "base/memory/raw_ptr.h"
30 #include "base/memory/ref_counted_memory.h"
31 #include "base/memory/singleton.h"
32 #include "base/process/process_handle.h"
33 #include "base/stl_util.h"
34 #include "base/strings/pattern.h"
35 #include "base/strings/stringprintf.h"
36 #include "base/synchronization/waitable_event.h"
37 #include "base/task/single_thread_task_runner.h"
38 #include "base/threading/platform_thread.h"
39 #include "base/threading/thread.h"
40 #include "base/time/time.h"
41 #include "base/trace_event/trace_buffer.h"
42 #include "base/values.h"
43 #include "build/build_config.h"
44 #include "testing/gmock/include/gmock/gmock.h"
45 #include "testing/gtest/include/gtest/gtest.h"
46
47 #if BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
48 #include "third_party/perfetto/protos/perfetto/config/chrome/chrome_config.gen.h" // nogncheck
49 #endif
50
51 namespace base::trace_event {
52
53 namespace {
54
55 enum CompareOp {
56 IS_EQUAL,
57 IS_NOT_EQUAL,
58 };
59
60 struct JsonKeyValue {
61 const char* key;
62 const char* value;
63 CompareOp op;
64 };
65
66 const int kAsyncId = 5;
67 const char kAsyncIdStr[] = "0x5";
68 const int kAsyncId2 = 6;
69 const char kAsyncId2Str[] = "0x6";
70
71 constexpr const char kRecordAllCategoryFilter[] = "*";
72 constexpr const char kAllCategory[] = "test_all";
73
IsCategoryEnabled(const char * name)74 bool IsCategoryEnabled(const char* name) {
75 #if BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
76 bool result;
77 perfetto::DynamicCategory dynamic_category(name);
78 TRACE_EVENT_CATEGORY_GROUP_ENABLED(dynamic_category, &result);
79 return result;
80 #else
81 return *TraceLog::GetInstance()->GetCategoryGroupEnabled(name);
82 #endif
83 }
84
85 class TraceEventTestFixture : public testing::Test {
86 public:
87 TraceEventTestFixture() = default;
88
89 void OnTraceDataCollected(
90 WaitableEvent* flush_complete_event,
91 const scoped_refptr<base::RefCountedString>& events_str,
92 bool has_more_events);
93 const Value::Dict* FindMatchingTraceEntry(const JsonKeyValue* key_values);
94 const Value::Dict* FindNamePhase(const char* name, const char* phase);
95 const Value::Dict* FindNamePhaseKeyValue(const char* name,
96 const char* phase,
97 const char* key,
98 const char* value);
99 void DropTracedMetadataRecords();
100 bool FindMatchingValue(const char* key,
101 const char* value);
102 bool FindNonMatchingValue(const char* key,
103 const char* value);
Clear()104 void Clear() {
105 trace_parsed_ = Value::List();
106 json_output_.json_output.clear();
107 }
108
BeginTrace()109 void BeginTrace() {
110 BeginSpecificTrace("*");
111 }
112
BeginSpecificTrace(const std::string & filter)113 void BeginSpecificTrace(const std::string& filter) {
114 TraceLog::GetInstance()->SetEnabled(TraceConfig(filter, ""),
115 TraceLog::RECORDING_MODE);
116 }
117
CancelTrace()118 void CancelTrace() {
119 WaitableEvent flush_complete_event(
120 WaitableEvent::ResetPolicy::AUTOMATIC,
121 WaitableEvent::InitialState::NOT_SIGNALED);
122 CancelTraceAsync(&flush_complete_event);
123 flush_complete_event.Wait();
124 }
125
EndTraceAndFlush()126 void EndTraceAndFlush() {
127 num_flush_callbacks_ = 0;
128 WaitableEvent flush_complete_event(
129 WaitableEvent::ResetPolicy::AUTOMATIC,
130 WaitableEvent::InitialState::NOT_SIGNALED);
131 EndTraceAndFlushAsync(&flush_complete_event);
132 flush_complete_event.Wait();
133 }
134
135 // Used when testing thread-local buffers which requires the thread initiating
136 // flush to have a message loop.
EndTraceAndFlushInThreadWithMessageLoop()137 void EndTraceAndFlushInThreadWithMessageLoop() {
138 WaitableEvent flush_complete_event(
139 WaitableEvent::ResetPolicy::AUTOMATIC,
140 WaitableEvent::InitialState::NOT_SIGNALED);
141 Thread flush_thread("flush");
142 flush_thread.Start();
143 flush_thread.task_runner()->PostTask(
144 FROM_HERE,
145 base::BindOnce(&TraceEventTestFixture::EndTraceAndFlushAsync,
146 base::Unretained(this), &flush_complete_event));
147 flush_complete_event.Wait();
148 }
149
CancelTraceAsync(WaitableEvent * flush_complete_event)150 void CancelTraceAsync(WaitableEvent* flush_complete_event) {
151 TraceLog::GetInstance()->CancelTracing(base::BindRepeating(
152 &TraceEventTestFixture::OnTraceDataCollected,
153 base::Unretained(static_cast<TraceEventTestFixture*>(this)),
154 base::Unretained(flush_complete_event)));
155 }
156
EndTraceAndFlushAsync(WaitableEvent * flush_complete_event)157 void EndTraceAndFlushAsync(WaitableEvent* flush_complete_event) {
158 TraceLog::GetInstance()->SetDisabled(TraceLog::RECORDING_MODE);
159 TraceLog::GetInstance()->Flush(base::BindRepeating(
160 &TraceEventTestFixture::OnTraceDataCollected,
161 base::Unretained(static_cast<TraceEventTestFixture*>(this)),
162 base::Unretained(flush_complete_event)));
163 }
164
SetUp()165 void SetUp() override {
166 const char* name = PlatformThread::GetName();
167 old_thread_name_ = name ? name : "";
168
169 TraceLog::ResetForTesting();
170 TraceLog* tracelog = TraceLog::GetInstance();
171 ASSERT_TRUE(tracelog);
172 ASSERT_FALSE(tracelog->IsEnabled());
173 trace_buffer_.SetOutputCallback(json_output_.GetCallback());
174 num_flush_callbacks_ = 0;
175 }
TearDown()176 void TearDown() override {
177 if (TraceLog::GetInstance())
178 EXPECT_FALSE(TraceLog::GetInstance()->IsEnabled());
179 PlatformThread::SetName(old_thread_name_);
180 // We want our singleton torn down after each test.
181 TraceLog::ResetForTesting();
182 }
183
184 std::string old_thread_name_;
185 Value::List trace_parsed_;
186 TraceResultBuffer trace_buffer_;
187 TraceResultBuffer::SimpleOutput json_output_;
188 size_t num_flush_callbacks_;
189
190 private:
191 // We want our singleton torn down after each test.
192 ShadowingAtExitManager at_exit_manager_;
193 Lock lock_;
194 };
195
OnTraceDataCollected(WaitableEvent * flush_complete_event,const scoped_refptr<base::RefCountedString> & events_str,bool has_more_events)196 void TraceEventTestFixture::OnTraceDataCollected(
197 WaitableEvent* flush_complete_event,
198 const scoped_refptr<base::RefCountedString>& events_str,
199 bool has_more_events) {
200 num_flush_callbacks_++;
201 if (num_flush_callbacks_ > 1) {
202 EXPECT_FALSE(events_str->data().empty());
203 }
204 AutoLock lock(lock_);
205 json_output_.json_output.clear();
206 trace_buffer_.Start();
207 trace_buffer_.AddFragment(events_str->data());
208 trace_buffer_.Finish();
209
210 absl::optional<Value> root = base::JSONReader::Read(
211 json_output_.json_output, JSON_PARSE_RFC | JSON_ALLOW_CONTROL_CHARS);
212
213 if (!root.has_value()) {
214 LOG(ERROR) << json_output_.json_output;
215 }
216
217 ASSERT_TRUE(root->is_list());
218 Value::List& root_list = root->GetList();
219
220 // Move items into our aggregate collection
221 trace_parsed_.reserve(trace_parsed_.size() + root_list.size());
222 for (auto& value : root_list)
223 trace_parsed_.Append(std::move(value));
224
225 if (!has_more_events)
226 flush_complete_event->Signal();
227 }
228
CompareJsonValues(const std::string & lhs,const std::string & rhs,CompareOp op)229 static bool CompareJsonValues(const std::string& lhs,
230 const std::string& rhs,
231 CompareOp op) {
232 switch (op) {
233 case IS_EQUAL:
234 return lhs == rhs;
235 case IS_NOT_EQUAL:
236 return lhs != rhs;
237 }
238 return false;
239 }
240
IsKeyValueInDict(const JsonKeyValue * key_value,const Value::Dict * dict)241 static bool IsKeyValueInDict(const JsonKeyValue* key_value,
242 const Value::Dict* dict) {
243 const std::string* value_str = dict->FindStringByDottedPath(key_value->key);
244 if (value_str &&
245 CompareJsonValues(*value_str, key_value->value, key_value->op))
246 return true;
247
248 // Recurse to test arguments
249 const Value::Dict* args_dict = dict->FindDictByDottedPath("args");
250 if (args_dict)
251 return IsKeyValueInDict(key_value, args_dict);
252
253 return false;
254 }
255
IsAllKeyValueInDict(const JsonKeyValue * key_values,const Value::Dict * dict)256 static bool IsAllKeyValueInDict(const JsonKeyValue* key_values,
257 const Value::Dict* dict) {
258 // Scan all key_values, they must all be present and equal.
259 while (key_values && key_values->key) {
260 if (!IsKeyValueInDict(key_values, dict)) {
261 return false;
262 }
263 ++key_values;
264 }
265 return true;
266 }
267
FindMatchingTraceEntry(const JsonKeyValue * key_values)268 const Value::Dict* TraceEventTestFixture::FindMatchingTraceEntry(
269 const JsonKeyValue* key_values) {
270 // Scan all items
271 for (const Value& value : trace_parsed_) {
272 if (!value.is_dict()) {
273 continue;
274 }
275
276 if (IsAllKeyValueInDict(key_values, &value.GetDict())) {
277 return &value.GetDict();
278 }
279 }
280 return nullptr;
281 }
282
DropTracedMetadataRecords()283 void TraceEventTestFixture::DropTracedMetadataRecords() {
284 trace_parsed_.EraseIf([](const Value& value) {
285 if (!value.is_dict()) {
286 return false;
287 }
288 const std::string* ph = value.GetDict().FindString("ph");
289 return ph && *ph == "M";
290 });
291 }
292
FindNamePhase(const char * name,const char * phase)293 const Value::Dict* TraceEventTestFixture::FindNamePhase(const char* name,
294 const char* phase) {
295 JsonKeyValue key_values[] = {{"name", name, IS_EQUAL},
296 {"ph", phase, IS_EQUAL},
297 {nullptr, nullptr, IS_EQUAL}};
298 return FindMatchingTraceEntry(key_values);
299 }
300
FindNamePhaseKeyValue(const char * name,const char * phase,const char * key,const char * value)301 const Value::Dict* TraceEventTestFixture::FindNamePhaseKeyValue(
302 const char* name,
303 const char* phase,
304 const char* key,
305 const char* value) {
306 JsonKeyValue key_values[] = {{"name", name, IS_EQUAL},
307 {"ph", phase, IS_EQUAL},
308 {key, value, IS_EQUAL},
309 {nullptr, nullptr, IS_EQUAL}};
310 return FindMatchingTraceEntry(key_values);
311 }
312
FindMatchingValue(const char * key,const char * value)313 bool TraceEventTestFixture::FindMatchingValue(const char* key,
314 const char* value) {
315 JsonKeyValue key_values[] = {{key, value, IS_EQUAL},
316 {nullptr, nullptr, IS_EQUAL}};
317 return FindMatchingTraceEntry(key_values);
318 }
319
FindNonMatchingValue(const char * key,const char * value)320 bool TraceEventTestFixture::FindNonMatchingValue(const char* key,
321 const char* value) {
322 JsonKeyValue key_values[] = {{key, value, IS_NOT_EQUAL},
323 {nullptr, nullptr, IS_EQUAL}};
324 return FindMatchingTraceEntry(key_values);
325 }
326
IsStringInDict(const char * string_to_match,const Value::Dict * dict)327 bool IsStringInDict(const char* string_to_match, const Value::Dict* dict) {
328 for (const auto pair : *dict) {
329 if (pair.first.find(string_to_match) != std::string::npos)
330 return true;
331
332 if (!pair.second.is_string())
333 continue;
334
335 if (pair.second.GetString().find(string_to_match) != std::string::npos)
336 return true;
337 }
338
339 // Recurse to test arguments
340 const Value::Dict* args_dict = dict->FindDict("args");
341 if (args_dict) {
342 return IsStringInDict(string_to_match, args_dict);
343 }
344
345 return false;
346 }
347
FindTraceEntry(const Value::List & trace_parsed,const char * string_to_match,const Value::Dict * match_after_this_item=nullptr)348 const Value::Dict* FindTraceEntry(
349 const Value::List& trace_parsed,
350 const char* string_to_match,
351 const Value::Dict* match_after_this_item = nullptr) {
352 // Scan all items.
353 for (const Value& value : trace_parsed) {
354 const Value::Dict* dict = value.GetIfDict();
355 if (!dict) {
356 continue;
357 }
358 if (match_after_this_item) {
359 if (dict == match_after_this_item) {
360 match_after_this_item = nullptr;
361 }
362 continue;
363 }
364
365 if (IsStringInDict(string_to_match, dict)) {
366 return dict;
367 }
368 }
369 return nullptr;
370 }
371
372 #if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
FindTraceEntries(const Value::List & trace_parsed,const char * string_to_match)373 std::vector<const Value::Dict*> FindTraceEntries(
374 const Value::List& trace_parsed,
375 const char* string_to_match) {
376 std::vector<const Value::Dict*> hits;
377 for (const Value& value : trace_parsed) {
378 if (!value.is_dict()) {
379 continue;
380 }
381
382 if (IsStringInDict(string_to_match, &value.GetDict())) {
383 hits.push_back(&value.GetDict());
384 }
385 }
386 return hits;
387 }
388 #endif // !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
389
390 constexpr const char kControlCharacters[] = "test_\001\002\003\n\r";
391
TraceWithAllMacroVariants(WaitableEvent * task_complete_event)392 void TraceWithAllMacroVariants(WaitableEvent* task_complete_event) {
393 {
394 TRACE_EVENT0("test_all", "TRACE_EVENT0 call");
395 TRACE_EVENT1("test_all", "TRACE_EVENT1 call", "name1", "value1");
396 TRACE_EVENT2("test_all", "TRACE_EVENT2 call", "name1", "\"value1\"",
397 "name2", "value\\2");
398
399 TRACE_EVENT_INSTANT0("test_all", "TRACE_EVENT_INSTANT0 call",
400 TRACE_EVENT_SCOPE_GLOBAL);
401 TRACE_EVENT_INSTANT1("test_all", "TRACE_EVENT_INSTANT1 call",
402 TRACE_EVENT_SCOPE_PROCESS, "name1", "value1");
403 TRACE_EVENT_INSTANT2("test_all", "TRACE_EVENT_INSTANT2 call",
404 TRACE_EVENT_SCOPE_THREAD, "name1", "value1", "name2",
405 "value2");
406
407 TRACE_EVENT_BEGIN0("test_all", "TRACE_EVENT_BEGIN0 call");
408 TRACE_EVENT_BEGIN1("test_all", "TRACE_EVENT_BEGIN1 call", "name1",
409 "value1");
410 TRACE_EVENT_BEGIN2("test_all", "TRACE_EVENT_BEGIN2 call", "name1", "value1",
411 "name2", "value2");
412
413 TRACE_EVENT_END0("test_all", "TRACE_EVENT_BEGIN2 call");
414 TRACE_EVENT_END1("test_all", "TRACE_EVENT_BEGIN1 call", "name1", "value1");
415 TRACE_EVENT_END2("test_all", "TRACE_EVENT_BEGIN0 call", "name1", "value1",
416 "name2", "value2");
417
418 TRACE_EVENT_ASYNC_BEGIN0("test_all", "TRACE_EVENT_ASYNC_BEGIN0 call",
419 kAsyncId);
420 TRACE_EVENT_ASYNC_BEGIN1("test_all", "TRACE_EVENT_ASYNC_BEGIN1 call",
421 kAsyncId, "name1", "value1");
422 TRACE_EVENT_ASYNC_BEGIN2("test_all", "TRACE_EVENT_ASYNC_BEGIN2 call",
423 kAsyncId, "name1", "value1", "name2", "value2");
424
425 TRACE_EVENT_ASYNC_STEP_INTO0("test_all",
426 "TRACE_EVENT_ASYNC_STEP_INTO0 call", kAsyncId,
427 "step_begin1");
428 TRACE_EVENT_ASYNC_STEP_INTO1("test_all",
429 "TRACE_EVENT_ASYNC_STEP_INTO1 call", kAsyncId,
430 "step_begin2", "name1", "value1");
431
432 TRACE_EVENT_ASYNC_END0("test_all", "TRACE_EVENT_ASYNC_END0 call", kAsyncId);
433 TRACE_EVENT_ASYNC_END1("test_all", "TRACE_EVENT_ASYNC_END1 call", kAsyncId,
434 "name1", "value1");
435 TRACE_EVENT_ASYNC_END2("test_all", "TRACE_EVENT_ASYNC_END2 call", kAsyncId,
436 "name1", "value1", "name2", "value2");
437
438 TRACE_COUNTER1("test_all", "TRACE_COUNTER1 call", 31415);
439 TRACE_COUNTER2("test_all", "TRACE_COUNTER2 call", "a", 30000, "b", 1415);
440
441 TRACE_COUNTER_WITH_TIMESTAMP1("test_all",
442 "TRACE_COUNTER_WITH_TIMESTAMP1 call",
443 TimeTicks::FromInternalValue(42), 31415);
444 TRACE_COUNTER_WITH_TIMESTAMP2(
445 "test_all", "TRACE_COUNTER_WITH_TIMESTAMP2 call",
446 TimeTicks::FromInternalValue(42), "a", 30000, "b", 1415);
447
448 TRACE_COUNTER_ID1("test_all", "TRACE_COUNTER_ID1 call", 0x319009, 31415);
449 TRACE_COUNTER_ID2("test_all", "TRACE_COUNTER_ID2 call", 0x319009, "a",
450 30000, "b", 1415);
451
452 TRACE_EVENT_ASYNC_STEP_PAST0("test_all",
453 "TRACE_EVENT_ASYNC_STEP_PAST0 call", kAsyncId2,
454 "step_end1");
455 TRACE_EVENT_ASYNC_STEP_PAST1("test_all",
456 "TRACE_EVENT_ASYNC_STEP_PAST1 call", kAsyncId2,
457 "step_end2", "name1", "value1");
458
459 TRACE_EVENT_OBJECT_CREATED_WITH_ID("test_all", "tracked object 1", 0x42);
460 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID("test_all", "tracked object 1", 0x42,
461 "hello");
462 TRACE_EVENT_OBJECT_DELETED_WITH_ID("test_all", "tracked object 1", 0x42);
463
464 TraceScopedTrackableObject<int, kAllCategory> trackable("tracked object 2",
465 0x2128506);
466 trackable.snapshot("world");
467
468 TRACE_EVENT_OBJECT_CREATED_WITH_ID("test_all", "tracked object 3",
469 TRACE_ID_WITH_SCOPE("scope", 0x42));
470 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID("test_all", "tracked object 3",
471 TRACE_ID_WITH_SCOPE("scope", 0x42),
472 "hello");
473 TRACE_EVENT_OBJECT_DELETED_WITH_ID("test_all", "tracked object 3",
474 TRACE_ID_WITH_SCOPE("scope", 0x42));
475
476 TRACE_EVENT1(kControlCharacters, kControlCharacters,
477 kControlCharacters, kControlCharacters);
478
479 TRACE_EVENT_ASYNC_BEGIN0("test_all", "async default process scope", 0x1000);
480 TRACE_EVENT_ASYNC_BEGIN0("test_all", "async local id",
481 TRACE_ID_LOCAL(0x2000));
482 TRACE_EVENT_ASYNC_BEGIN0("test_all", "async global id",
483 TRACE_ID_GLOBAL(0x3000));
484 TRACE_EVENT_ASYNC_BEGIN0(
485 "test_all", "async global id with scope string",
486 TRACE_ID_WITH_SCOPE("scope string", TRACE_ID_GLOBAL(0x4000)));
487 } // Scope close causes TRACE_EVENT0 etc to send their END events.
488
489 if (task_complete_event)
490 task_complete_event->Signal();
491 }
492
ValidateAllTraceMacrosCreatedData(const Value::List & trace_parsed)493 void ValidateAllTraceMacrosCreatedData(const Value::List& trace_parsed) {
494 const Value::Dict* item = nullptr;
495
496 #define EXPECT_FIND_(string) \
497 item = FindTraceEntry(trace_parsed, string); \
498 EXPECT_TRUE(item);
499 #define EXPECT_NOT_FIND_(string) \
500 item = FindTraceEntry(trace_parsed, string); \
501 EXPECT_FALSE(item);
502 #define EXPECT_SUB_FIND_(string) \
503 if (item) \
504 EXPECT_TRUE(IsStringInDict(string, item));
505
506 EXPECT_FIND_("TRACE_EVENT0 call");
507 {
508 EXPECT_TRUE((item = FindTraceEntry(trace_parsed, "TRACE_EVENT0 call")));
509 EXPECT_EQ(*item->FindString("ph"), "X");
510 item = FindTraceEntry(trace_parsed, "TRACE_EVENT0 call", item);
511 EXPECT_FALSE(item);
512 }
513 EXPECT_FIND_("TRACE_EVENT1 call");
514 EXPECT_SUB_FIND_("name1");
515 EXPECT_SUB_FIND_("value1");
516 EXPECT_FIND_("TRACE_EVENT2 call");
517 EXPECT_SUB_FIND_("name1");
518 EXPECT_SUB_FIND_("\"value1\"");
519 EXPECT_SUB_FIND_("name2");
520 EXPECT_SUB_FIND_("value\\2");
521
522 EXPECT_FIND_("TRACE_EVENT_INSTANT0 call");
523 { EXPECT_EQ(*item->FindString("s"), "g"); }
524 EXPECT_FIND_("TRACE_EVENT_INSTANT1 call");
525 { EXPECT_EQ(*item->FindString("s"), "p"); }
526 EXPECT_SUB_FIND_("name1");
527 EXPECT_SUB_FIND_("value1");
528 EXPECT_FIND_("TRACE_EVENT_INSTANT2 call");
529 { EXPECT_EQ(*item->FindString("s"), "t"); }
530 EXPECT_SUB_FIND_("name1");
531 EXPECT_SUB_FIND_("value1");
532 EXPECT_SUB_FIND_("name2");
533 EXPECT_SUB_FIND_("value2");
534
535 EXPECT_FIND_("TRACE_EVENT_BEGIN0 call");
536 EXPECT_FIND_("TRACE_EVENT_BEGIN1 call");
537 EXPECT_SUB_FIND_("name1");
538 EXPECT_SUB_FIND_("value1");
539 EXPECT_FIND_("TRACE_EVENT_BEGIN2 call");
540 EXPECT_SUB_FIND_("name1");
541 EXPECT_SUB_FIND_("value1");
542 EXPECT_SUB_FIND_("name2");
543 EXPECT_SUB_FIND_("value2");
544
545 EXPECT_FIND_("TRACE_EVENT_ASYNC_BEGIN0 call");
546 EXPECT_SUB_FIND_("id");
547 EXPECT_SUB_FIND_(kAsyncIdStr);
548 EXPECT_FIND_("TRACE_EVENT_ASYNC_BEGIN1 call");
549 EXPECT_SUB_FIND_("id");
550 EXPECT_SUB_FIND_(kAsyncIdStr);
551 EXPECT_SUB_FIND_("name1");
552 EXPECT_SUB_FIND_("value1");
553 EXPECT_FIND_("TRACE_EVENT_ASYNC_BEGIN2 call");
554 EXPECT_SUB_FIND_("id");
555 EXPECT_SUB_FIND_(kAsyncIdStr);
556 EXPECT_SUB_FIND_("name1");
557 EXPECT_SUB_FIND_("value1");
558 EXPECT_SUB_FIND_("name2");
559 EXPECT_SUB_FIND_("value2");
560
561 EXPECT_FIND_("TRACE_EVENT_ASYNC_STEP_INTO0 call");
562 EXPECT_SUB_FIND_("id");
563 EXPECT_SUB_FIND_(kAsyncIdStr);
564 EXPECT_SUB_FIND_("step_begin1");
565 EXPECT_FIND_("TRACE_EVENT_ASYNC_STEP_INTO1 call");
566 EXPECT_SUB_FIND_("id");
567 EXPECT_SUB_FIND_(kAsyncIdStr);
568 EXPECT_SUB_FIND_("step_begin2");
569 EXPECT_SUB_FIND_("name1");
570 EXPECT_SUB_FIND_("value1");
571
572 // Perfetto doesn't have separate begin and end events.
573 #if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
574 EXPECT_FIND_("TRACE_EVENT_ASYNC_END0 call");
575 EXPECT_SUB_FIND_("id");
576 EXPECT_SUB_FIND_(kAsyncIdStr);
577 EXPECT_FIND_("TRACE_EVENT_ASYNC_END1 call");
578 EXPECT_SUB_FIND_("id");
579 EXPECT_SUB_FIND_(kAsyncIdStr);
580 EXPECT_SUB_FIND_("name1");
581 EXPECT_SUB_FIND_("value1");
582 EXPECT_FIND_("TRACE_EVENT_ASYNC_END2 call");
583 EXPECT_SUB_FIND_("id");
584 EXPECT_SUB_FIND_(kAsyncIdStr);
585 EXPECT_SUB_FIND_("name1");
586 EXPECT_SUB_FIND_("value1");
587 EXPECT_SUB_FIND_("name2");
588 EXPECT_SUB_FIND_("value2");
589 #endif // !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
590
591 EXPECT_FIND_("TRACE_COUNTER1 call");
592 {
593 EXPECT_EQ(*item->FindString("ph"), "C");
594
595 EXPECT_EQ(*item->FindIntByDottedPath("args.value"), 31415);
596 }
597
598 EXPECT_FIND_("TRACE_COUNTER2 call");
599 {
600 EXPECT_EQ(*item->FindString("ph"), "C");
601
602 EXPECT_EQ(*item->FindIntByDottedPath("args.a"), 30000);
603
604 EXPECT_EQ(*item->FindIntByDottedPath("args.b"), 1415);
605 }
606
607 EXPECT_FIND_("TRACE_COUNTER_WITH_TIMESTAMP1 call");
608 {
609 EXPECT_EQ(*item->FindString("ph"), "C");
610
611 EXPECT_EQ(*item->FindIntByDottedPath("args.value"), 31415);
612
613 EXPECT_EQ(*item->FindInt("ts"), 42);
614 }
615
616 EXPECT_FIND_("TRACE_COUNTER_WITH_TIMESTAMP2 call");
617 {
618 EXPECT_EQ(*item->FindString("ph"), "C");
619
620 EXPECT_EQ(*item->FindIntByDottedPath("args.a"), 30000);
621
622 EXPECT_EQ(*item->FindIntByDottedPath("args.b"), 1415);
623
624 EXPECT_EQ(*item->FindInt("ts"), 42);
625 }
626
627 EXPECT_FIND_("TRACE_COUNTER_ID1 call");
628 {
629 EXPECT_EQ(*item->FindString("id"), "0x319009");
630
631 EXPECT_EQ(*item->FindString("ph"), "C");
632
633 EXPECT_EQ(*item->FindIntByDottedPath("args.value"), 31415);
634 }
635
636 EXPECT_FIND_("TRACE_COUNTER_ID2 call");
637 {
638 EXPECT_EQ(*item->FindString("id"), "0x319009");
639
640 EXPECT_EQ(*item->FindString("ph"), "C");
641
642 EXPECT_EQ(*item->FindIntByDottedPath("args.a"), 30000);
643
644 EXPECT_EQ(*item->FindIntByDottedPath("args.b"), 1415);
645 }
646
647 EXPECT_FIND_("TRACE_EVENT_ASYNC_STEP_PAST0 call");
648 {
649 EXPECT_SUB_FIND_("id");
650 EXPECT_SUB_FIND_(kAsyncId2Str);
651 EXPECT_SUB_FIND_("step_end1");
652 EXPECT_FIND_("TRACE_EVENT_ASYNC_STEP_PAST1 call");
653 EXPECT_SUB_FIND_("id");
654 EXPECT_SUB_FIND_(kAsyncId2Str);
655 EXPECT_SUB_FIND_("step_end2");
656 EXPECT_SUB_FIND_("name1");
657 EXPECT_SUB_FIND_("value1");
658 }
659
660 EXPECT_FIND_("tracked object 1");
661 {
662 EXPECT_EQ(*item->FindString("ph"), "N");
663 EXPECT_FALSE(item->contains("scope"));
664 EXPECT_EQ(*item->FindString("id"), "0x42");
665
666 item = FindTraceEntry(trace_parsed, "tracked object 1", item);
667 EXPECT_TRUE(item);
668 EXPECT_EQ(*item->FindString("ph"), "O");
669 EXPECT_FALSE(item->contains("scope"));
670 EXPECT_EQ(*item->FindString("id"), "0x42");
671 EXPECT_EQ(*item->FindStringByDottedPath("args.snapshot"), "hello");
672
673 item = FindTraceEntry(trace_parsed, "tracked object 1", item);
674 EXPECT_TRUE(item);
675 EXPECT_EQ(*item->FindString("ph"), "D");
676 EXPECT_FALSE(item->contains("scope"));
677 EXPECT_EQ(*item->FindString("id"), "0x42");
678 }
679
680 EXPECT_FIND_("tracked object 2");
681 {
682 EXPECT_EQ(*item->FindString("ph"), "N");
683 EXPECT_EQ(*item->FindString("id"), "0x2128506");
684
685 item = FindTraceEntry(trace_parsed, "tracked object 2", item);
686 EXPECT_TRUE(item);
687 EXPECT_EQ(*item->FindString("ph"), "O");
688 EXPECT_EQ(*item->FindString("id"), "0x2128506");
689 EXPECT_EQ(*item->FindStringByDottedPath("args.snapshot"), "world");
690
691 item = FindTraceEntry(trace_parsed, "tracked object 2", item);
692 EXPECT_TRUE(item);
693 EXPECT_EQ(*item->FindString("ph"), "D");
694 EXPECT_EQ(*item->FindString("id"), "0x2128506");
695 }
696
697 EXPECT_FIND_("tracked object 3");
698 {
699 #if BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
700 auto* id_hash = "0x6a31ee0fa7951e05";
701 #else
702 auto* id_hash = "0x42";
703 #endif
704 EXPECT_EQ(*item->FindString("ph"), "N");
705 EXPECT_EQ(*item->FindString("scope"), "scope");
706 EXPECT_EQ(*item->FindString("id"), id_hash);
707
708 item = FindTraceEntry(trace_parsed, "tracked object 3", item);
709 EXPECT_TRUE(item);
710 EXPECT_EQ(*item->FindString("ph"), "O");
711 EXPECT_EQ(*item->FindString("scope"), "scope");
712 EXPECT_EQ(*item->FindString("id"), id_hash);
713 EXPECT_EQ(*item->FindStringByDottedPath("args.snapshot"), "hello");
714
715 item = FindTraceEntry(trace_parsed, "tracked object 3", item);
716 EXPECT_TRUE(item);
717 EXPECT_EQ(*item->FindString("ph"), "D");
718 EXPECT_EQ(*item->FindString("scope"), "scope");
719 EXPECT_EQ(*item->FindString("id"), id_hash);
720 }
721
722 EXPECT_FIND_(kControlCharacters);
723 EXPECT_SUB_FIND_(kControlCharacters);
724
725 EXPECT_FIND_("async default process scope");
726 {
727 EXPECT_EQ(*item->FindString("ph"), "S");
728
729 EXPECT_EQ(*item->FindString("id"), "0x1000");
730 }
731
732 EXPECT_FIND_("async local id");
733 {
734 EXPECT_EQ(*item->FindString("ph"), "S");
735
736 EXPECT_EQ(*item->FindStringByDottedPath("id2.local"), "0x2000");
737 }
738
739 EXPECT_FIND_("async global id");
740 {
741 EXPECT_EQ(*item->FindString("ph"), "S");
742
743 #if BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
744 const char kIdPath[] = "id";
745 #else
746 const char kIdPath[] = "id2.global";
747 #endif
748 EXPECT_EQ(*item->FindStringByDottedPath(kIdPath), "0x3000");
749 }
750
751 EXPECT_FIND_("async global id with scope string");
752 {
753 EXPECT_EQ(*item->FindString("ph"), "S");
754
755 #if BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
756 const char kIdPath[] = "id";
757 #else
758 const char kIdPath[] = "id2.global";
759 #endif
760 EXPECT_EQ(*item->FindStringByDottedPath(kIdPath), "0x4000");
761
762 #if BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
763 const char kExpectedScope[] = "test_all:scope string";
764 #else
765 const char kExpectedScope[] = "scope string";
766 #endif
767
768 EXPECT_EQ(*item->FindStringByDottedPath("scope"), kExpectedScope);
769 }
770 }
771
TraceManyInstantEvents(int thread_id,int num_events,WaitableEvent * task_complete_event)772 void TraceManyInstantEvents(int thread_id, int num_events,
773 WaitableEvent* task_complete_event) {
774 for (int i = 0; i < num_events; i++) {
775 TRACE_EVENT_INSTANT2("test_all", "multi thread event",
776 TRACE_EVENT_SCOPE_THREAD, "thread", thread_id, "event",
777 i);
778 }
779
780 if (task_complete_event)
781 task_complete_event->Signal();
782 }
783
ValidateInstantEventPresentOnEveryThread(const Value::List & trace_parsed,int num_threads,int num_events)784 void ValidateInstantEventPresentOnEveryThread(const Value::List& trace_parsed,
785 int num_threads,
786 int num_events) {
787 std::map<int, std::map<int, bool>> results;
788
789 for (const Value& value : trace_parsed) {
790 const Value::Dict* dict = value.GetIfDict();
791 if (!dict) {
792 continue;
793 }
794
795 const std::string* name = dict->FindString("name");
796 if (!name || *name != "multi thread event")
797 continue;
798
799 absl::optional<int> maybe_thread = dict->FindIntByDottedPath("args.thread");
800 absl::optional<int> maybe_event = dict->FindIntByDottedPath("args.event");
801
802 EXPECT_TRUE(maybe_thread.has_value());
803 EXPECT_TRUE(maybe_event.has_value());
804 results[maybe_thread.value_or(0)][maybe_event.value_or(0)] = true;
805 }
806
807 EXPECT_FALSE(results[-1][-1]);
808 for (int thread = 0; thread < num_threads; thread++) {
809 for (int event = 0; event < num_events; event++) {
810 EXPECT_TRUE(results[thread][event]);
811 }
812 }
813 }
814
CheckTraceDefaultCategoryFilters(const TraceLog & trace_log)815 void CheckTraceDefaultCategoryFilters(const TraceLog& trace_log) {
816 // Default enables all category filters except the disabled-by-default-* ones.
817 EXPECT_TRUE(IsCategoryEnabled("foo"));
818 EXPECT_TRUE(IsCategoryEnabled("bar"));
819 EXPECT_TRUE(IsCategoryEnabled("foo,bar"));
820 EXPECT_TRUE(IsCategoryEnabled("foo,disabled-by-default-foo"));
821 EXPECT_FALSE(
822 IsCategoryEnabled("disabled-by-default-foo,disabled-by-default-bar"));
823 }
824
825 } // namespace
826
827 // Simple Test for emitting data and validating it was received.
TEST_F(TraceEventTestFixture,DataCaptured)828 TEST_F(TraceEventTestFixture, DataCaptured) {
829 TraceLog::GetInstance()->SetEnabled(TraceConfig(kRecordAllCategoryFilter, ""),
830 TraceLog::RECORDING_MODE);
831
832 TraceWithAllMacroVariants(nullptr);
833
834 EndTraceAndFlush();
835
836 ValidateAllTraceMacrosCreatedData(trace_parsed_);
837 }
838
839 // Emit some events and validate that only empty strings are received
840 // if we tell Flush() to discard events.
TEST_F(TraceEventTestFixture,DataDiscarded)841 TEST_F(TraceEventTestFixture, DataDiscarded) {
842 TraceLog::GetInstance()->SetEnabled(TraceConfig(kRecordAllCategoryFilter, ""),
843 TraceLog::RECORDING_MODE);
844
845 TraceWithAllMacroVariants(nullptr);
846
847 CancelTrace();
848
849 EXPECT_TRUE(trace_parsed_.empty());
850 }
851
852 class MockEnabledStateChangedObserver :
853 public TraceLog::EnabledStateObserver {
854 public:
855 MOCK_METHOD0(OnTraceLogEnabled, void());
856 MOCK_METHOD0(OnTraceLogDisabled, void());
857 };
858
TEST_F(TraceEventTestFixture,EnabledObserverFiresOnEnable)859 TEST_F(TraceEventTestFixture, EnabledObserverFiresOnEnable) {
860 MockEnabledStateChangedObserver observer;
861 TraceLog::GetInstance()->AddEnabledStateObserver(&observer);
862
863 EXPECT_CALL(observer, OnTraceLogEnabled())
864 .Times(1);
865 TraceLog::GetInstance()->SetEnabled(TraceConfig(kRecordAllCategoryFilter, ""),
866 TraceLog::RECORDING_MODE);
867 testing::Mock::VerifyAndClear(&observer);
868 EXPECT_TRUE(TraceLog::GetInstance()->IsEnabled());
869
870 // Cleanup.
871 TraceLog::GetInstance()->RemoveEnabledStateObserver(&observer);
872 TraceLog::GetInstance()->SetDisabled();
873 }
874
875 // Nested TraceLog enabling isn't supported by Perfetto.
876 #if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
TEST_F(TraceEventTestFixture,EnabledObserverDoesntFireOnSecondEnable)877 TEST_F(TraceEventTestFixture, EnabledObserverDoesntFireOnSecondEnable) {
878 TraceLog::GetInstance()->SetEnabled(TraceConfig(kRecordAllCategoryFilter, ""),
879 TraceLog::RECORDING_MODE);
880
881 testing::StrictMock<MockEnabledStateChangedObserver> observer;
882 TraceLog::GetInstance()->AddEnabledStateObserver(&observer);
883
884 EXPECT_CALL(observer, OnTraceLogEnabled())
885 .Times(0);
886 EXPECT_CALL(observer, OnTraceLogDisabled())
887 .Times(0);
888 TraceLog::GetInstance()->SetEnabled(TraceConfig(kRecordAllCategoryFilter, ""),
889 TraceLog::RECORDING_MODE);
890 testing::Mock::VerifyAndClear(&observer);
891 EXPECT_TRUE(TraceLog::GetInstance()->IsEnabled());
892
893 // Cleanup.
894 TraceLog::GetInstance()->RemoveEnabledStateObserver(&observer);
895 TraceLog::GetInstance()->SetDisabled();
896 TraceLog::GetInstance()->SetDisabled();
897 }
898
TEST_F(TraceEventTestFixture,EnabledObserverFiresOnFirstDisable)899 TEST_F(TraceEventTestFixture, EnabledObserverFiresOnFirstDisable) {
900 TraceConfig tc_inc_all("*", "");
901 TraceLog::GetInstance()->SetEnabled(tc_inc_all, TraceLog::RECORDING_MODE);
902 TraceLog::GetInstance()->SetEnabled(tc_inc_all, TraceLog::RECORDING_MODE);
903
904 testing::StrictMock<MockEnabledStateChangedObserver> observer;
905 TraceLog::GetInstance()->AddEnabledStateObserver(&observer);
906
907 EXPECT_CALL(observer, OnTraceLogEnabled())
908 .Times(0);
909 EXPECT_CALL(observer, OnTraceLogDisabled())
910 .Times(1);
911 TraceLog::GetInstance()->SetDisabled();
912 testing::Mock::VerifyAndClear(&observer);
913
914 // Cleanup.
915 TraceLog::GetInstance()->RemoveEnabledStateObserver(&observer);
916 TraceLog::GetInstance()->SetDisabled();
917 }
918 #endif // !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
919
TEST_F(TraceEventTestFixture,EnabledObserverFiresOnDisable)920 TEST_F(TraceEventTestFixture, EnabledObserverFiresOnDisable) {
921 TraceLog::GetInstance()->SetEnabled(TraceConfig(kRecordAllCategoryFilter, ""),
922 TraceLog::RECORDING_MODE);
923
924 MockEnabledStateChangedObserver observer;
925 TraceLog::GetInstance()->AddEnabledStateObserver(&observer);
926
927 EXPECT_CALL(observer, OnTraceLogDisabled())
928 .Times(1);
929 TraceLog::GetInstance()->SetDisabled();
930 testing::Mock::VerifyAndClear(&observer);
931
932 // Cleanup.
933 TraceLog::GetInstance()->RemoveEnabledStateObserver(&observer);
934 }
935
TEST_F(TraceEventTestFixture,EnabledObserverOwnedByTraceLog)936 TEST_F(TraceEventTestFixture, EnabledObserverOwnedByTraceLog) {
937 auto observer = std::make_unique<MockEnabledStateChangedObserver>();
938 EXPECT_CALL(*observer, OnTraceLogEnabled()).Times(1);
939 EXPECT_CALL(*observer, OnTraceLogDisabled()).Times(1);
940 TraceLog::GetInstance()->AddOwnedEnabledStateObserver(std::move(observer));
941 TraceLog::GetInstance()->SetEnabled(TraceConfig(kRecordAllCategoryFilter, ""),
942 TraceLog::RECORDING_MODE);
943 TraceLog::GetInstance()->SetDisabled();
944 TraceLog::ResetForTesting();
945 // These notifications won't be sent.
946 TraceLog::GetInstance()->SetEnabled(TraceConfig(kRecordAllCategoryFilter, ""),
947 TraceLog::RECORDING_MODE);
948 TraceLog::GetInstance()->SetDisabled();
949 }
950
951 // Tests the IsEnabled() state of TraceLog changes before callbacks.
952 class AfterStateChangeEnabledStateObserver
953 : public TraceLog::EnabledStateObserver {
954 public:
955 AfterStateChangeEnabledStateObserver() = default;
956 ~AfterStateChangeEnabledStateObserver() override = default;
957
958 // TraceLog::EnabledStateObserver overrides:
OnTraceLogEnabled()959 void OnTraceLogEnabled() override {
960 EXPECT_TRUE(TraceLog::GetInstance()->IsEnabled());
961 }
962
OnTraceLogDisabled()963 void OnTraceLogDisabled() override {
964 EXPECT_FALSE(TraceLog::GetInstance()->IsEnabled());
965 }
966 };
967
TEST_F(TraceEventTestFixture,ObserversFireAfterStateChange)968 TEST_F(TraceEventTestFixture, ObserversFireAfterStateChange) {
969 AfterStateChangeEnabledStateObserver observer;
970 TraceLog::GetInstance()->AddEnabledStateObserver(&observer);
971
972 TraceLog::GetInstance()->SetEnabled(TraceConfig(kRecordAllCategoryFilter, ""),
973 TraceLog::RECORDING_MODE);
974 EXPECT_TRUE(TraceLog::GetInstance()->IsEnabled());
975
976 TraceLog::GetInstance()->SetDisabled();
977 EXPECT_FALSE(TraceLog::GetInstance()->IsEnabled());
978
979 TraceLog::GetInstance()->RemoveEnabledStateObserver(&observer);
980 }
981
982 // Tests that a state observer can remove itself during a callback.
983 class SelfRemovingEnabledStateObserver
984 : public TraceLog::EnabledStateObserver {
985 public:
986 SelfRemovingEnabledStateObserver() = default;
987 ~SelfRemovingEnabledStateObserver() override = default;
988
989 // TraceLog::EnabledStateObserver overrides:
OnTraceLogEnabled()990 void OnTraceLogEnabled() override {}
991
OnTraceLogDisabled()992 void OnTraceLogDisabled() override {
993 TraceLog::GetInstance()->RemoveEnabledStateObserver(this);
994 }
995 };
996
997 // Self removing observers are not supported at the moment.
998 // TODO(alph): We could add support once we have recursive locks.
TEST_F(TraceEventTestFixture,DISABLED_SelfRemovingObserver)999 TEST_F(TraceEventTestFixture, DISABLED_SelfRemovingObserver) {
1000 ASSERT_EQ(0u, TraceLog::GetInstance()->GetObserverCountForTest());
1001
1002 SelfRemovingEnabledStateObserver observer;
1003 TraceLog::GetInstance()->AddEnabledStateObserver(&observer);
1004 EXPECT_EQ(1u, TraceLog::GetInstance()->GetObserverCountForTest());
1005
1006 TraceLog::GetInstance()->SetEnabled(TraceConfig(kRecordAllCategoryFilter, ""),
1007 TraceLog::RECORDING_MODE);
1008 TraceLog::GetInstance()->SetDisabled();
1009 // The observer removed itself on disable.
1010 EXPECT_EQ(0u, TraceLog::GetInstance()->GetObserverCountForTest());
1011 }
1012
IsNewTrace()1013 bool IsNewTrace() {
1014 bool is_new_trace;
1015 TRACE_EVENT_IS_NEW_TRACE(&is_new_trace);
1016 return is_new_trace;
1017 }
1018
TEST_F(TraceEventTestFixture,NewTraceRecording)1019 TEST_F(TraceEventTestFixture, NewTraceRecording) {
1020 ASSERT_FALSE(IsNewTrace());
1021 TraceLog::GetInstance()->SetEnabled(TraceConfig(kRecordAllCategoryFilter, ""),
1022 TraceLog::RECORDING_MODE);
1023 // First call to IsNewTrace() should succeed. But, the second shouldn't.
1024 ASSERT_TRUE(IsNewTrace());
1025 ASSERT_FALSE(IsNewTrace());
1026 EndTraceAndFlush();
1027
1028 // IsNewTrace() should definitely be false now.
1029 ASSERT_FALSE(IsNewTrace());
1030
1031 // Start another trace. IsNewTrace() should become true again, briefly, as
1032 // before.
1033 TraceLog::GetInstance()->SetEnabled(TraceConfig(kRecordAllCategoryFilter, ""),
1034 TraceLog::RECORDING_MODE);
1035 ASSERT_TRUE(IsNewTrace());
1036 ASSERT_FALSE(IsNewTrace());
1037
1038 // Cleanup.
1039 EndTraceAndFlush();
1040 }
1041
1042 // This test is not meaningful with Perfetto's deferred flushing behavior.
1043 #if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
TEST_F(TraceEventTestFixture,TestTraceFlush)1044 TEST_F(TraceEventTestFixture, TestTraceFlush) {
1045 size_t min_traces = 1;
1046 size_t max_traces = 1;
1047 do {
1048 max_traces *= 2;
1049 TraceLog::GetInstance()->SetEnabled(TraceConfig(),
1050 TraceLog::RECORDING_MODE);
1051 for (size_t i = 0; i < max_traces; i++) {
1052 TRACE_EVENT_INSTANT0("test_x", "y", TRACE_EVENT_SCOPE_THREAD);
1053 }
1054 EndTraceAndFlush();
1055 } while (num_flush_callbacks_ < 2);
1056
1057 while (min_traces + 50 < max_traces) {
1058 size_t traces = (min_traces + max_traces) / 2;
1059 TraceLog::GetInstance()->SetEnabled(TraceConfig(),
1060 TraceLog::RECORDING_MODE);
1061 for (size_t i = 0; i < traces; i++) {
1062 TRACE_EVENT_INSTANT0("test_x", "y", TRACE_EVENT_SCOPE_THREAD);
1063 }
1064 EndTraceAndFlush();
1065 if (num_flush_callbacks_ < 2) {
1066 min_traces = traces - 10;
1067 } else {
1068 max_traces = traces + 10;
1069 }
1070 }
1071
1072 for (size_t traces = min_traces; traces < max_traces; traces++) {
1073 TraceLog::GetInstance()->SetEnabled(TraceConfig(),
1074 TraceLog::RECORDING_MODE);
1075 for (size_t i = 0; i < traces; i++) {
1076 TRACE_EVENT_INSTANT0("test_x", "y", TRACE_EVENT_SCOPE_THREAD);
1077 }
1078 EndTraceAndFlush();
1079 }
1080 }
1081 #endif // !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
1082
TEST_F(TraceEventTestFixture,AddMetadataEvent)1083 TEST_F(TraceEventTestFixture, AddMetadataEvent) {
1084 int num_calls = 0;
1085
1086 class Convertable : public ConvertableToTraceFormat {
1087 public:
1088 explicit Convertable(int* num_calls) : num_calls_(num_calls) {}
1089 ~Convertable() override = default;
1090 void AppendAsTraceFormat(std::string* out) const override {
1091 (*num_calls_)++;
1092 out->append("\"metadata_value\"");
1093 }
1094
1095 private:
1096 raw_ptr<int> num_calls_;
1097 };
1098
1099 std::unique_ptr<ConvertableToTraceFormat> conv1(new Convertable(&num_calls));
1100 std::unique_ptr<Convertable> conv2(new Convertable(&num_calls));
1101
1102 BeginTrace();
1103 TRACE_EVENT_API_ADD_METADATA_EVENT(
1104 TraceLog::GetCategoryGroupEnabled("__metadata"), "metadata_event_1",
1105 "metadata_arg_name", std::move(conv1));
1106 TRACE_EVENT_API_ADD_METADATA_EVENT(
1107 TraceLog::GetCategoryGroupEnabled("__metadata"), "metadata_event_2",
1108 "metadata_arg_name", std::move(conv2));
1109 // |AppendAsTraceFormat| should only be called on flush, not when the event
1110 // is added.
1111 ASSERT_EQ(0, num_calls);
1112 EndTraceAndFlush();
1113 ASSERT_EQ(2, num_calls);
1114 EXPECT_TRUE(FindNamePhaseKeyValue("metadata_event_1", "M",
1115 "metadata_arg_name", "metadata_value"));
1116 EXPECT_TRUE(FindNamePhaseKeyValue("metadata_event_2", "M",
1117 "metadata_arg_name", "metadata_value"));
1118
1119 // The metadata event should only be adde to the current trace. In this new
1120 // trace, the event should not appear.
1121 BeginTrace();
1122 EndTraceAndFlush();
1123 ASSERT_EQ(2, num_calls);
1124 }
1125
1126 // Test that categories work.
TEST_F(TraceEventTestFixture,Categories)1127 TEST_F(TraceEventTestFixture, Categories) {
1128 const std::vector<std::string> empty_categories;
1129 std::vector<std::string> included_categories;
1130 std::vector<std::string> excluded_categories;
1131
1132 // Test that category filtering works.
1133
1134 // Include nonexistent category -> no events
1135 Clear();
1136 included_categories.clear();
1137 TraceLog::GetInstance()->SetEnabled(TraceConfig("not_found823564786", ""),
1138 TraceLog::RECORDING_MODE);
1139 TRACE_EVENT_INSTANT0("cat1", "name", TRACE_EVENT_SCOPE_THREAD);
1140 TRACE_EVENT_INSTANT0("cat2", "name", TRACE_EVENT_SCOPE_THREAD);
1141 EndTraceAndFlush();
1142 DropTracedMetadataRecords();
1143 EXPECT_TRUE(trace_parsed_.empty());
1144
1145 // Include existent category -> only events of that category
1146 Clear();
1147 included_categories.clear();
1148 TraceLog::GetInstance()->SetEnabled(TraceConfig("test_inc", ""),
1149 TraceLog::RECORDING_MODE);
1150 TRACE_EVENT_INSTANT0("test_inc", "name", TRACE_EVENT_SCOPE_THREAD);
1151 TRACE_EVENT_INSTANT0("test_inc2", "name", TRACE_EVENT_SCOPE_THREAD);
1152 EndTraceAndFlush();
1153 DropTracedMetadataRecords();
1154 EXPECT_TRUE(FindMatchingValue("cat", "test_inc"));
1155 EXPECT_FALSE(FindNonMatchingValue("cat", "test_inc"));
1156
1157 // Include existent wildcard -> all categories matching wildcard
1158 Clear();
1159 included_categories.clear();
1160 TraceLog::GetInstance()->SetEnabled(TraceConfig("test_inc_wildcard_*", ""),
1161 TraceLog::RECORDING_MODE);
1162 TRACE_EVENT_INSTANT0("test_inc_wildcard_abc", "included",
1163 TRACE_EVENT_SCOPE_THREAD);
1164 TRACE_EVENT_INSTANT0("test_inc_wildcard_", "included",
1165 TRACE_EVENT_SCOPE_THREAD);
1166 TRACE_EVENT_INSTANT0("cat1", "not_inc", TRACE_EVENT_SCOPE_THREAD);
1167 TRACE_EVENT_INSTANT0("cat2", "not_inc", TRACE_EVENT_SCOPE_THREAD);
1168 TRACE_EVENT_INSTANT0("test_inc_wildcard_category,test_other_category",
1169 "included", TRACE_EVENT_SCOPE_THREAD);
1170 TRACE_EVENT_INSTANT0("test_non_included_category,test_inc_wildcard_category",
1171 "included", TRACE_EVENT_SCOPE_THREAD);
1172 EndTraceAndFlush();
1173 EXPECT_TRUE(FindMatchingValue("cat", "test_inc_wildcard_abc"));
1174 EXPECT_TRUE(FindMatchingValue("cat", "test_inc_wildcard_"));
1175 EXPECT_FALSE(FindMatchingValue("name", "not_inc"));
1176 EXPECT_TRUE(FindMatchingValue(
1177 "cat", "test_inc_wildcard_category,test_other_category"));
1178 EXPECT_TRUE(FindMatchingValue(
1179 "cat", "test_non_included_category,test_inc_wildcard_category"));
1180
1181 included_categories.clear();
1182
1183 // Exclude nonexistent category -> all events
1184 Clear();
1185 TraceLog::GetInstance()->SetEnabled(TraceConfig("-not_found823564786", ""),
1186 TraceLog::RECORDING_MODE);
1187 TRACE_EVENT_INSTANT0("cat1", "name", TRACE_EVENT_SCOPE_THREAD);
1188 TRACE_EVENT_INSTANT0("cat2", "name", TRACE_EVENT_SCOPE_THREAD);
1189 TRACE_EVENT_INSTANT0("category1,category2", "name", TRACE_EVENT_SCOPE_THREAD);
1190 EndTraceAndFlush();
1191 EXPECT_TRUE(FindMatchingValue("cat", "cat1"));
1192 EXPECT_TRUE(FindMatchingValue("cat", "cat2"));
1193 EXPECT_TRUE(FindMatchingValue("cat", "category1,category2"));
1194
1195 // Exclude existent category -> only events of other categories
1196 Clear();
1197 TraceLog::GetInstance()->SetEnabled(TraceConfig("-test_inc", ""),
1198 TraceLog::RECORDING_MODE);
1199 TRACE_EVENT_INSTANT0("test_inc", "name", TRACE_EVENT_SCOPE_THREAD);
1200 TRACE_EVENT_INSTANT0("test_inc2", "name", TRACE_EVENT_SCOPE_THREAD);
1201 TRACE_EVENT_INSTANT0("test_inc2,test_inc", "name", TRACE_EVENT_SCOPE_THREAD);
1202 TRACE_EVENT_INSTANT0("test_inc,test_inc2", "name", TRACE_EVENT_SCOPE_THREAD);
1203 EndTraceAndFlush();
1204 EXPECT_TRUE(FindMatchingValue("cat", "test_inc2"));
1205 EXPECT_FALSE(FindMatchingValue("cat", "test_inc"));
1206 EXPECT_TRUE(FindMatchingValue("cat", "test_inc2,test_inc"));
1207 EXPECT_TRUE(FindMatchingValue("cat", "test_inc,test_inc2"));
1208
1209 // Exclude existent wildcard -> all categories not matching wildcard
1210 Clear();
1211 TraceLog::GetInstance()->SetEnabled(TraceConfig("-test_inc_wildcard_*", ""),
1212 TraceLog::RECORDING_MODE);
1213 TRACE_EVENT_INSTANT0("test_inc_wildcard_abc", "not_inc",
1214 TRACE_EVENT_SCOPE_THREAD);
1215 TRACE_EVENT_INSTANT0("test_inc_wildcard_", "not_inc",
1216 TRACE_EVENT_SCOPE_THREAD);
1217 TRACE_EVENT_INSTANT0("cat1", "included", TRACE_EVENT_SCOPE_THREAD);
1218 TRACE_EVENT_INSTANT0("cat2", "included", TRACE_EVENT_SCOPE_THREAD);
1219 EndTraceAndFlush();
1220 EXPECT_TRUE(FindMatchingValue("cat", "cat1"));
1221 EXPECT_TRUE(FindMatchingValue("cat", "cat2"));
1222 EXPECT_FALSE(FindMatchingValue("name", "not_inc"));
1223 }
1224
1225
1226 // Test ASYNC_BEGIN/END events
TEST_F(TraceEventTestFixture,AsyncBeginEndEvents)1227 TEST_F(TraceEventTestFixture, AsyncBeginEndEvents) {
1228 BeginTrace();
1229
1230 uint64_t id = 0xfeedbeeffeedbeefull;
1231 TRACE_EVENT_ASYNC_BEGIN0("cat", "name1", id);
1232 TRACE_EVENT_ASYNC_STEP_INTO0("cat", "name1", id, "step1");
1233 TRACE_EVENT_ASYNC_END0("cat", "name1", id);
1234 TRACE_EVENT_BEGIN0("cat", "name2");
1235 TRACE_EVENT_ASYNC_BEGIN0("cat", "name3", 0);
1236 TRACE_EVENT_ASYNC_STEP_PAST0("cat", "name3", 0, "step2");
1237
1238 EndTraceAndFlush();
1239
1240 EXPECT_TRUE(FindNamePhase("name1", "S"));
1241 EXPECT_TRUE(FindNamePhase("name1", "T"));
1242 EXPECT_TRUE(FindNamePhase("name1", "F"));
1243
1244 std::string id_str;
1245 StringAppendF(&id_str, "0x%" PRIx64, id);
1246
1247 EXPECT_TRUE(FindNamePhaseKeyValue("name1", "S", "id", id_str.c_str()));
1248 EXPECT_TRUE(FindNamePhaseKeyValue("name1", "T", "id", id_str.c_str()));
1249 EXPECT_TRUE(FindNamePhaseKeyValue("name1", "F", "id", id_str.c_str()));
1250 EXPECT_TRUE(FindNamePhaseKeyValue("name3", "S", "id", "0x0"));
1251 EXPECT_TRUE(FindNamePhaseKeyValue("name3", "p", "id", "0x0"));
1252
1253 // BEGIN events should not have id
1254 EXPECT_FALSE(FindNamePhaseKeyValue("name2", "B", "id", "0"));
1255 }
1256
1257 // Test ASYNC_BEGIN/END events
TEST_F(TraceEventTestFixture,AsyncBeginEndPointerNotMangled)1258 TEST_F(TraceEventTestFixture, AsyncBeginEndPointerNotMangled) {
1259 void* ptr = this;
1260
1261 TraceLog::GetInstance()->SetProcessID(100);
1262 BeginTrace();
1263 TRACE_EVENT_ASYNC_BEGIN0("cat", "name1", ptr);
1264 TRACE_EVENT_ASYNC_BEGIN0("cat", "name2", ptr);
1265 EndTraceAndFlush();
1266
1267 TraceLog::GetInstance()->SetProcessID(200);
1268 BeginTrace();
1269 TRACE_EVENT_ASYNC_BEGIN0("cat", "name1", ptr);
1270 TRACE_EVENT_ASYNC_END0("cat", "name1", ptr);
1271 EndTraceAndFlush();
1272
1273 const Value::Dict* async_begin = FindNamePhase("name1", "S");
1274 const Value::Dict* async_begin2 = FindNamePhase("name2", "S");
1275 const Value::Dict* async_end = FindNamePhase("name1", "F");
1276 EXPECT_TRUE(async_begin);
1277 EXPECT_TRUE(async_begin2);
1278 EXPECT_TRUE(async_end);
1279
1280 std::string async_begin_id_str =
1281 *async_begin->FindStringByDottedPath("id2.local");
1282 std::string async_begin2_id_str =
1283 *async_begin2->FindStringByDottedPath("id2.local");
1284 std::string async_end_id_str =
1285 *async_end->FindStringByDottedPath("id2.local");
1286
1287 // Since all ids are process-local and not mangled, they should be equal.
1288 EXPECT_STREQ(async_begin_id_str.c_str(), async_begin2_id_str.c_str());
1289 EXPECT_STREQ(async_begin_id_str.c_str(), async_end_id_str.c_str());
1290 }
1291
1292 // Test that static strings are not copied.
TEST_F(TraceEventTestFixture,StaticStringVsString)1293 TEST_F(TraceEventTestFixture, StaticStringVsString) {
1294 TraceLog* tracer = TraceLog::GetInstance();
1295 // Make sure old events are flushed:
1296 EXPECT_EQ(0u, tracer->GetStatus().event_count);
1297 const unsigned char* category_group_enabled =
1298 TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED("base");
1299
1300 {
1301 BeginTrace();
1302 // Test that string arguments are copied.
1303 [[maybe_unused]] TraceEventHandle handle1 =
1304 trace_event_internal::AddTraceEvent(
1305 TRACE_EVENT_PHASE_INSTANT, category_group_enabled, "name1",
1306 trace_event_internal::kGlobalScope, trace_event_internal::kNoId, 0,
1307 trace_event_internal::kNoId, "arg1", std::string("argval"), "arg2",
1308 std::string("argval"));
1309 // Test that static TRACE_STR_COPY string arguments are copied.
1310 [[maybe_unused]] TraceEventHandle handle2 =
1311 trace_event_internal::AddTraceEvent(
1312 TRACE_EVENT_PHASE_INSTANT, category_group_enabled, "name2",
1313 trace_event_internal::kGlobalScope, trace_event_internal::kNoId, 0,
1314 trace_event_internal::kNoId, "arg1", TRACE_STR_COPY("argval"),
1315 "arg2", TRACE_STR_COPY("argval"));
1316 #if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
1317 EXPECT_GT(tracer->GetStatus().event_count, 1u);
1318 const TraceEvent* event1 = tracer->GetEventByHandle(handle1);
1319 const TraceEvent* event2 = tracer->GetEventByHandle(handle2);
1320 ASSERT_TRUE(event1);
1321 ASSERT_TRUE(event2);
1322 EXPECT_STREQ("name1", event1->name());
1323 EXPECT_STREQ("name2", event2->name());
1324 EXPECT_FALSE(event1->parameter_copy_storage().empty());
1325 EXPECT_FALSE(event2->parameter_copy_storage().empty());
1326 EXPECT_GT(event1->parameter_copy_storage().size(), 0u);
1327 EXPECT_GT(event2->parameter_copy_storage().size(), 0u);
1328 #endif // !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
1329 EndTraceAndFlush();
1330 }
1331
1332 {
1333 BeginTrace();
1334 // Test that static literal string arguments are not copied.
1335 [[maybe_unused]] TraceEventHandle handle1 =
1336 trace_event_internal::AddTraceEvent(
1337 TRACE_EVENT_PHASE_INSTANT, category_group_enabled, "name1",
1338 trace_event_internal::kGlobalScope, trace_event_internal::kNoId, 0,
1339 trace_event_internal::kNoId, "arg1", "argval", "arg2", "argval");
1340 #if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
1341 EXPECT_GT(tracer->GetStatus().event_count, 1u);
1342 const TraceEvent* event1 = tracer->GetEventByHandle(handle1);
1343 ASSERT_TRUE(event1);
1344 EXPECT_STREQ("name1", event1->name());
1345 EXPECT_TRUE(event1->parameter_copy_storage().empty());
1346 #endif
1347 EndTraceAndFlush();
1348 }
1349 }
1350
1351 // Test that data sent from other threads is gathered
TEST_F(TraceEventTestFixture,DataCapturedOnThread)1352 TEST_F(TraceEventTestFixture, DataCapturedOnThread) {
1353 BeginTrace();
1354
1355 Thread thread("1");
1356 WaitableEvent task_complete_event(WaitableEvent::ResetPolicy::AUTOMATIC,
1357 WaitableEvent::InitialState::NOT_SIGNALED);
1358 thread.Start();
1359
1360 thread.task_runner()->PostTask(
1361 FROM_HERE,
1362 base::BindOnce(&TraceWithAllMacroVariants, &task_complete_event));
1363 task_complete_event.Wait();
1364 thread.Stop();
1365
1366 EndTraceAndFlush();
1367 ValidateAllTraceMacrosCreatedData(trace_parsed_);
1368 }
1369
1370 // Test that data sent from multiple threads is gathered
TEST_F(TraceEventTestFixture,DataCapturedManyThreads)1371 TEST_F(TraceEventTestFixture, DataCapturedManyThreads) {
1372 BeginTrace();
1373
1374 const int num_threads = 4;
1375 const int num_events = 4000;
1376 Thread* threads[num_threads];
1377 WaitableEvent* task_complete_events[num_threads];
1378 for (int i = 0; i < num_threads; i++) {
1379 threads[i] = new Thread(StringPrintf("Thread %d", i));
1380 task_complete_events[i] =
1381 new WaitableEvent(WaitableEvent::ResetPolicy::AUTOMATIC,
1382 WaitableEvent::InitialState::NOT_SIGNALED);
1383 threads[i]->Start();
1384 threads[i]->task_runner()->PostTask(
1385 FROM_HERE, base::BindOnce(&TraceManyInstantEvents, i, num_events,
1386 task_complete_events[i]));
1387 }
1388
1389 for (auto* event : task_complete_events) {
1390 event->Wait();
1391 }
1392
1393 // Let half of the threads end before flush.
1394 for (int i = 0; i < num_threads / 2; i++) {
1395 threads[i]->Stop();
1396 delete threads[i];
1397 delete task_complete_events[i];
1398 }
1399
1400 EndTraceAndFlushInThreadWithMessageLoop();
1401 ValidateInstantEventPresentOnEveryThread(trace_parsed_,
1402 num_threads, num_events);
1403
1404 // Let the other half of the threads end after flush.
1405 for (int i = num_threads / 2; i < num_threads; i++) {
1406 threads[i]->Stop();
1407 delete threads[i];
1408 delete task_complete_events[i];
1409 }
1410 }
1411
1412 // Test that thread and process names show up in the trace.
1413 // In SDK build, thread names are not tracked inside //base. Instead, there's
1414 // a special TrackNameRecorder component in //services that is tested in
1415 // services_unittests.
1416 // TODO(khokhlov): Verify if we need thread name support for unit-test tracing.
1417 #if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
TEST_F(TraceEventTestFixture,ThreadNames)1418 TEST_F(TraceEventTestFixture, ThreadNames) {
1419 // Create threads before we enable tracing to make sure
1420 // that tracelog still captures them.
1421 const int kNumThreads = 4;
1422 const int kNumEvents = 10;
1423 Thread* threads[kNumThreads];
1424 PlatformThreadId thread_ids[kNumThreads];
1425 for (int i = 0; i < kNumThreads; i++)
1426 threads[i] = new Thread(StringPrintf("Thread %d", i));
1427
1428 // Enable tracing.
1429 BeginTrace();
1430
1431 // Now run some trace code on these threads.
1432 WaitableEvent* task_complete_events[kNumThreads];
1433 for (int i = 0; i < kNumThreads; i++) {
1434 task_complete_events[i] =
1435 new WaitableEvent(WaitableEvent::ResetPolicy::AUTOMATIC,
1436 WaitableEvent::InitialState::NOT_SIGNALED);
1437 threads[i]->Start();
1438 thread_ids[i] = threads[i]->GetThreadId();
1439 threads[i]->task_runner()->PostTask(
1440 FROM_HERE, base::BindOnce(&TraceManyInstantEvents, i, kNumEvents,
1441 task_complete_events[i]));
1442 }
1443 for (auto* event : task_complete_events) {
1444 event->Wait();
1445 }
1446
1447 // Shut things down.
1448 for (int i = 0; i < kNumThreads; i++) {
1449 threads[i]->Stop();
1450 delete threads[i];
1451 delete task_complete_events[i];
1452 }
1453
1454 EndTraceAndFlush();
1455
1456 // Make sure we get thread name metadata.
1457 // Note, the test suite may have created a ton of threads.
1458 // So, we'll have thread names for threads we didn't create.
1459 std::vector<const Value::Dict*> items =
1460 FindTraceEntries(trace_parsed_, "thread_name");
1461 for (const Value::Dict* item : items) {
1462 ASSERT_TRUE(item);
1463
1464 absl::optional<int> maybe_tid = item->FindInt("tid");
1465 EXPECT_TRUE(maybe_tid.has_value());
1466
1467 // See if this thread name is one of the threads we just created
1468 for (int j = 0; j < kNumThreads; j++) {
1469 if (static_cast<int>(thread_ids[j]) != maybe_tid.value())
1470 continue;
1471
1472 EXPECT_EQ(*item->FindString("ph"), "M");
1473 EXPECT_EQ(*item->FindInt("pid"),
1474 static_cast<int>(base::GetCurrentProcId()));
1475
1476 // If the thread name changes or the tid gets reused, the name will be
1477 // a comma-separated list of thread names, so look for a substring.
1478 std::string expected_name = StringPrintf("Thread %d", j);
1479 const std::string* name = item->FindStringByDottedPath("args.name");
1480 EXPECT_TRUE(name && name->find(expected_name) != std::string::npos);
1481 }
1482 }
1483 }
1484 #endif // !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
1485
1486 // Test that the disabled trace categories are included/excluded from the
1487 // trace output correctly.
TEST_F(TraceEventTestFixture,DisabledCategories)1488 TEST_F(TraceEventTestFixture, DisabledCategories) {
1489 BeginTrace();
1490 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("cc"), "first",
1491 TRACE_EVENT_SCOPE_THREAD);
1492 TRACE_EVENT_INSTANT0("test_included", "first", TRACE_EVENT_SCOPE_THREAD);
1493 EndTraceAndFlush();
1494 {
1495 const Value::Dict* item = nullptr;
1496 Value::List& trace_parsed = trace_parsed_;
1497 EXPECT_NOT_FIND_("disabled-by-default-cc");
1498 EXPECT_FIND_("test_included");
1499 }
1500 Clear();
1501
1502 BeginSpecificTrace("disabled-by-default-cc");
1503 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("cc"), "second",
1504 TRACE_EVENT_SCOPE_THREAD);
1505 TRACE_EVENT_INSTANT0("test_other_included", "second",
1506 TRACE_EVENT_SCOPE_THREAD);
1507 EndTraceAndFlush();
1508
1509 {
1510 const Value::Dict* item = nullptr;
1511 Value::List& trace_parsed = trace_parsed_;
1512 EXPECT_FIND_("disabled-by-default-cc");
1513 EXPECT_FIND_("test_other_included");
1514 }
1515
1516 Clear();
1517
1518 BeginSpecificTrace("test_other_included");
1519 TRACE_EVENT_INSTANT0("test_other_included," TRACE_DISABLED_BY_DEFAULT("cc"),
1520 "test_first", TRACE_EVENT_SCOPE_THREAD);
1521 TRACE_EVENT_INSTANT0(
1522 "test," TRACE_DISABLED_BY_DEFAULT("cc") ",test_other_included", "second",
1523 TRACE_EVENT_SCOPE_THREAD);
1524 EndTraceAndFlush();
1525
1526 {
1527 const Value::Dict* item = nullptr;
1528 Value::List& trace_parsed = trace_parsed_;
1529 EXPECT_FIND_("test,disabled-by-default-cc,test_other_included");
1530 EXPECT_FIND_("test_other_included,disabled-by-default-cc");
1531 }
1532 }
1533
1534 // Perfetto always traces all macro arguments immediately.
1535 #if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
TEST_F(TraceEventTestFixture,NormallyNoDeepCopy)1536 TEST_F(TraceEventTestFixture, NormallyNoDeepCopy) {
1537 // Test that the TRACE_EVENT macros do not deep-copy their string. If they
1538 // do so it may indicate a performance regression, but more-over it would
1539 // make the DEEP_COPY overloads redundant.
1540 std::string name_string("event name");
1541
1542 BeginTrace();
1543 TRACE_EVENT_INSTANT0("category", name_string.c_str(),
1544 TRACE_EVENT_SCOPE_THREAD);
1545
1546 // Modify the string in place (a wholesale reassignment may leave the old
1547 // string intact on the heap).
1548 name_string[0] = '@';
1549
1550 EndTraceAndFlush();
1551
1552 EXPECT_FALSE(FindTraceEntry(trace_parsed_, "event name"));
1553 EXPECT_TRUE(FindTraceEntry(trace_parsed_, name_string.c_str()));
1554 }
1555 #endif // !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
1556
TEST_F(TraceEventTestFixture,DeepCopy)1557 TEST_F(TraceEventTestFixture, DeepCopy) {
1558 static const char kOriginalName[] = "name1";
1559 std::string name(kOriginalName);
1560 std::string arg1("arg1");
1561 std::string arg2("arg2");
1562 std::string val("val");
1563
1564 BeginTrace();
1565 TRACE_EVENT_COPY_BEGIN2("category", name.c_str(), arg1.c_str(), 5,
1566 arg2.c_str(), val);
1567 TRACE_EVENT_COPY_BEGIN2("category", name.c_str(), arg1.c_str(), 5,
1568 arg2.c_str(), val);
1569
1570 // As per NormallyNoDeepCopy, modify the strings in place.
1571 name[0] = arg1[0] = arg2[0] = val[0] = '@';
1572
1573 EndTraceAndFlush();
1574
1575 EXPECT_FALSE(FindTraceEntry(trace_parsed_, name.c_str()));
1576
1577 const Value::Dict* entry = FindTraceEntry(trace_parsed_, kOriginalName);
1578 ASSERT_TRUE(entry);
1579
1580 EXPECT_FALSE(entry->FindIntByDottedPath("args.@rg1"));
1581
1582 ASSERT_TRUE(entry->FindIntByDottedPath("args.arg1"));
1583 EXPECT_EQ(*entry->FindIntByDottedPath("args.arg1"), 5);
1584
1585 ASSERT_TRUE(entry->FindStringByDottedPath("args.arg2"));
1586 EXPECT_EQ(*entry->FindStringByDottedPath("args.arg2"), "val");
1587 }
1588
1589 // Test that TraceResultBuffer outputs the correct result whether it is added
1590 // in chunks or added all at once.
TEST_F(TraceEventTestFixture,TraceResultBuffer)1591 TEST_F(TraceEventTestFixture, TraceResultBuffer) {
1592 Clear();
1593
1594 trace_buffer_.Start();
1595 trace_buffer_.AddFragment("bla1");
1596 trace_buffer_.AddFragment("bla2");
1597 trace_buffer_.AddFragment("bla3,bla4");
1598 trace_buffer_.Finish();
1599 EXPECT_STREQ(json_output_.json_output.c_str(), "[bla1,bla2,bla3,bla4]");
1600
1601 Clear();
1602
1603 trace_buffer_.Start();
1604 trace_buffer_.AddFragment("bla1,bla2,bla3,bla4");
1605 trace_buffer_.Finish();
1606 EXPECT_STREQ(json_output_.json_output.c_str(), "[bla1,bla2,bla3,bla4]");
1607 }
1608
1609 // Test that trace_event parameters are not evaluated if the tracing
1610 // system is disabled.
TEST_F(TraceEventTestFixture,TracingIsLazy)1611 TEST_F(TraceEventTestFixture, TracingIsLazy) {
1612 BeginTrace();
1613
1614 int a = 0;
1615 TRACE_EVENT_INSTANT1("category", "test", TRACE_EVENT_SCOPE_THREAD, "a", a++);
1616 EXPECT_EQ(1, a);
1617
1618 TraceLog::GetInstance()->SetDisabled();
1619
1620 TRACE_EVENT_INSTANT1("category", "test", TRACE_EVENT_SCOPE_THREAD, "a", a++);
1621 EXPECT_EQ(1, a);
1622
1623 EndTraceAndFlush();
1624 }
1625
TEST_F(TraceEventTestFixture,TraceEnableDisable)1626 TEST_F(TraceEventTestFixture, TraceEnableDisable) {
1627 TraceLog* trace_log = TraceLog::GetInstance();
1628 TraceConfig tc_inc_all("*", "");
1629 trace_log->SetEnabled(tc_inc_all, TraceLog::RECORDING_MODE);
1630 EXPECT_TRUE(trace_log->IsEnabled());
1631 trace_log->SetDisabled();
1632 EXPECT_FALSE(trace_log->IsEnabled());
1633
1634 trace_log->SetEnabled(tc_inc_all, TraceLog::RECORDING_MODE);
1635 EXPECT_TRUE(trace_log->IsEnabled());
1636 // Nested enable isn't supported by Perfetto.
1637 #if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
1638 trace_log->SetEnabled(TraceConfig(), TraceLog::RECORDING_MODE);
1639 EXPECT_TRUE(trace_log->IsEnabled());
1640 trace_log->SetDisabled();
1641 EXPECT_FALSE(trace_log->IsEnabled());
1642 #endif // !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
1643 trace_log->SetDisabled();
1644 EXPECT_FALSE(trace_log->IsEnabled());
1645 }
1646
1647 // Nested enable isn't supported by Perfetto.
1648 #if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
TEST_F(TraceEventTestFixture,TraceCategoriesAfterNestedEnable)1649 TEST_F(TraceEventTestFixture, TraceCategoriesAfterNestedEnable) {
1650 TraceLog* trace_log = TraceLog::GetInstance();
1651 trace_log->SetEnabled(TraceConfig("foo,bar", ""), TraceLog::RECORDING_MODE);
1652 EXPECT_TRUE(*trace_log->GetCategoryGroupEnabled("foo"));
1653 EXPECT_TRUE(*trace_log->GetCategoryGroupEnabled("bar"));
1654 EXPECT_FALSE(*trace_log->GetCategoryGroupEnabled("baz"));
1655 trace_log->SetEnabled(TraceConfig("foo2", ""), TraceLog::RECORDING_MODE);
1656 EXPECT_TRUE(*trace_log->GetCategoryGroupEnabled("foo2"));
1657 EXPECT_FALSE(*trace_log->GetCategoryGroupEnabled("baz"));
1658 // The "" becomes the default category set when applied.
1659 trace_log->SetEnabled(TraceConfig(), TraceLog::RECORDING_MODE);
1660 EXPECT_TRUE(*trace_log->GetCategoryGroupEnabled("foo"));
1661 EXPECT_TRUE(*trace_log->GetCategoryGroupEnabled("baz"));
1662 EXPECT_STREQ(
1663 "",
1664 trace_log->GetCurrentTraceConfig().ToCategoryFilterString().c_str());
1665 trace_log->SetDisabled();
1666 trace_log->SetDisabled();
1667 trace_log->SetDisabled();
1668 EXPECT_FALSE(*trace_log->GetCategoryGroupEnabled("foo"));
1669 EXPECT_FALSE(*trace_log->GetCategoryGroupEnabled("baz"));
1670
1671 trace_log->SetEnabled(TraceConfig("-foo,-bar", ""), TraceLog::RECORDING_MODE);
1672 EXPECT_FALSE(*trace_log->GetCategoryGroupEnabled("foo"));
1673 EXPECT_TRUE(*trace_log->GetCategoryGroupEnabled("baz"));
1674 trace_log->SetEnabled(TraceConfig("moo", ""), TraceLog::RECORDING_MODE);
1675 EXPECT_TRUE(*trace_log->GetCategoryGroupEnabled("baz"));
1676 EXPECT_TRUE(*trace_log->GetCategoryGroupEnabled("moo"));
1677 EXPECT_FALSE(*trace_log->GetCategoryGroupEnabled("foo"));
1678 EXPECT_STREQ(
1679 "-foo,-bar",
1680 trace_log->GetCurrentTraceConfig().ToCategoryFilterString().c_str());
1681 trace_log->SetDisabled();
1682 trace_log->SetDisabled();
1683
1684 // Make sure disabled categories aren't cleared if we set in the second.
1685 trace_log->SetEnabled(TraceConfig("disabled-by-default-cc,foo", ""),
1686 TraceLog::RECORDING_MODE);
1687 EXPECT_FALSE(*trace_log->GetCategoryGroupEnabled("bar"));
1688 trace_log->SetEnabled(TraceConfig("disabled-by-default-gpu", ""),
1689 TraceLog::RECORDING_MODE);
1690 EXPECT_TRUE(*trace_log->GetCategoryGroupEnabled("disabled-by-default-cc"));
1691 EXPECT_TRUE(*trace_log->GetCategoryGroupEnabled("disabled-by-default-gpu"));
1692 EXPECT_TRUE(*trace_log->GetCategoryGroupEnabled("bar"));
1693 EXPECT_STREQ(
1694 "disabled-by-default-cc,disabled-by-default-gpu",
1695 trace_log->GetCurrentTraceConfig().ToCategoryFilterString().c_str());
1696 trace_log->SetDisabled();
1697 trace_log->SetDisabled();
1698 }
1699 #endif // !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
1700
TEST_F(TraceEventTestFixture,TraceWithDefaultCategoryFilters)1701 TEST_F(TraceEventTestFixture, TraceWithDefaultCategoryFilters) {
1702 TraceLog* trace_log = TraceLog::GetInstance();
1703
1704 trace_log->SetEnabled(TraceConfig(), TraceLog::RECORDING_MODE);
1705 CheckTraceDefaultCategoryFilters(*trace_log);
1706 trace_log->SetDisabled();
1707
1708 trace_log->SetEnabled(TraceConfig("", ""), TraceLog::RECORDING_MODE);
1709 CheckTraceDefaultCategoryFilters(*trace_log);
1710 trace_log->SetDisabled();
1711
1712 trace_log->SetEnabled(TraceConfig("*", ""), TraceLog::RECORDING_MODE);
1713 CheckTraceDefaultCategoryFilters(*trace_log);
1714 trace_log->SetDisabled();
1715
1716 trace_log->SetEnabled(TraceConfig(""), TraceLog::RECORDING_MODE);
1717 CheckTraceDefaultCategoryFilters(*trace_log);
1718 trace_log->SetDisabled();
1719 }
1720
TEST_F(TraceEventTestFixture,TraceWithDisabledByDefaultCategoryFilters)1721 TEST_F(TraceEventTestFixture, TraceWithDisabledByDefaultCategoryFilters) {
1722 TraceLog* trace_log = TraceLog::GetInstance();
1723
1724 trace_log->SetEnabled(TraceConfig("foo,disabled-by-default-foo", ""),
1725 TraceLog::RECORDING_MODE);
1726 EXPECT_TRUE(IsCategoryEnabled("foo"));
1727 EXPECT_TRUE(IsCategoryEnabled("disabled-by-default-foo"));
1728 EXPECT_FALSE(IsCategoryEnabled("bar"));
1729 EXPECT_FALSE(IsCategoryEnabled("disabled-by-default-bar"));
1730 trace_log->SetDisabled();
1731
1732 // Enabling only the disabled-by-default-* category means the default ones
1733 // are also enabled.
1734 trace_log->SetEnabled(TraceConfig("disabled-by-default-foo", ""),
1735 TraceLog::RECORDING_MODE);
1736 EXPECT_TRUE(IsCategoryEnabled("disabled-by-default-foo"));
1737 EXPECT_TRUE(IsCategoryEnabled("foo"));
1738 EXPECT_TRUE(IsCategoryEnabled("bar"));
1739 EXPECT_FALSE(IsCategoryEnabled("disabled-by-default-bar"));
1740 trace_log->SetDisabled();
1741 }
1742
1743 class MyData : public ConvertableToTraceFormat {
1744 public:
1745 MyData() = default;
1746 MyData(const MyData&) = delete;
1747 MyData& operator=(const MyData&) = delete;
1748 ~MyData() override = default;
1749
AppendAsTraceFormat(std::string * out) const1750 void AppendAsTraceFormat(std::string* out) const override {
1751 out->append("{\"foo\":1}");
1752 }
1753 };
1754
TEST_F(TraceEventTestFixture,ConvertableTypes)1755 TEST_F(TraceEventTestFixture, ConvertableTypes) {
1756 TraceLog::GetInstance()->SetEnabled(TraceConfig(kRecordAllCategoryFilter, ""),
1757 TraceLog::RECORDING_MODE);
1758
1759 {
1760 std::unique_ptr<ConvertableToTraceFormat> data(new MyData());
1761 std::unique_ptr<ConvertableToTraceFormat> data1(new MyData());
1762 std::unique_ptr<ConvertableToTraceFormat> data2(new MyData());
1763 TRACE_EVENT1("foo", "bar", "data", std::move(data));
1764 TRACE_EVENT2("foo", "baz", "data1", std::move(data1), "data2",
1765 std::move(data2));
1766 }
1767
1768 // Check that std::unique_ptr<DerivedClassOfConvertable> are properly treated
1769 // as convertable and not accidentally casted to bool.
1770 {
1771 std::unique_ptr<MyData> convertData1(new MyData());
1772 std::unique_ptr<MyData> convertData2(new MyData());
1773 std::unique_ptr<MyData> convertData3(new MyData());
1774 std::unique_ptr<MyData> convertData4(new MyData());
1775 TRACE_EVENT2("foo", "string_first", "str", "string value 1", "convert",
1776 std::move(convertData1));
1777 TRACE_EVENT2("foo", "string_second", "convert", std::move(convertData2),
1778 "str", "string value 2");
1779 TRACE_EVENT2("foo", "both_conv", "convert1", std::move(convertData3),
1780 "convert2", std::move(convertData4));
1781 }
1782 EndTraceAndFlush();
1783
1784 // One arg version.
1785 const Value::Dict* dict = FindNamePhase("bar", "X");
1786 ASSERT_TRUE(dict);
1787
1788 const Value::Dict* args_dict = dict->FindDict("args");
1789 ASSERT_TRUE(args_dict);
1790
1791 const Value::Dict* convertable_dict = args_dict->FindDict("data");
1792 ASSERT_TRUE(convertable_dict);
1793
1794 EXPECT_EQ(*convertable_dict->FindInt("foo"), 1);
1795
1796 // Two arg version.
1797 dict = FindNamePhase("baz", "X");
1798 ASSERT_TRUE(dict);
1799
1800 args_dict = dict->FindDict("args");
1801 ASSERT_TRUE(args_dict);
1802
1803 convertable_dict = args_dict->FindDict("data1");
1804 ASSERT_TRUE(convertable_dict);
1805
1806 convertable_dict = args_dict->FindDict("data2");
1807 ASSERT_TRUE(convertable_dict);
1808
1809 // Convertable with other types.
1810 dict = FindNamePhase("string_first", "X");
1811 ASSERT_TRUE(dict);
1812
1813 args_dict = dict->FindDict("args");
1814 ASSERT_TRUE(args_dict);
1815
1816 EXPECT_EQ(*args_dict->FindString("str"), "string value 1");
1817
1818 convertable_dict = args_dict->FindDict("convert");
1819 ASSERT_TRUE(convertable_dict);
1820
1821 EXPECT_EQ(*convertable_dict->FindInt("foo"), 1);
1822
1823 dict = FindNamePhase("string_second", "X");
1824 ASSERT_TRUE(dict);
1825
1826 args_dict = dict->FindDict("args");
1827 ASSERT_TRUE(args_dict);
1828
1829 EXPECT_EQ(*args_dict->FindString("str"), "string value 2");
1830
1831 convertable_dict = args_dict->FindDict("convert");
1832 ASSERT_TRUE(convertable_dict);
1833
1834 EXPECT_EQ(*convertable_dict->FindInt("foo"), 1);
1835
1836 dict = FindNamePhase("both_conv", "X");
1837 ASSERT_TRUE(dict);
1838
1839 args_dict = dict->FindDict("args");
1840 ASSERT_TRUE(args_dict);
1841
1842 convertable_dict = args_dict->FindDict("convert1");
1843 ASSERT_TRUE(convertable_dict);
1844 convertable_dict = args_dict->FindDict("convert2");
1845 ASSERT_TRUE(convertable_dict);
1846 }
1847
TEST_F(TraceEventTestFixture,PrimitiveArgs)1848 TEST_F(TraceEventTestFixture, PrimitiveArgs) {
1849 TraceLog::GetInstance()->SetEnabled(TraceConfig(kRecordAllCategoryFilter, ""),
1850 TraceLog::RECORDING_MODE);
1851
1852 {
1853 TRACE_EVENT1("foo", "event1", "int_one", 1);
1854 TRACE_EVENT1("foo", "event2", "int_neg_ten", -10);
1855 TRACE_EVENT1("foo", "event3", "float_one", 1.0f);
1856 TRACE_EVENT1("foo", "event4", "float_half", .5f);
1857 TRACE_EVENT1("foo", "event5", "float_neghalf", -.5f);
1858 TRACE_EVENT1("foo", "event6", "float_infinity",
1859 std::numeric_limits<float>::infinity());
1860 TRACE_EVENT1("foo", "event6b", "float_neg_infinity",
1861 -std::numeric_limits<float>::infinity());
1862 TRACE_EVENT1("foo", "event7", "double_nan",
1863 std::numeric_limits<double>::quiet_NaN());
1864 void* p = nullptr;
1865 TRACE_EVENT1("foo", "event8", "pointer_null", p);
1866 p = reinterpret_cast<void*>(0xbadf00d);
1867 TRACE_EVENT1("foo", "event9", "pointer_badf00d", p);
1868 TRACE_EVENT1("foo", "event10", "bool_true", true);
1869 TRACE_EVENT1("foo", "event11", "bool_false", false);
1870 TRACE_EVENT1("foo", "event12", "time_null", base::Time());
1871 TRACE_EVENT1("foo", "event13", "time_one",
1872 base::Time::FromInternalValue(1));
1873 TRACE_EVENT1("foo", "event14", "timeticks_null", base::TimeTicks());
1874 TRACE_EVENT1("foo", "event15", "timeticks_one",
1875 base::TimeTicks::FromInternalValue(1));
1876 }
1877 EndTraceAndFlush();
1878
1879 const Value::Dict* args_dict = nullptr;
1880 const Value::Dict* dict = nullptr;
1881 std::string str_value;
1882
1883 dict = FindNamePhase("event1", "X");
1884 ASSERT_TRUE(dict);
1885 args_dict = dict->FindDict("args");
1886 ASSERT_TRUE(args_dict);
1887 EXPECT_EQ(*args_dict->FindInt("int_one"), 1);
1888
1889 dict = FindNamePhase("event2", "X");
1890 ASSERT_TRUE(dict);
1891 args_dict = dict->FindDict("args");
1892 ASSERT_TRUE(args_dict);
1893 EXPECT_EQ(*args_dict->FindInt("int_neg_ten"), -10);
1894
1895 // 1f must be serialized to JSON as "1.0" in order to be a double, not an int.
1896 dict = FindNamePhase("event3", "X");
1897 ASSERT_TRUE(dict);
1898 args_dict = dict->FindDict("args");
1899 ASSERT_TRUE(args_dict);
1900 EXPECT_EQ(*args_dict->FindDouble("float_one"), 1.0);
1901
1902 // .5f must be serialized to JSON as "0.5".
1903 dict = FindNamePhase("event4", "X");
1904 ASSERT_TRUE(dict);
1905 args_dict = dict->FindDict("args");
1906 ASSERT_TRUE(args_dict);
1907 EXPECT_EQ(*args_dict->FindDouble("float_half"), 0.5);
1908
1909 // -.5f must be serialized to JSON as "-0.5".
1910 dict = FindNamePhase("event5", "X");
1911 ASSERT_TRUE(dict);
1912 args_dict = dict->FindDict("args");
1913 ASSERT_TRUE(args_dict);
1914 EXPECT_EQ(*args_dict->FindDouble("float_neghalf"), -0.5);
1915
1916 // Infinity is serialized to JSON as a string.
1917 dict = FindNamePhase("event6", "X");
1918 ASSERT_TRUE(dict);
1919 args_dict = dict->FindDict("args");
1920 ASSERT_TRUE(args_dict);
1921 EXPECT_EQ(*args_dict->FindString("float_infinity"), "Infinity");
1922 dict = FindNamePhase("event6b", "X");
1923 ASSERT_TRUE(dict);
1924 args_dict = dict->FindDict("args");
1925 ASSERT_TRUE(args_dict);
1926 EXPECT_EQ(*args_dict->FindString("float_neg_infinity"), "-Infinity");
1927
1928 // NaN is serialized to JSON as a string.
1929 dict = FindNamePhase("event7", "X");
1930 ASSERT_TRUE(dict);
1931 args_dict = dict->FindDict("args");
1932 ASSERT_TRUE(args_dict);
1933 EXPECT_EQ(*args_dict->FindString("double_nan"), "NaN");
1934
1935 // NULL pointers should be serialized as "0x0".
1936 dict = FindNamePhase("event8", "X");
1937 ASSERT_TRUE(dict);
1938 args_dict = dict->FindDict("args");
1939 ASSERT_TRUE(args_dict);
1940 EXPECT_EQ(*args_dict->FindString("pointer_null"), "0x0");
1941
1942 // Other pointers should be serlized as a hex string.
1943 dict = FindNamePhase("event9", "X");
1944 ASSERT_TRUE(dict);
1945 args_dict = dict->FindDict("args");
1946 ASSERT_TRUE(args_dict);
1947 EXPECT_EQ(*args_dict->FindString("pointer_badf00d"), "0xbadf00d");
1948
1949 dict = FindNamePhase("event10", "X");
1950 ASSERT_TRUE(dict);
1951 args_dict = dict->FindDict("args");
1952 ASSERT_TRUE(args_dict);
1953 EXPECT_EQ(*args_dict->FindBool("bool_true"), true);
1954
1955 dict = FindNamePhase("event11", "X");
1956 ASSERT_TRUE(dict);
1957 args_dict = dict->FindDict("args");
1958 ASSERT_TRUE(args_dict);
1959 EXPECT_EQ(*args_dict->FindBool("bool_false"), false);
1960
1961 dict = FindNamePhase("event12", "X");
1962 ASSERT_TRUE(dict);
1963 args_dict = dict->FindDict("args");
1964 ASSERT_TRUE(args_dict);
1965 EXPECT_EQ(*args_dict->FindInt("time_null"), 0);
1966
1967 dict = FindNamePhase("event13", "X");
1968 ASSERT_TRUE(dict);
1969 args_dict = dict->FindDict("args");
1970 ASSERT_TRUE(args_dict);
1971 EXPECT_EQ(*args_dict->FindInt("time_one"), 1);
1972
1973 dict = FindNamePhase("event14", "X");
1974 ASSERT_TRUE(dict);
1975 args_dict = dict->FindDict("args");
1976 ASSERT_TRUE(args_dict);
1977 EXPECT_EQ(*args_dict->FindInt("timeticks_null"), 0);
1978
1979 dict = FindNamePhase("event15", "X");
1980 ASSERT_TRUE(dict);
1981 args_dict = dict->FindDict("args");
1982 ASSERT_TRUE(args_dict);
1983 EXPECT_EQ(*args_dict->FindInt("timeticks_one"), 1);
1984 }
1985
TEST_F(TraceEventTestFixture,NameIsEscaped)1986 TEST_F(TraceEventTestFixture, NameIsEscaped) {
1987 TraceLog::GetInstance()->SetEnabled(TraceConfig(kRecordAllCategoryFilter, ""),
1988 TraceLog::RECORDING_MODE);
1989 TRACE_EVENT0("category", "name\\with\\backspaces");
1990 EndTraceAndFlush();
1991
1992 EXPECT_TRUE(FindMatchingValue("cat", "category"));
1993 EXPECT_TRUE(FindMatchingValue("name", "name\\with\\backspaces"));
1994 }
1995
1996 // Runtime args filtering is not supported by Perfetto.
1997 #if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
1998 namespace {
1999
IsArgNameAllowed(const char * arg_name)2000 bool IsArgNameAllowed(const char* arg_name) {
2001 return base::MatchPattern(arg_name, "granular_arg_allowed");
2002 }
2003
IsTraceEventArgsAllowlisted(const char * category_group_name,const char * event_name,ArgumentNameFilterPredicate * arg_filter)2004 bool IsTraceEventArgsAllowlisted(const char* category_group_name,
2005 const char* event_name,
2006 ArgumentNameFilterPredicate* arg_filter) {
2007 if (base::MatchPattern(category_group_name, "toplevel") &&
2008 base::MatchPattern(event_name, "*")) {
2009 return true;
2010 }
2011
2012 if (base::MatchPattern(category_group_name, "benchmark") &&
2013 base::MatchPattern(event_name, "granularly_allowed")) {
2014 *arg_filter = base::BindRepeating(&IsArgNameAllowed);
2015 return true;
2016 }
2017
2018 return false;
2019 }
2020
2021 } // namespace
2022
TEST_F(TraceEventTestFixture,ArgsAllowlisting)2023 TEST_F(TraceEventTestFixture, ArgsAllowlisting) {
2024 TraceLog::GetInstance()->SetArgumentFilterPredicate(
2025 base::BindRepeating(&IsTraceEventArgsAllowlisted));
2026
2027 TraceLog::GetInstance()->SetEnabled(
2028 TraceConfig(kRecordAllCategoryFilter, "enable-argument-filter"),
2029 TraceLog::RECORDING_MODE);
2030
2031 TRACE_EVENT1("toplevel", "event1", "int_one", 1);
2032 TRACE_EVENT1("Testing", "event2", "int_two", 1);
2033
2034 TRACE_EVENT2("benchmark", "granularly_allowed", "granular_arg_allowed",
2035 "allowed_value", "granular_arg_disallowed", "disallowed_value");
2036
2037 EndTraceAndFlush();
2038
2039 const Value::Dict* args_dict = nullptr;
2040 const Value::Dict* dict = nullptr;
2041
2042 dict = FindNamePhase("event1", "X");
2043 ASSERT_TRUE(dict);
2044 args_dict = dict->FindDict("args");
2045 ASSERT_TRUE(args_dict);
2046 EXPECT_EQ(*args_dict->FindInt("int_one"), 1);
2047 EXPECT_FALSE(args_dict->FindInt("int_two"));
2048
2049 dict = FindNamePhase("event2", "X");
2050 ASSERT_TRUE(dict);
2051 EXPECT_EQ(*dict->FindString("args"), "__stripped__");
2052
2053 dict = FindNamePhase("granularly_allowed", "X");
2054 ASSERT_TRUE(dict);
2055 args_dict = dict->FindDict("args");
2056 ASSERT_TRUE(args_dict);
2057
2058 EXPECT_EQ(*args_dict->FindString("granular_arg_allowed"), "allowed_value");
2059
2060 EXPECT_EQ(*args_dict->FindString("granular_arg_disallowed"), "__stripped__");
2061 }
2062 #endif // !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
2063
2064 // TraceBuffer isn't used with Perfetto.
2065 #if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
TEST_F(TraceEventTestFixture,TraceBufferVectorReportFull)2066 TEST_F(TraceEventTestFixture, TraceBufferVectorReportFull) {
2067 TraceLog* trace_log = TraceLog::GetInstance();
2068 trace_log->SetEnabled(
2069 TraceConfig(kRecordAllCategoryFilter, ""), TraceLog::RECORDING_MODE);
2070 trace_log->logged_events_.reset(
2071 TraceBuffer::CreateTraceBufferVectorOfSize(100));
2072 do {
2073 TRACE_EVENT_BEGIN_WITH_ID_TID_AND_TIMESTAMP0("test_all", "with_timestamp",
2074 0, 0, TimeTicks::Now());
2075 TRACE_EVENT_END_WITH_ID_TID_AND_TIMESTAMP0("test_all", "with_timestamp", 0,
2076 0, TimeTicks::Now());
2077 } while (!trace_log->BufferIsFull());
2078
2079 EndTraceAndFlush();
2080
2081 const Value::Dict* trace_full_metadata = nullptr;
2082
2083 trace_full_metadata = FindTraceEntry(trace_parsed_,
2084 "overflowed_at_ts");
2085
2086 EXPECT_TRUE(trace_full_metadata);
2087 EXPECT_EQ(*trace_full_metadata->FindString("ph"), "M");
2088 absl::optional<double> maybe_buffer_limit_reached_timestamp =
2089 trace_full_metadata->FindDoubleByDottedPath("args.overflowed_at_ts");
2090
2091 EXPECT_EQ(*maybe_buffer_limit_reached_timestamp,
2092 static_cast<double>(
2093 trace_log->buffer_limit_reached_timestamp_.ToInternalValue()));
2094
2095 // Test that buffer_limit_reached_timestamp's value is between the timestamp
2096 // of the last trace event and current time.
2097 DropTracedMetadataRecords();
2098 ASSERT_TRUE(!trace_parsed_.empty());
2099 const Value& last_trace_event = trace_parsed_.back();
2100 EXPECT_TRUE(last_trace_event.is_dict());
2101 absl::optional<double> maybe_last_trace_event_timestamp =
2102 last_trace_event.GetDict().FindDouble("ts");
2103 EXPECT_TRUE(maybe_last_trace_event_timestamp.has_value());
2104 EXPECT_LE(maybe_last_trace_event_timestamp.value(),
2105 maybe_buffer_limit_reached_timestamp.value());
2106 EXPECT_LE(maybe_buffer_limit_reached_timestamp.value(),
2107 trace_log->OffsetNow().ToInternalValue());
2108 }
2109
TEST_F(TraceEventTestFixture,TraceBufferRingBufferGetReturnChunk)2110 TEST_F(TraceEventTestFixture, TraceBufferRingBufferGetReturnChunk) {
2111 TraceLog::GetInstance()->SetEnabled(
2112 TraceConfig(kRecordAllCategoryFilter, RECORD_CONTINUOUSLY),
2113 TraceLog::RECORDING_MODE);
2114 TraceBuffer* buffer = TraceLog::GetInstance()->trace_buffer();
2115 size_t capacity = buffer->Capacity();
2116 size_t num_chunks = capacity / TraceBufferChunk::kTraceBufferChunkSize;
2117 uint32_t last_seq = 0;
2118 size_t chunk_index;
2119 EXPECT_EQ(0u, buffer->Size());
2120
2121 std::unique_ptr<TraceBufferChunk* []> chunks(
2122 new TraceBufferChunk*[num_chunks]);
2123 for (size_t i = 0; i < num_chunks; ++i) {
2124 chunks[i] = buffer->GetChunk(&chunk_index).release();
2125 EXPECT_TRUE(chunks[i]);
2126 EXPECT_EQ(i, chunk_index);
2127 EXPECT_GT(chunks[i]->seq(), last_seq);
2128 EXPECT_EQ((i + 1) * TraceBufferChunk::kTraceBufferChunkSize,
2129 buffer->Size());
2130 last_seq = chunks[i]->seq();
2131 }
2132
2133 // Ring buffer is never full.
2134 EXPECT_FALSE(buffer->IsFull());
2135
2136 // Return all chunks in original order.
2137 for (size_t i = 0; i < num_chunks; ++i)
2138 buffer->ReturnChunk(i, std::unique_ptr<TraceBufferChunk>(chunks[i]));
2139
2140 // Should recycle the chunks in the returned order.
2141 for (size_t i = 0; i < num_chunks; ++i) {
2142 chunks[i] = buffer->GetChunk(&chunk_index).release();
2143 EXPECT_TRUE(chunks[i]);
2144 EXPECT_EQ(i, chunk_index);
2145 EXPECT_GT(chunks[i]->seq(), last_seq);
2146 last_seq = chunks[i]->seq();
2147 }
2148
2149 // Return all chunks in reverse order.
2150 for (size_t i = 0; i < num_chunks; ++i) {
2151 buffer->ReturnChunk(num_chunks - i - 1, std::unique_ptr<TraceBufferChunk>(
2152 chunks[num_chunks - i - 1]));
2153 }
2154
2155 // Should recycle the chunks in the returned order.
2156 for (size_t i = 0; i < num_chunks; ++i) {
2157 chunks[i] = buffer->GetChunk(&chunk_index).release();
2158 EXPECT_TRUE(chunks[i]);
2159 EXPECT_EQ(num_chunks - i - 1, chunk_index);
2160 EXPECT_GT(chunks[i]->seq(), last_seq);
2161 last_seq = chunks[i]->seq();
2162 }
2163
2164 for (size_t i = 0; i < num_chunks; ++i)
2165 buffer->ReturnChunk(i, std::unique_ptr<TraceBufferChunk>(chunks[i]));
2166
2167 TraceLog::GetInstance()->SetDisabled();
2168 }
2169
TEST_F(TraceEventTestFixture,TraceBufferRingBufferHalfIteration)2170 TEST_F(TraceEventTestFixture, TraceBufferRingBufferHalfIteration) {
2171 TraceLog::GetInstance()->SetEnabled(
2172 TraceConfig(kRecordAllCategoryFilter, RECORD_CONTINUOUSLY),
2173 TraceLog::RECORDING_MODE);
2174 TraceBuffer* buffer = TraceLog::GetInstance()->trace_buffer();
2175 size_t capacity = buffer->Capacity();
2176 size_t num_chunks = capacity / TraceBufferChunk::kTraceBufferChunkSize;
2177 size_t chunk_index;
2178 EXPECT_EQ(0u, buffer->Size());
2179 EXPECT_FALSE(buffer->NextChunk());
2180
2181 size_t half_chunks = num_chunks / 2;
2182 std::unique_ptr<TraceBufferChunk* []> chunks(
2183 new TraceBufferChunk*[half_chunks]);
2184
2185 for (size_t i = 0; i < half_chunks; ++i) {
2186 chunks[i] = buffer->GetChunk(&chunk_index).release();
2187 EXPECT_TRUE(chunks[i]);
2188 EXPECT_EQ(i, chunk_index);
2189 }
2190 for (size_t i = 0; i < half_chunks; ++i)
2191 buffer->ReturnChunk(i, std::unique_ptr<TraceBufferChunk>(chunks[i]));
2192
2193 for (size_t i = 0; i < half_chunks; ++i)
2194 EXPECT_EQ(chunks[i], buffer->NextChunk());
2195 EXPECT_FALSE(buffer->NextChunk());
2196 TraceLog::GetInstance()->SetDisabled();
2197 }
2198
TEST_F(TraceEventTestFixture,TraceBufferRingBufferFullIteration)2199 TEST_F(TraceEventTestFixture, TraceBufferRingBufferFullIteration) {
2200 TraceLog::GetInstance()->SetEnabled(
2201 TraceConfig(kRecordAllCategoryFilter, RECORD_CONTINUOUSLY),
2202 TraceLog::RECORDING_MODE);
2203 TraceBuffer* buffer = TraceLog::GetInstance()->trace_buffer();
2204 size_t capacity = buffer->Capacity();
2205 size_t num_chunks = capacity / TraceBufferChunk::kTraceBufferChunkSize;
2206 size_t chunk_index;
2207 EXPECT_EQ(0u, buffer->Size());
2208 EXPECT_FALSE(buffer->NextChunk());
2209
2210 std::unique_ptr<TraceBufferChunk* []> chunks(
2211 new TraceBufferChunk*[num_chunks]);
2212
2213 for (size_t i = 0; i < num_chunks; ++i) {
2214 chunks[i] = buffer->GetChunk(&chunk_index).release();
2215 EXPECT_TRUE(chunks[i]);
2216 EXPECT_EQ(i, chunk_index);
2217 }
2218 for (size_t i = 0; i < num_chunks; ++i)
2219 buffer->ReturnChunk(i, std::unique_ptr<TraceBufferChunk>(chunks[i]));
2220
2221 for (size_t i = 0; i < num_chunks; ++i)
2222 EXPECT_TRUE(chunks[i] == buffer->NextChunk());
2223 EXPECT_FALSE(buffer->NextChunk());
2224 TraceLog::GetInstance()->SetDisabled();
2225 }
2226
TEST_F(TraceEventTestFixture,TraceRecordAsMuchAsPossibleMode)2227 TEST_F(TraceEventTestFixture, TraceRecordAsMuchAsPossibleMode) {
2228 TraceLog::GetInstance()->SetEnabled(
2229 TraceConfig(kRecordAllCategoryFilter, RECORD_AS_MUCH_AS_POSSIBLE),
2230 TraceLog::RECORDING_MODE);
2231 TraceBuffer* buffer = TraceLog::GetInstance()->trace_buffer();
2232 EXPECT_EQ(512000000UL, buffer->Capacity());
2233 TraceLog::GetInstance()->SetDisabled();
2234 }
2235
TEST_F(TraceEventTestFixture,ConfigTraceBufferLimit)2236 TEST_F(TraceEventTestFixture, ConfigTraceBufferLimit) {
2237 const size_t kLimit = 2048;
2238 TraceConfig config(kRecordAllCategoryFilter, RECORD_UNTIL_FULL);
2239 config.SetTraceBufferSizeInEvents(kLimit);
2240 TraceLog::GetInstance()->SetEnabled(config, TraceLog::RECORDING_MODE);
2241 TraceBuffer* buffer = TraceLog::GetInstance()->trace_buffer();
2242 EXPECT_EQ(kLimit, buffer->Capacity());
2243 TraceLog::GetInstance()->SetDisabled();
2244 }
2245 #endif // BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
2246
BlockUntilStopped(WaitableEvent * task_start_event,WaitableEvent * task_stop_event)2247 void BlockUntilStopped(WaitableEvent* task_start_event,
2248 WaitableEvent* task_stop_event) {
2249 task_start_event->Signal();
2250 task_stop_event->Wait();
2251 }
2252
TEST_F(TraceEventTestFixture,SetCurrentThreadBlocksMessageLoopBeforeTracing)2253 TEST_F(TraceEventTestFixture, SetCurrentThreadBlocksMessageLoopBeforeTracing) {
2254 BeginTrace();
2255
2256 Thread thread("1");
2257 WaitableEvent task_complete_event(WaitableEvent::ResetPolicy::AUTOMATIC,
2258 WaitableEvent::InitialState::NOT_SIGNALED);
2259 thread.Start();
2260 thread.task_runner()->PostTask(
2261 FROM_HERE, BindOnce(&TraceLog::SetCurrentThreadBlocksMessageLoop,
2262 Unretained(TraceLog::GetInstance())));
2263
2264 thread.task_runner()->PostTask(
2265 FROM_HERE, BindOnce(&TraceWithAllMacroVariants, &task_complete_event));
2266 task_complete_event.Wait();
2267
2268 WaitableEvent task_start_event(WaitableEvent::ResetPolicy::AUTOMATIC,
2269 WaitableEvent::InitialState::NOT_SIGNALED);
2270 WaitableEvent task_stop_event(WaitableEvent::ResetPolicy::AUTOMATIC,
2271 WaitableEvent::InitialState::NOT_SIGNALED);
2272 thread.task_runner()->PostTask(
2273 FROM_HERE,
2274 BindOnce(&BlockUntilStopped, &task_start_event, &task_stop_event));
2275 task_start_event.Wait();
2276
2277 EndTraceAndFlush();
2278 ValidateAllTraceMacrosCreatedData(trace_parsed_);
2279
2280 task_stop_event.Signal();
2281 thread.Stop();
2282 }
2283
TEST_F(TraceEventTestFixture,ConvertTraceConfigToInternalOptions)2284 TEST_F(TraceEventTestFixture, ConvertTraceConfigToInternalOptions) {
2285 TraceLog* trace_log = TraceLog::GetInstance();
2286 EXPECT_EQ(TraceLog::kInternalRecordUntilFull,
2287 trace_log->GetInternalOptionsFromTraceConfig(
2288 TraceConfig(kRecordAllCategoryFilter, RECORD_UNTIL_FULL)));
2289
2290 EXPECT_EQ(TraceLog::kInternalRecordContinuously,
2291 trace_log->GetInternalOptionsFromTraceConfig(
2292 TraceConfig(kRecordAllCategoryFilter, RECORD_CONTINUOUSLY)));
2293
2294 EXPECT_EQ(TraceLog::kInternalEchoToConsole,
2295 trace_log->GetInternalOptionsFromTraceConfig(
2296 TraceConfig(kRecordAllCategoryFilter, ECHO_TO_CONSOLE)));
2297
2298 EXPECT_EQ(TraceLog::kInternalEchoToConsole,
2299 trace_log->GetInternalOptionsFromTraceConfig(
2300 TraceConfig("*", "trace-to-console,enable-systrace")));
2301 }
2302
SetBlockingFlagAndBlockUntilStopped(WaitableEvent * task_start_event,WaitableEvent * task_stop_event)2303 void SetBlockingFlagAndBlockUntilStopped(WaitableEvent* task_start_event,
2304 WaitableEvent* task_stop_event) {
2305 TraceLog::GetInstance()->SetCurrentThreadBlocksMessageLoop();
2306 BlockUntilStopped(task_start_event, task_stop_event);
2307 }
2308
TEST_F(TraceEventTestFixture,SetCurrentThreadBlocksMessageLoopAfterTracing)2309 TEST_F(TraceEventTestFixture, SetCurrentThreadBlocksMessageLoopAfterTracing) {
2310 BeginTrace();
2311
2312 Thread thread("1");
2313 WaitableEvent task_complete_event(WaitableEvent::ResetPolicy::AUTOMATIC,
2314 WaitableEvent::InitialState::NOT_SIGNALED);
2315 thread.Start();
2316
2317 thread.task_runner()->PostTask(
2318 FROM_HERE, BindOnce(&TraceWithAllMacroVariants, &task_complete_event));
2319 task_complete_event.Wait();
2320
2321 WaitableEvent task_start_event(WaitableEvent::ResetPolicy::AUTOMATIC,
2322 WaitableEvent::InitialState::NOT_SIGNALED);
2323 WaitableEvent task_stop_event(WaitableEvent::ResetPolicy::AUTOMATIC,
2324 WaitableEvent::InitialState::NOT_SIGNALED);
2325 thread.task_runner()->PostTask(FROM_HERE,
2326 BindOnce(&SetBlockingFlagAndBlockUntilStopped,
2327 &task_start_event, &task_stop_event));
2328 task_start_event.Wait();
2329
2330 EndTraceAndFlush();
2331 ValidateAllTraceMacrosCreatedData(trace_parsed_);
2332
2333 task_stop_event.Signal();
2334 thread.Stop();
2335 }
2336
TEST_F(TraceEventTestFixture,ThreadOnceBlocking)2337 TEST_F(TraceEventTestFixture, ThreadOnceBlocking) {
2338 BeginTrace();
2339
2340 Thread thread("1");
2341 WaitableEvent task_complete_event(WaitableEvent::ResetPolicy::AUTOMATIC,
2342 WaitableEvent::InitialState::NOT_SIGNALED);
2343 thread.Start();
2344
2345 thread.task_runner()->PostTask(
2346 FROM_HERE, BindOnce(&TraceWithAllMacroVariants, &task_complete_event));
2347 task_complete_event.Wait();
2348
2349 WaitableEvent task_start_event(WaitableEvent::ResetPolicy::AUTOMATIC,
2350 WaitableEvent::InitialState::NOT_SIGNALED);
2351 WaitableEvent task_stop_event(WaitableEvent::ResetPolicy::AUTOMATIC,
2352 WaitableEvent::InitialState::NOT_SIGNALED);
2353 thread.task_runner()->PostTask(
2354 FROM_HERE,
2355 BindOnce(&BlockUntilStopped, &task_start_event, &task_stop_event));
2356 task_start_event.Wait();
2357
2358 // The thread will timeout in this flush.
2359 EndTraceAndFlushInThreadWithMessageLoop();
2360 Clear();
2361
2362 // Let the thread's message loop continue to spin.
2363 task_stop_event.Signal();
2364
2365 // The following sequence ensures that the FlushCurrentThread task has been
2366 // executed in the thread before continuing.
2367 thread.task_runner()->PostTask(
2368 FROM_HERE,
2369 BindOnce(&BlockUntilStopped, &task_start_event, &task_stop_event));
2370 task_start_event.Wait();
2371 task_stop_event.Signal();
2372 Clear();
2373
2374 // TraceLog should discover the generation mismatch and recover the thread
2375 // local buffer for the thread without any error.
2376 BeginTrace();
2377 thread.task_runner()->PostTask(
2378 FROM_HERE, BindOnce(&TraceWithAllMacroVariants, &task_complete_event));
2379 task_complete_event.Wait();
2380 EndTraceAndFlushInThreadWithMessageLoop();
2381 ValidateAllTraceMacrosCreatedData(trace_parsed_);
2382 }
2383
2384 std::string* g_log_buffer = nullptr;
MockLogMessageHandler(int,const char *,int,size_t,const std::string & str)2385 bool MockLogMessageHandler(int, const char*, int, size_t,
2386 const std::string& str) {
2387 if (!g_log_buffer)
2388 g_log_buffer = new std::string();
2389 g_log_buffer->append(str);
2390 return false;
2391 }
2392
TEST_F(TraceEventTestFixture,EchoToConsole)2393 TEST_F(TraceEventTestFixture, EchoToConsole) {
2394 logging::LogMessageHandlerFunction old_log_message_handler =
2395 logging::GetLogMessageHandler();
2396 logging::SetLogMessageHandler(MockLogMessageHandler);
2397
2398 TraceLog::GetInstance()->SetEnabled(
2399 TraceConfig(kRecordAllCategoryFilter, ECHO_TO_CONSOLE),
2400 TraceLog::RECORDING_MODE);
2401 TRACE_EVENT_BEGIN0("test_a", "begin_end");
2402 {
2403 TRACE_EVENT0("test_b", "duration");
2404 TRACE_EVENT0("test_b1", "duration1");
2405 }
2406 TRACE_EVENT_INSTANT0("test_c", "instant", TRACE_EVENT_SCOPE_GLOBAL);
2407 TRACE_EVENT_END0("test_a", "begin_end");
2408
2409 // Perfetto's console interceptor outputs directly to the console and has test
2410 // coverage upstream.
2411 #if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
2412 EXPECT_NE(std::string::npos, g_log_buffer->find("begin_end[test_a]\x1b"));
2413 EXPECT_NE(std::string::npos, g_log_buffer->find("| duration[test_b]\x1b"));
2414 EXPECT_NE(std::string::npos,
2415 g_log_buffer->find("| | duration1[test_b1]\x1b"));
2416 EXPECT_NE(std::string::npos, g_log_buffer->find("| | duration1[test_b1] ("));
2417 EXPECT_NE(std::string::npos, g_log_buffer->find("| duration[test_b] ("));
2418 EXPECT_NE(std::string::npos, g_log_buffer->find("| instant[test_c]\x1b"));
2419 EXPECT_NE(std::string::npos, g_log_buffer->find("begin_end[test_a] ("));
2420 #endif // !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
2421
2422 EndTraceAndFlush();
2423 delete g_log_buffer;
2424 logging::SetLogMessageHandler(old_log_message_handler);
2425 g_log_buffer = nullptr;
2426 }
2427
LogMessageHandlerWithTraceEvent(int,const char *,int,size_t,const std::string &)2428 bool LogMessageHandlerWithTraceEvent(int, const char*, int, size_t,
2429 const std::string&) {
2430 TRACE_EVENT0("log", "trace_event");
2431 return false;
2432 }
2433
TEST_F(TraceEventTestFixture,EchoToConsoleTraceEventRecursion)2434 TEST_F(TraceEventTestFixture, EchoToConsoleTraceEventRecursion) {
2435 logging::LogMessageHandlerFunction old_log_message_handler =
2436 logging::GetLogMessageHandler();
2437 logging::SetLogMessageHandler(LogMessageHandlerWithTraceEvent);
2438
2439 TraceLog::GetInstance()->SetEnabled(
2440 TraceConfig(kRecordAllCategoryFilter, ECHO_TO_CONSOLE),
2441 TraceLog::RECORDING_MODE);
2442 {
2443 // This should not cause deadlock or infinite recursion.
2444 TRACE_EVENT0("test_b", "duration");
2445 }
2446
2447 EndTraceAndFlush();
2448 logging::SetLogMessageHandler(old_log_message_handler);
2449 }
2450
2451 // Perfetto doesn't support overriding the time offset.
2452 #if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
TEST_F(TraceEventTestFixture,TimeOffset)2453 TEST_F(TraceEventTestFixture, TimeOffset) {
2454 BeginTrace();
2455 // Let TraceLog timer start from 0.
2456 TimeDelta time_offset = TimeTicks::Now() - TimeTicks();
2457 TraceLog::GetInstance()->SetTimeOffset(time_offset);
2458
2459 {
2460 TRACE_EVENT0("test_all", "duration1");
2461 TRACE_EVENT0("test_all", "duration2");
2462 }
2463 TRACE_EVENT_BEGIN_WITH_ID_TID_AND_TIMESTAMP0("test_all", "with_timestamp", 0,
2464 0, TimeTicks::Now());
2465 TRACE_EVENT_END_WITH_ID_TID_AND_TIMESTAMP0("test_all", "with_timestamp", 0, 0,
2466 TimeTicks::Now());
2467
2468 EndTraceAndFlush();
2469 DropTracedMetadataRecords();
2470
2471 double end_time = static_cast<double>(
2472 (TimeTicks::Now() - time_offset).ToInternalValue());
2473 double last_timestamp = 0;
2474 for (const Value& item : trace_parsed_) {
2475 EXPECT_TRUE(item.is_dict());
2476 absl::optional<double> timestamp = item.GetDict().FindDouble("ts");
2477 EXPECT_TRUE(timestamp.has_value());
2478 EXPECT_GE(timestamp.value(), last_timestamp);
2479 EXPECT_LE(timestamp.value(), end_time);
2480 last_timestamp = timestamp.value();
2481 }
2482 }
2483 #endif // !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
2484
TEST_F(TraceEventTestFixture,ClockSyncEventsAreAlwaysAddedToTrace)2485 TEST_F(TraceEventTestFixture, ClockSyncEventsAreAlwaysAddedToTrace) {
2486 BeginSpecificTrace("-*");
2487 TRACE_EVENT_CLOCK_SYNC_RECEIVER(1);
2488 EndTraceAndFlush();
2489 EXPECT_TRUE(FindNamePhase("clock_sync", "c"));
2490 }
2491
TEST_F(TraceEventTestFixture,ContextLambda)2492 TEST_F(TraceEventTestFixture, ContextLambda) {
2493 TraceLog::GetInstance()->SetEnabled(TraceConfig(kRecordAllCategoryFilter, ""),
2494 TraceLog::RECORDING_MODE);
2495
2496 {
2497 TRACE_EVENT1("cat", "Name", "arg", [&](perfetto::TracedValue ctx) {
2498 std::move(ctx).WriteString("foobar");
2499 });
2500 }
2501 EndTraceAndFlush();
2502
2503 const Value::Dict* dict = FindNamePhase("Name", "X");
2504 ASSERT_TRUE(dict);
2505
2506 const Value::Dict* args_dict = dict->FindDict("args");
2507 ASSERT_TRUE(args_dict);
2508
2509 #if BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
2510 EXPECT_EQ(*args_dict->FindString("arg"), "foobar");
2511 #else
2512 // Pre-client-lib, these types of TracedValues can't be serialized to JSON.
2513 EXPECT_EQ(*args_dict->FindString("arg"), "Unsupported (crbug.com/1225176)");
2514 #endif
2515 }
2516
2517 #if BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
2518 class ConfigObserver : public TraceLog::EnabledStateObserver {
2519 public:
2520 ConfigObserver() = default;
2521 ~ConfigObserver() override = default;
2522
OnTraceLogEnabled()2523 void OnTraceLogEnabled() override {
2524 observed_config = TraceLog::GetInstance()->GetCurrentTraceConfig();
2525 tracing_enabled.Signal();
2526 }
2527
OnTraceLogDisabled()2528 void OnTraceLogDisabled() override { tracing_disabled.Signal(); }
2529
2530 TraceConfig observed_config;
2531 WaitableEvent tracing_enabled{WaitableEvent::ResetPolicy::AUTOMATIC,
2532 WaitableEvent::InitialState::NOT_SIGNALED};
2533 WaitableEvent tracing_disabled{WaitableEvent::ResetPolicy::AUTOMATIC,
2534 WaitableEvent::InitialState::NOT_SIGNALED};
2535 };
2536
2537 // Test that GetCurrentTraceConfig() returns the correct config when tracing
2538 // was started through Perfetto SDK.
TEST_F(TraceEventTestFixture,GetCurrentTraceConfig)2539 TEST_F(TraceEventTestFixture, GetCurrentTraceConfig) {
2540 ConfigObserver observer;
2541 TraceLog::GetInstance()->AddEnabledStateObserver(&observer);
2542
2543 const TraceConfig actual_config{"foo,bar", ""};
2544 perfetto::TraceConfig perfetto_config;
2545 perfetto_config.add_buffers()->set_size_kb(1000);
2546 auto* source_config = perfetto_config.add_data_sources()->mutable_config();
2547 source_config->set_name("track_event");
2548 source_config->set_target_buffer(0);
2549 source_config->mutable_chrome_config()->set_trace_config(
2550 actual_config.ToString());
2551
2552 auto tracing_session = perfetto::Tracing::NewTrace();
2553 tracing_session->Setup(perfetto_config);
2554 tracing_session->Start();
2555
2556 observer.tracing_enabled.Wait();
2557 tracing_session->Stop();
2558 observer.tracing_disabled.Wait();
2559
2560 EXPECT_EQ(actual_config.ToString(), observer.observed_config.ToString());
2561 }
2562 #endif // BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
2563
2564 } // namespace base::trace_event
2565