• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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