Chromium Code Reviews| 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; |
|
Primiano Tucci (use gerrit)
2016/04/14 10:15:33
why do we need this change?
Dmitry Skiba
2016/04/15 07:01:40
Because we want to check only valid frames, within
| |
| 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 |