1 // Copyright 2016 The Chromium Authors. All rights reserved.
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/blame_context.h"
6 
7 #include "base/json/json_writer.h"
8 #include "base/test/task_environment.h"
9 #include "base/test/trace_event_analyzer.h"
10 #include "base/trace_event/traced_value.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12 
13 namespace base {
14 namespace trace_event {
15 namespace {
16 
17 const char kTestBlameContextCategory[] = "test";
18 const char kDisabledTestBlameContextCategory[] = "disabled-by-default-test";
19 const char kTestBlameContextName[] = "TestBlameContext";
20 const char kTestBlameContextType[] = "TestBlameContextType";
21 const char kTestBlameContextScope[] = "TestBlameContextScope";
22 
23 class TestBlameContext : public BlameContext {
24  public:
TestBlameContext(int id)25   explicit TestBlameContext(int id)
26       : BlameContext(kTestBlameContextCategory,
27                      kTestBlameContextName,
28                      kTestBlameContextType,
29                      kTestBlameContextScope,
30                      id,
31                      nullptr) {}
32 
TestBlameContext(int id,const TestBlameContext & parent)33   TestBlameContext(int id, const TestBlameContext& parent)
34       : BlameContext(kTestBlameContextCategory,
35                      kTestBlameContextName,
36                      kTestBlameContextType,
37                      kTestBlameContextScope,
38                      id,
39                      &parent) {}
40 
41  protected:
AsValueInto(trace_event::TracedValue * state)42   void AsValueInto(trace_event::TracedValue* state) override {
43     BlameContext::AsValueInto(state);
44     state->SetBoolean("crossStreams", false);
45   }
46 };
47 
48 class DisabledTestBlameContext : public BlameContext {
49  public:
DisabledTestBlameContext(int id)50   explicit DisabledTestBlameContext(int id)
51       : BlameContext(kDisabledTestBlameContextCategory,
52                      kTestBlameContextName,
53                      kTestBlameContextType,
54                      kTestBlameContextScope,
55                      id,
56                      nullptr) {}
57 };
58 
59 class BlameContextTest : public testing::Test {
60  protected:
61   test::TaskEnvironment task_environment_;
62 };
63 
TEST_F(BlameContextTest,EnterAndLeave)64 TEST_F(BlameContextTest, EnterAndLeave) {
65   using trace_analyzer::Query;
66   trace_analyzer::Start("*");
67   {
68     TestBlameContext blame_context(0x1234);
69     blame_context.Initialize();
70     blame_context.Enter();
71     blame_context.Leave();
72   }
73   auto analyzer = trace_analyzer::Stop();
74 
75   trace_analyzer::TraceEventVector events;
76   Query q = Query::EventPhaseIs(TRACE_EVENT_PHASE_ENTER_CONTEXT) ||
77             Query::EventPhaseIs(TRACE_EVENT_PHASE_LEAVE_CONTEXT);
78   analyzer->FindEvents(q, &events);
79 
80   EXPECT_EQ(2u, events.size());
81   EXPECT_EQ(TRACE_EVENT_PHASE_ENTER_CONTEXT, events[0]->phase);
82   EXPECT_EQ(kTestBlameContextCategory, events[0]->category);
83   EXPECT_EQ(kTestBlameContextName, events[0]->name);
84   EXPECT_EQ("0x1234", events[0]->id);
85   EXPECT_EQ(TRACE_EVENT_PHASE_LEAVE_CONTEXT, events[1]->phase);
86   EXPECT_EQ(kTestBlameContextCategory, events[1]->category);
87   EXPECT_EQ(kTestBlameContextName, events[1]->name);
88   EXPECT_EQ("0x1234", events[1]->id);
89 }
90 
TEST_F(BlameContextTest,DifferentCategories)91 TEST_F(BlameContextTest, DifferentCategories) {
92   // Ensure there is no cross talk between blame contexts from different
93   // categories.
94   using trace_analyzer::Query;
95   trace_analyzer::Start("*");
96   {
97     TestBlameContext blame_context(0x1234);
98     DisabledTestBlameContext disabled_blame_context(0x5678);
99     blame_context.Initialize();
100     blame_context.Enter();
101     blame_context.Leave();
102     disabled_blame_context.Initialize();
103     disabled_blame_context.Enter();
104     disabled_blame_context.Leave();
105   }
106   auto analyzer = trace_analyzer::Stop();
107 
108   trace_analyzer::TraceEventVector events;
109   Query q = Query::EventPhaseIs(TRACE_EVENT_PHASE_ENTER_CONTEXT) ||
110             Query::EventPhaseIs(TRACE_EVENT_PHASE_LEAVE_CONTEXT);
111   analyzer->FindEvents(q, &events);
112 
113   // None of the events from the disabled-by-default category should show up.
114   EXPECT_EQ(2u, events.size());
115   EXPECT_EQ(TRACE_EVENT_PHASE_ENTER_CONTEXT, events[0]->phase);
116   EXPECT_EQ(kTestBlameContextCategory, events[0]->category);
117   EXPECT_EQ(kTestBlameContextName, events[0]->name);
118   EXPECT_EQ("0x1234", events[0]->id);
119   EXPECT_EQ(TRACE_EVENT_PHASE_LEAVE_CONTEXT, events[1]->phase);
120   EXPECT_EQ(kTestBlameContextCategory, events[1]->category);
121   EXPECT_EQ(kTestBlameContextName, events[1]->name);
122   EXPECT_EQ("0x1234", events[1]->id);
123 }
124 
TEST_F(BlameContextTest,TakeSnapshot)125 TEST_F(BlameContextTest, TakeSnapshot) {
126   using trace_analyzer::Query;
127   trace_analyzer::Start("*");
128   {
129     TestBlameContext parent_blame_context(0x5678);
130     TestBlameContext blame_context(0x1234, parent_blame_context);
131     parent_blame_context.Initialize();
132     blame_context.Initialize();
133     blame_context.TakeSnapshot();
134   }
135   auto analyzer = trace_analyzer::Stop();
136 
137   trace_analyzer::TraceEventVector events;
138   Query q = Query::EventPhaseIs(TRACE_EVENT_PHASE_SNAPSHOT_OBJECT);
139   analyzer->FindEvents(q, &events);
140 
141   // We should have 3 snapshots: one for both calls to Initialize() and one from
142   // the explicit call to TakeSnapshot().
143   EXPECT_EQ(3u, events.size());
144   EXPECT_EQ(kTestBlameContextCategory, events[0]->category);
145   EXPECT_EQ(kTestBlameContextType, events[0]->name);
146   EXPECT_EQ("0x5678", events[0]->id);
147   EXPECT_TRUE(events[0]->HasArg("snapshot"));
148 
149   EXPECT_EQ(kTestBlameContextCategory, events[1]->category);
150   EXPECT_EQ(kTestBlameContextType, events[1]->name);
151   EXPECT_EQ("0x1234", events[1]->id);
152   EXPECT_TRUE(events[0]->HasArg("snapshot"));
153 
154   EXPECT_EQ(kTestBlameContextCategory, events[2]->category);
155   EXPECT_EQ(kTestBlameContextType, events[2]->name);
156   EXPECT_EQ("0x1234", events[2]->id);
157   EXPECT_TRUE(events[0]->HasArg("snapshot"));
158 
159   const char kExpectedSnapshotJson[] =
160       "{"
161           "\"crossStreams\":false,"
162           "\"parent\":{"
163               "\"id_ref\":\"0x5678\","
164               "\"scope\":\"TestBlameContextScope\""
165           "}"
166       "}";
167 
168   std::string snapshot_json;
169   JSONWriter::Write(*events[2]->GetKnownArgAsValue("snapshot"), &snapshot_json);
170   EXPECT_EQ(kExpectedSnapshotJson, snapshot_json);
171 }
172 
173 }  // namepace
174 }  // namespace trace_event
175 }  // namespace base
176