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 = actual + ctx.backtrace.frame_count; | 36 auto actual_bottom = std::end(ctx.backtrace.frames); |
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 ASSERT_EQ(0u, ctx.backtrace.frame_count); | 56 for (StackFrame frame : ctx.backtrace.frames) |
| 57 ASSERT_EQ(nullptr, frame); |
57 } | 58 } |
58 | 59 |
59 class AllocationContextTrackerTest : public testing::Test { | 60 class AllocationContextTrackerTest : public testing::Test { |
60 public: | 61 public: |
61 void SetUp() override { | 62 void SetUp() override { |
62 TraceConfig config(""); | 63 TraceConfig config(""); |
63 TraceLog::GetInstance()->SetEnabled(config, TraceLog::RECORDING_MODE); | 64 TraceLog::GetInstance()->SetEnabled(config, TraceLog::RECORDING_MODE); |
64 AllocationContextTracker::SetCaptureEnabled(true); | 65 AllocationContextTracker::SetCaptureEnabled(true); |
65 } | 66 } |
66 | 67 |
67 void TearDown() override { | 68 void TearDown() override { |
68 AllocationContextTracker::SetCaptureEnabled(false); | 69 AllocationContextTracker::SetCaptureEnabled(false); |
69 TraceLog::GetInstance()->SetDisabled(); | 70 TraceLog::GetInstance()->SetDisabled(); |
70 } | 71 } |
71 }; | 72 }; |
72 | 73 |
73 // Check that |TRACE_EVENT| macros push and pop to the pseudo stack correctly. | 74 // 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. |
74 TEST_F(AllocationContextTrackerTest, PseudoStackScopedTrace) { | 77 TEST_F(AllocationContextTrackerTest, PseudoStackScopedTrace) { |
75 StackFrame c = StackFrame::FromTraceEventName(kCupcake); | 78 StackFrame c = kCupcake; |
76 StackFrame d = StackFrame::FromTraceEventName(kDonut); | 79 StackFrame d = kDonut; |
77 StackFrame e = StackFrame::FromTraceEventName(kEclair); | 80 StackFrame e = kEclair; |
78 StackFrame f = StackFrame::FromTraceEventName(kFroyo); | 81 StackFrame f = kFroyo; |
79 | 82 |
80 AssertBacktraceEmpty(); | 83 AssertBacktraceEmpty(); |
81 | 84 |
82 { | 85 { |
83 TRACE_EVENT0("Testing", kCupcake); | 86 TRACE_EVENT0("Testing", kCupcake); |
84 StackFrame frame_c[] = {c}; | 87 StackFrame frame_c[] = {c, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; |
85 AssertBacktraceEquals(frame_c); | 88 AssertBacktraceEquals(frame_c); |
86 | 89 |
87 { | 90 { |
88 TRACE_EVENT0("Testing", kDonut); | 91 TRACE_EVENT0("Testing", kDonut); |
89 StackFrame frame_cd[] = {c, d}; | 92 StackFrame frame_cd[] = {c, d, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; |
90 AssertBacktraceEquals(frame_cd); | 93 AssertBacktraceEquals(frame_cd); |
91 } | 94 } |
92 | 95 |
93 AssertBacktraceEquals(frame_c); | 96 AssertBacktraceEquals(frame_c); |
94 | 97 |
95 { | 98 { |
96 TRACE_EVENT0("Testing", kEclair); | 99 TRACE_EVENT0("Testing", kEclair); |
97 StackFrame frame_ce[] = {c, e}; | 100 StackFrame frame_ce[] = {c, e, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; |
98 AssertBacktraceEquals(frame_ce); | 101 AssertBacktraceEquals(frame_ce); |
99 } | 102 } |
100 | 103 |
101 AssertBacktraceEquals(frame_c); | 104 AssertBacktraceEquals(frame_c); |
102 } | 105 } |
103 | 106 |
104 AssertBacktraceEmpty(); | 107 AssertBacktraceEmpty(); |
105 | 108 |
106 { | 109 { |
107 TRACE_EVENT0("Testing", kFroyo); | 110 TRACE_EVENT0("Testing", kFroyo); |
108 StackFrame frame_f[] = {f}; | 111 StackFrame frame_f[] = {f, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; |
109 AssertBacktraceEquals(frame_f); | 112 AssertBacktraceEquals(frame_f); |
110 } | 113 } |
111 | 114 |
112 AssertBacktraceEmpty(); | 115 AssertBacktraceEmpty(); |
113 } | 116 } |
114 | 117 |
115 // Same as |PseudoStackScopedTrace|, but now test the |TRACE_EVENT_BEGIN| and | 118 // Same as |PseudoStackScopedTrace|, but now test the |TRACE_EVENT_BEGIN| and |
116 // |TRACE_EVENT_END| macros. | 119 // |TRACE_EVENT_END| macros. |
117 TEST_F(AllocationContextTrackerTest, PseudoStackBeginEndTrace) { | 120 TEST_F(AllocationContextTrackerTest, PseudoStackBeginEndTrace) { |
118 StackFrame c = StackFrame::FromTraceEventName(kCupcake); | 121 StackFrame c = kCupcake; |
119 StackFrame d = StackFrame::FromTraceEventName(kDonut); | 122 StackFrame d = kDonut; |
120 StackFrame e = StackFrame::FromTraceEventName(kEclair); | 123 StackFrame e = kEclair; |
121 StackFrame f = StackFrame::FromTraceEventName(kFroyo); | 124 StackFrame f = kFroyo; |
122 | 125 |
123 StackFrame frame_c[] = {c}; | 126 StackFrame frame_c[] = {c, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; |
124 StackFrame frame_cd[] = {c, d}; | 127 StackFrame frame_cd[] = {c, d, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; |
125 StackFrame frame_ce[] = {c, e}; | 128 StackFrame frame_ce[] = {c, e, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; |
126 StackFrame frame_f[] = {f}; | 129 StackFrame frame_f[] = {f, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; |
127 | 130 |
128 AssertBacktraceEmpty(); | 131 AssertBacktraceEmpty(); |
129 | 132 |
130 TRACE_EVENT_BEGIN0("Testing", kCupcake); | 133 TRACE_EVENT_BEGIN0("Testing", kCupcake); |
131 AssertBacktraceEquals(frame_c); | 134 AssertBacktraceEquals(frame_c); |
132 | 135 |
133 TRACE_EVENT_BEGIN0("Testing", kDonut); | 136 TRACE_EVENT_BEGIN0("Testing", kDonut); |
134 AssertBacktraceEquals(frame_cd); | 137 AssertBacktraceEquals(frame_cd); |
135 TRACE_EVENT_END0("Testing", kDonut); | 138 TRACE_EVENT_END0("Testing", kDonut); |
136 | 139 |
137 AssertBacktraceEquals(frame_c); | 140 AssertBacktraceEquals(frame_c); |
138 | 141 |
139 TRACE_EVENT_BEGIN0("Testing", kEclair); | 142 TRACE_EVENT_BEGIN0("Testing", kEclair); |
140 AssertBacktraceEquals(frame_ce); | 143 AssertBacktraceEquals(frame_ce); |
141 TRACE_EVENT_END0("Testing", kEclair); | 144 TRACE_EVENT_END0("Testing", kEclair); |
142 | 145 |
143 AssertBacktraceEquals(frame_c); | 146 AssertBacktraceEquals(frame_c); |
144 TRACE_EVENT_END0("Testing", kCupcake); | 147 TRACE_EVENT_END0("Testing", kCupcake); |
145 | 148 |
146 AssertBacktraceEmpty(); | 149 AssertBacktraceEmpty(); |
147 | 150 |
148 TRACE_EVENT_BEGIN0("Testing", kFroyo); | 151 TRACE_EVENT_BEGIN0("Testing", kFroyo); |
149 AssertBacktraceEquals(frame_f); | 152 AssertBacktraceEquals(frame_f); |
150 TRACE_EVENT_END0("Testing", kFroyo); | 153 TRACE_EVENT_END0("Testing", kFroyo); |
151 | 154 |
152 AssertBacktraceEmpty(); | 155 AssertBacktraceEmpty(); |
153 } | 156 } |
154 | 157 |
155 TEST_F(AllocationContextTrackerTest, PseudoStackMixedTrace) { | 158 TEST_F(AllocationContextTrackerTest, PseudoStackMixedTrace) { |
156 StackFrame c = StackFrame::FromTraceEventName(kCupcake); | 159 StackFrame c = kCupcake; |
157 StackFrame d = StackFrame::FromTraceEventName(kDonut); | 160 StackFrame d = kDonut; |
158 StackFrame e = StackFrame::FromTraceEventName(kEclair); | 161 StackFrame e = kEclair; |
159 StackFrame f = StackFrame::FromTraceEventName(kFroyo); | 162 StackFrame f = kFroyo; |
160 | 163 |
161 StackFrame frame_c[] = {c}; | 164 StackFrame frame_c[] = {c, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; |
162 StackFrame frame_cd[] = {c, d}; | 165 StackFrame frame_cd[] = {c, d, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; |
163 StackFrame frame_e[] = {e}; | 166 StackFrame frame_e[] = {e, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; |
164 StackFrame frame_ef[] = {e, f}; | 167 StackFrame frame_ef[] = {e, f, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; |
165 | 168 |
166 AssertBacktraceEmpty(); | 169 AssertBacktraceEmpty(); |
167 | 170 |
168 TRACE_EVENT_BEGIN0("Testing", kCupcake); | 171 TRACE_EVENT_BEGIN0("Testing", kCupcake); |
169 AssertBacktraceEquals(frame_c); | 172 AssertBacktraceEquals(frame_c); |
170 | 173 |
171 { | 174 { |
172 TRACE_EVENT0("Testing", kDonut); | 175 TRACE_EVENT0("Testing", kDonut); |
173 AssertBacktraceEquals(frame_cd); | 176 AssertBacktraceEquals(frame_cd); |
174 } | 177 } |
175 | 178 |
176 AssertBacktraceEquals(frame_c); | 179 AssertBacktraceEquals(frame_c); |
177 TRACE_EVENT_END0("Testing", kCupcake); | 180 TRACE_EVENT_END0("Testing", kCupcake); |
178 AssertBacktraceEmpty(); | 181 AssertBacktraceEmpty(); |
179 | 182 |
180 { | 183 { |
181 TRACE_EVENT0("Testing", kEclair); | 184 TRACE_EVENT0("Testing", kEclair); |
182 AssertBacktraceEquals(frame_e); | 185 AssertBacktraceEquals(frame_e); |
183 | 186 |
184 TRACE_EVENT_BEGIN0("Testing", kFroyo); | 187 TRACE_EVENT_BEGIN0("Testing", kFroyo); |
185 AssertBacktraceEquals(frame_ef); | 188 AssertBacktraceEquals(frame_ef); |
186 TRACE_EVENT_END0("Testing", kFroyo); | 189 TRACE_EVENT_END0("Testing", kFroyo); |
187 AssertBacktraceEquals(frame_e); | 190 AssertBacktraceEquals(frame_e); |
188 } | 191 } |
189 | 192 |
190 AssertBacktraceEmpty(); | 193 AssertBacktraceEmpty(); |
191 } | 194 } |
192 | 195 |
193 TEST_F(AllocationContextTrackerTest, BacktraceTakesTop) { | 196 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(c, ctx.backtrace.frames[0]); | 220 ASSERT_EQ(kCupcake, ctx.backtrace.frames[0]); |
221 ASSERT_EQ(f, ctx.backtrace.frames[11]); | 221 ASSERT_EQ(kFroyo, 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(c, ctx.backtrace.frames[0]); | 228 ASSERT_EQ(kCupcake, ctx.backtrace.frames[0]); |
229 ASSERT_EQ(f, ctx.backtrace.frames[11]); | 229 ASSERT_EQ(kFroyo, 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(StackFrame::FromThreadName(kThread1), ctx1.backtrace.frames[0]); | 242 ASSERT_EQ(kThread1, ctx1.backtrace.frames[0]); |
243 ASSERT_EQ(StackFrame::FromTraceEventName(kCupcake), ctx1.backtrace.frames[1]); | 243 ASSERT_EQ(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(StackFrame::FromThreadName(kThread2), ctx2.backtrace.frames[0]); | 251 ASSERT_EQ(kThread2, ctx2.backtrace.frames[0]); |
252 ASSERT_EQ(StackFrame::FromTraceEventName(kCupcake), ctx2.backtrace.frames[1]); | 252 ASSERT_EQ(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 |