OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <stddef.h> | 5 #include <stddef.h> |
6 | 6 |
7 #include <iterator> | 7 #include <iterator> |
8 | 8 |
9 #include "base/memory/ref_counted.h" | 9 #include "base/memory/ref_counted.h" |
10 #include "base/pending_task.h" | 10 #include "base/pending_task.h" |
(...skipping 15 matching lines...) Expand all Loading... |
26 | 26 |
27 // Asserts that the fixed-size array |expected_backtrace| matches the backtrace | 27 // Asserts that the fixed-size array |expected_backtrace| matches the backtrace |
28 // in |AllocationContextTracker::GetContextSnapshot|. | 28 // in |AllocationContextTracker::GetContextSnapshot|. |
29 template <size_t N> | 29 template <size_t N> |
30 void AssertBacktraceEquals(const StackFrame(&expected_backtrace)[N]) { | 30 void AssertBacktraceEquals(const StackFrame(&expected_backtrace)[N]) { |
31 AllocationContext ctx = | 31 AllocationContext ctx = |
32 AllocationContextTracker::GetInstanceForCurrentThread() | 32 AllocationContextTracker::GetInstanceForCurrentThread() |
33 ->GetContextSnapshot(); | 33 ->GetContextSnapshot(); |
34 | 34 |
35 auto actual = std::begin(ctx.backtrace.frames); | 35 auto actual = std::begin(ctx.backtrace.frames); |
36 auto actual_bottom = std::end(ctx.backtrace.frames); | 36 auto actual_bottom = actual + ctx.backtrace.frame_count; |
37 auto expected = std::begin(expected_backtrace); | 37 auto expected = std::begin(expected_backtrace); |
38 auto expected_bottom = std::end(expected_backtrace); | 38 auto expected_bottom = std::end(expected_backtrace); |
39 | 39 |
40 // Note that this requires the pointers to be equal, this is not doing a deep | 40 // Note that this requires the pointers to be equal, this is not doing a deep |
41 // string comparison. | 41 // string comparison. |
42 for (; actual != actual_bottom && expected != expected_bottom; | 42 for (; actual != actual_bottom && expected != expected_bottom; |
43 actual++, expected++) | 43 actual++, expected++) |
44 ASSERT_EQ(*expected, *actual); | 44 ASSERT_EQ(*expected, *actual); |
45 | 45 |
46 // Ensure that the height of the stacks is the same. | 46 // Ensure that the height of the stacks is the same. |
47 ASSERT_EQ(actual, actual_bottom); | 47 ASSERT_EQ(actual, actual_bottom); |
48 ASSERT_EQ(expected, expected_bottom); | 48 ASSERT_EQ(expected, expected_bottom); |
49 } | 49 } |
50 | 50 |
51 void AssertBacktraceEmpty() { | 51 void AssertBacktraceEmpty() { |
52 AllocationContext ctx = | 52 AllocationContext ctx = |
53 AllocationContextTracker::GetInstanceForCurrentThread() | 53 AllocationContextTracker::GetInstanceForCurrentThread() |
54 ->GetContextSnapshot(); | 54 ->GetContextSnapshot(); |
55 | 55 |
56 for (StackFrame frame : ctx.backtrace.frames) | 56 ASSERT_EQ(0u, ctx.backtrace.frame_count); |
57 ASSERT_EQ(nullptr, frame); | |
58 } | 57 } |
59 | 58 |
60 class AllocationContextTrackerTest : public testing::Test { | 59 class AllocationContextTrackerTest : public testing::Test { |
61 public: | 60 public: |
62 void SetUp() override { | 61 void SetUp() override { |
63 TraceConfig config(""); | 62 TraceConfig config(""); |
64 TraceLog::GetInstance()->SetEnabled(config, TraceLog::RECORDING_MODE); | 63 TraceLog::GetInstance()->SetEnabled(config, TraceLog::RECORDING_MODE); |
65 AllocationContextTracker::SetCaptureEnabled(true); | 64 AllocationContextTracker::SetCaptureEnabled(true); |
66 } | 65 } |
67 | 66 |
68 void TearDown() override { | 67 void TearDown() override { |
69 AllocationContextTracker::SetCaptureEnabled(false); | 68 AllocationContextTracker::SetCaptureEnabled(false); |
70 TraceLog::GetInstance()->SetDisabled(); | 69 TraceLog::GetInstance()->SetDisabled(); |
71 } | 70 } |
72 }; | 71 }; |
73 | 72 |
74 // Check that |TRACE_EVENT| macros push and pop to the pseudo stack correctly. | 73 // Check that |TRACE_EVENT| macros push and pop to the pseudo stack correctly. |
75 // Also check that |GetContextSnapshot| fills the backtrace with null pointers | |
76 // when the pseudo stack height is less than the capacity. | |
77 TEST_F(AllocationContextTrackerTest, PseudoStackScopedTrace) { | 74 TEST_F(AllocationContextTrackerTest, PseudoStackScopedTrace) { |
78 StackFrame c = kCupcake; | 75 StackFrame c = StackFrame::FromTraceEventName(kCupcake); |
79 StackFrame d = kDonut; | 76 StackFrame d = StackFrame::FromTraceEventName(kDonut); |
80 StackFrame e = kEclair; | 77 StackFrame e = StackFrame::FromTraceEventName(kEclair); |
81 StackFrame f = kFroyo; | 78 StackFrame f = StackFrame::FromTraceEventName(kFroyo); |
82 | 79 |
83 AssertBacktraceEmpty(); | 80 AssertBacktraceEmpty(); |
84 | 81 |
85 { | 82 { |
86 TRACE_EVENT0("Testing", kCupcake); | 83 TRACE_EVENT0("Testing", kCupcake); |
87 StackFrame frame_c[] = {c, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | 84 StackFrame frame_c[] = {c}; |
88 AssertBacktraceEquals(frame_c); | 85 AssertBacktraceEquals(frame_c); |
89 | 86 |
90 { | 87 { |
91 TRACE_EVENT0("Testing", kDonut); | 88 TRACE_EVENT0("Testing", kDonut); |
92 StackFrame frame_cd[] = {c, d, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | 89 StackFrame frame_cd[] = {c, d}; |
93 AssertBacktraceEquals(frame_cd); | 90 AssertBacktraceEquals(frame_cd); |
94 } | 91 } |
95 | 92 |
96 AssertBacktraceEquals(frame_c); | 93 AssertBacktraceEquals(frame_c); |
97 | 94 |
98 { | 95 { |
99 TRACE_EVENT0("Testing", kEclair); | 96 TRACE_EVENT0("Testing", kEclair); |
100 StackFrame frame_ce[] = {c, e, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | 97 StackFrame frame_ce[] = {c, e}; |
101 AssertBacktraceEquals(frame_ce); | 98 AssertBacktraceEquals(frame_ce); |
102 } | 99 } |
103 | 100 |
104 AssertBacktraceEquals(frame_c); | 101 AssertBacktraceEquals(frame_c); |
105 } | 102 } |
106 | 103 |
107 AssertBacktraceEmpty(); | 104 AssertBacktraceEmpty(); |
108 | 105 |
109 { | 106 { |
110 TRACE_EVENT0("Testing", kFroyo); | 107 TRACE_EVENT0("Testing", kFroyo); |
111 StackFrame frame_f[] = {f, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | 108 StackFrame frame_f[] = {f}; |
112 AssertBacktraceEquals(frame_f); | 109 AssertBacktraceEquals(frame_f); |
113 } | 110 } |
114 | 111 |
115 AssertBacktraceEmpty(); | 112 AssertBacktraceEmpty(); |
116 } | 113 } |
117 | 114 |
118 // Same as |PseudoStackScopedTrace|, but now test the |TRACE_EVENT_BEGIN| and | 115 // Same as |PseudoStackScopedTrace|, but now test the |TRACE_EVENT_BEGIN| and |
119 // |TRACE_EVENT_END| macros. | 116 // |TRACE_EVENT_END| macros. |
120 TEST_F(AllocationContextTrackerTest, PseudoStackBeginEndTrace) { | 117 TEST_F(AllocationContextTrackerTest, PseudoStackBeginEndTrace) { |
121 StackFrame c = kCupcake; | 118 StackFrame c = StackFrame::FromTraceEventName(kCupcake); |
122 StackFrame d = kDonut; | 119 StackFrame d = StackFrame::FromTraceEventName(kDonut); |
123 StackFrame e = kEclair; | 120 StackFrame e = StackFrame::FromTraceEventName(kEclair); |
124 StackFrame f = kFroyo; | 121 StackFrame f = StackFrame::FromTraceEventName(kFroyo); |
125 | 122 |
126 StackFrame frame_c[] = {c, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | 123 StackFrame frame_c[] = {c}; |
127 StackFrame frame_cd[] = {c, d, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | 124 StackFrame frame_cd[] = {c, d}; |
128 StackFrame frame_ce[] = {c, e, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | 125 StackFrame frame_ce[] = {c, e}; |
129 StackFrame frame_f[] = {f, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | 126 StackFrame frame_f[] = {f}; |
130 | 127 |
131 AssertBacktraceEmpty(); | 128 AssertBacktraceEmpty(); |
132 | 129 |
133 TRACE_EVENT_BEGIN0("Testing", kCupcake); | 130 TRACE_EVENT_BEGIN0("Testing", kCupcake); |
134 AssertBacktraceEquals(frame_c); | 131 AssertBacktraceEquals(frame_c); |
135 | 132 |
136 TRACE_EVENT_BEGIN0("Testing", kDonut); | 133 TRACE_EVENT_BEGIN0("Testing", kDonut); |
137 AssertBacktraceEquals(frame_cd); | 134 AssertBacktraceEquals(frame_cd); |
138 TRACE_EVENT_END0("Testing", kDonut); | 135 TRACE_EVENT_END0("Testing", kDonut); |
139 | 136 |
140 AssertBacktraceEquals(frame_c); | 137 AssertBacktraceEquals(frame_c); |
141 | 138 |
142 TRACE_EVENT_BEGIN0("Testing", kEclair); | 139 TRACE_EVENT_BEGIN0("Testing", kEclair); |
143 AssertBacktraceEquals(frame_ce); | 140 AssertBacktraceEquals(frame_ce); |
144 TRACE_EVENT_END0("Testing", kEclair); | 141 TRACE_EVENT_END0("Testing", kEclair); |
145 | 142 |
146 AssertBacktraceEquals(frame_c); | 143 AssertBacktraceEquals(frame_c); |
147 TRACE_EVENT_END0("Testing", kCupcake); | 144 TRACE_EVENT_END0("Testing", kCupcake); |
148 | 145 |
149 AssertBacktraceEmpty(); | 146 AssertBacktraceEmpty(); |
150 | 147 |
151 TRACE_EVENT_BEGIN0("Testing", kFroyo); | 148 TRACE_EVENT_BEGIN0("Testing", kFroyo); |
152 AssertBacktraceEquals(frame_f); | 149 AssertBacktraceEquals(frame_f); |
153 TRACE_EVENT_END0("Testing", kFroyo); | 150 TRACE_EVENT_END0("Testing", kFroyo); |
154 | 151 |
155 AssertBacktraceEmpty(); | 152 AssertBacktraceEmpty(); |
156 } | 153 } |
157 | 154 |
158 TEST_F(AllocationContextTrackerTest, PseudoStackMixedTrace) { | 155 TEST_F(AllocationContextTrackerTest, PseudoStackMixedTrace) { |
159 StackFrame c = kCupcake; | 156 StackFrame c = StackFrame::FromTraceEventName(kCupcake); |
160 StackFrame d = kDonut; | 157 StackFrame d = StackFrame::FromTraceEventName(kDonut); |
161 StackFrame e = kEclair; | 158 StackFrame e = StackFrame::FromTraceEventName(kEclair); |
162 StackFrame f = kFroyo; | 159 StackFrame f = StackFrame::FromTraceEventName(kFroyo); |
163 | 160 |
164 StackFrame frame_c[] = {c, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | 161 StackFrame frame_c[] = {c}; |
165 StackFrame frame_cd[] = {c, d, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | 162 StackFrame frame_cd[] = {c, d}; |
166 StackFrame frame_e[] = {e, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | 163 StackFrame frame_e[] = {e}; |
167 StackFrame frame_ef[] = {e, f, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | 164 StackFrame frame_ef[] = {e, f}; |
168 | 165 |
169 AssertBacktraceEmpty(); | 166 AssertBacktraceEmpty(); |
170 | 167 |
171 TRACE_EVENT_BEGIN0("Testing", kCupcake); | 168 TRACE_EVENT_BEGIN0("Testing", kCupcake); |
172 AssertBacktraceEquals(frame_c); | 169 AssertBacktraceEquals(frame_c); |
173 | 170 |
174 { | 171 { |
175 TRACE_EVENT0("Testing", kDonut); | 172 TRACE_EVENT0("Testing", kDonut); |
176 AssertBacktraceEquals(frame_cd); | 173 AssertBacktraceEquals(frame_cd); |
177 } | 174 } |
178 | 175 |
179 AssertBacktraceEquals(frame_c); | 176 AssertBacktraceEquals(frame_c); |
180 TRACE_EVENT_END0("Testing", kCupcake); | 177 TRACE_EVENT_END0("Testing", kCupcake); |
181 AssertBacktraceEmpty(); | 178 AssertBacktraceEmpty(); |
182 | 179 |
183 { | 180 { |
184 TRACE_EVENT0("Testing", kEclair); | 181 TRACE_EVENT0("Testing", kEclair); |
185 AssertBacktraceEquals(frame_e); | 182 AssertBacktraceEquals(frame_e); |
186 | 183 |
187 TRACE_EVENT_BEGIN0("Testing", kFroyo); | 184 TRACE_EVENT_BEGIN0("Testing", kFroyo); |
188 AssertBacktraceEquals(frame_ef); | 185 AssertBacktraceEquals(frame_ef); |
189 TRACE_EVENT_END0("Testing", kFroyo); | 186 TRACE_EVENT_END0("Testing", kFroyo); |
190 AssertBacktraceEquals(frame_e); | 187 AssertBacktraceEquals(frame_e); |
191 } | 188 } |
192 | 189 |
193 AssertBacktraceEmpty(); | 190 AssertBacktraceEmpty(); |
194 } | 191 } |
195 | 192 |
196 TEST_F(AllocationContextTrackerTest, BacktraceTakesTop) { | 193 TEST_F(AllocationContextTrackerTest, BacktraceTakesTop) { |
| 194 StackFrame c = StackFrame::FromTraceEventName(kCupcake); |
| 195 StackFrame f = StackFrame::FromTraceEventName(kFroyo); |
| 196 |
197 // Push 12 events onto the pseudo stack. | 197 // Push 12 events onto the pseudo stack. |
198 TRACE_EVENT0("Testing", kCupcake); | 198 TRACE_EVENT0("Testing", kCupcake); |
199 TRACE_EVENT0("Testing", kCupcake); | 199 TRACE_EVENT0("Testing", kCupcake); |
200 TRACE_EVENT0("Testing", kCupcake); | 200 TRACE_EVENT0("Testing", kCupcake); |
201 TRACE_EVENT0("Testing", kCupcake); | 201 TRACE_EVENT0("Testing", kCupcake); |
202 | 202 |
203 TRACE_EVENT0("Testing", kCupcake); | 203 TRACE_EVENT0("Testing", kCupcake); |
204 TRACE_EVENT0("Testing", kCupcake); | 204 TRACE_EVENT0("Testing", kCupcake); |
205 TRACE_EVENT0("Testing", kCupcake); | 205 TRACE_EVENT0("Testing", kCupcake); |
206 TRACE_EVENT0("Testing", kCupcake); | 206 TRACE_EVENT0("Testing", kCupcake); |
207 | 207 |
208 TRACE_EVENT0("Testing", kCupcake); | 208 TRACE_EVENT0("Testing", kCupcake); |
209 TRACE_EVENT0("Testing", kDonut); | 209 TRACE_EVENT0("Testing", kDonut); |
210 TRACE_EVENT0("Testing", kEclair); | 210 TRACE_EVENT0("Testing", kEclair); |
211 TRACE_EVENT0("Testing", kFroyo); | 211 TRACE_EVENT0("Testing", kFroyo); |
212 | 212 |
213 { | 213 { |
214 TRACE_EVENT0("Testing", kGingerbread); | 214 TRACE_EVENT0("Testing", kGingerbread); |
215 AllocationContext ctx = | 215 AllocationContext ctx = |
216 AllocationContextTracker::GetInstanceForCurrentThread() | 216 AllocationContextTracker::GetInstanceForCurrentThread() |
217 ->GetContextSnapshot(); | 217 ->GetContextSnapshot(); |
218 | 218 |
219 // The pseudo stack relies on pointer equality, not deep string comparisons. | 219 // The pseudo stack relies on pointer equality, not deep string comparisons. |
220 ASSERT_EQ(kCupcake, ctx.backtrace.frames[0]); | 220 ASSERT_EQ(c, ctx.backtrace.frames[0]); |
221 ASSERT_EQ(kFroyo, ctx.backtrace.frames[11]); | 221 ASSERT_EQ(f, ctx.backtrace.frames[11]); |
222 } | 222 } |
223 | 223 |
224 { | 224 { |
225 AllocationContext ctx = | 225 AllocationContext ctx = |
226 AllocationContextTracker::GetInstanceForCurrentThread() | 226 AllocationContextTracker::GetInstanceForCurrentThread() |
227 ->GetContextSnapshot(); | 227 ->GetContextSnapshot(); |
228 ASSERT_EQ(kCupcake, ctx.backtrace.frames[0]); | 228 ASSERT_EQ(c, ctx.backtrace.frames[0]); |
229 ASSERT_EQ(kFroyo, ctx.backtrace.frames[11]); | 229 ASSERT_EQ(f, ctx.backtrace.frames[11]); |
230 } | 230 } |
231 } | 231 } |
232 | 232 |
233 TEST_F(AllocationContextTrackerTest, SetCurrentThreadName) { | 233 TEST_F(AllocationContextTrackerTest, SetCurrentThreadName) { |
234 TRACE_EVENT0("Testing", kCupcake); | 234 TRACE_EVENT0("Testing", kCupcake); |
235 | 235 |
236 // Test if the thread name is inserted into backtrace. | 236 // Test if the thread name is inserted into backtrace. |
237 const char kThread1[] = "thread1"; | 237 const char kThread1[] = "thread1"; |
238 AllocationContextTracker::SetCurrentThreadName(kThread1); | 238 AllocationContextTracker::SetCurrentThreadName(kThread1); |
239 AllocationContext ctx1 = | 239 AllocationContext ctx1 = |
240 AllocationContextTracker::GetInstanceForCurrentThread() | 240 AllocationContextTracker::GetInstanceForCurrentThread() |
241 ->GetContextSnapshot(); | 241 ->GetContextSnapshot(); |
242 ASSERT_EQ(kThread1, ctx1.backtrace.frames[0]); | 242 ASSERT_EQ(StackFrame::FromThreadName(kThread1), ctx1.backtrace.frames[0]); |
243 ASSERT_EQ(kCupcake, ctx1.backtrace.frames[1]); | 243 ASSERT_EQ(StackFrame::FromTraceEventName(kCupcake), ctx1.backtrace.frames[1]); |
244 | 244 |
245 // Test if the thread name is reset. | 245 // Test if the thread name is reset. |
246 const char kThread2[] = "thread2"; | 246 const char kThread2[] = "thread2"; |
247 AllocationContextTracker::SetCurrentThreadName(kThread2); | 247 AllocationContextTracker::SetCurrentThreadName(kThread2); |
248 AllocationContext ctx2 = | 248 AllocationContext ctx2 = |
249 AllocationContextTracker::GetInstanceForCurrentThread() | 249 AllocationContextTracker::GetInstanceForCurrentThread() |
250 ->GetContextSnapshot(); | 250 ->GetContextSnapshot(); |
251 ASSERT_EQ(kThread2, ctx2.backtrace.frames[0]); | 251 ASSERT_EQ(StackFrame::FromThreadName(kThread2), ctx2.backtrace.frames[0]); |
252 ASSERT_EQ(kCupcake, ctx2.backtrace.frames[1]); | 252 ASSERT_EQ(StackFrame::FromTraceEventName(kCupcake), ctx2.backtrace.frames[1]); |
253 } | 253 } |
254 | 254 |
255 TEST_F(AllocationContextTrackerTest, TrackTaskContext) { | 255 TEST_F(AllocationContextTrackerTest, TrackTaskContext) { |
256 const char kContext1[] = "context1"; | 256 const char kContext1[] = "context1"; |
257 const char kContext2[] = "context2"; | 257 const char kContext2[] = "context2"; |
258 { | 258 { |
259 // The context from the scoped task event should be used as type name. | 259 // The context from the scoped task event should be used as type name. |
260 TRACE_EVENT_API_SCOPED_TASK_EXECUTION_EVENT event1(kContext1); | 260 TRACE_EVENT_API_SCOPED_TASK_EXECUTION_EVENT event1(kContext1); |
261 AllocationContext ctx1 = | 261 AllocationContext ctx1 = |
262 AllocationContextTracker::GetInstanceForCurrentThread() | 262 AllocationContextTracker::GetInstanceForCurrentThread() |
(...skipping 10 matching lines...) Expand all Loading... |
273 | 273 |
274 // Type should be nullptr without task event. | 274 // Type should be nullptr without task event. |
275 AllocationContext ctx = | 275 AllocationContext ctx = |
276 AllocationContextTracker::GetInstanceForCurrentThread() | 276 AllocationContextTracker::GetInstanceForCurrentThread() |
277 ->GetContextSnapshot(); | 277 ->GetContextSnapshot(); |
278 ASSERT_FALSE(ctx.type_name); | 278 ASSERT_FALSE(ctx.type_name); |
279 } | 279 } |
280 | 280 |
281 } // namespace trace_event | 281 } // namespace trace_event |
282 } // namespace base | 282 } // namespace base |
OLD | NEW |