Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(23)

Side by Side Diff: base/trace_event/memory_profiler_allocation_context_unittest.cc

Issue 1372523002: [tracing] Implement trace_event::AllocationContext (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@alloccontext
Patch Set: Fix string interning bug, extract backtrace into struct Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 "base/trace_event/memory_profiler_allocation_context.h" 5 #include "base/trace_event/memory_profiler_allocation_context.h"
6 #include "base/trace_event/trace_event.h" 6 #include "base/trace_event/trace_event.h"
7 #include "testing/gtest/include/gtest/gtest.h" 7 #include "testing/gtest/include/gtest/gtest.h"
8 8
9 namespace base { 9 namespace base {
10 namespace trace_event { 10 namespace trace_event {
11 11
12 // Define all strings once, because the pseudo stack requires pointer equality, 12 // Define all strings once, because the pseudo stack requires pointer equality,
13 // and string interning is unreliable. 13 // and string interning is unreliable.
14 const char kCupcake[] = "Cupcake"; 14 const char kCupcake[] = "Cupcake";
15 const char kDonut[] = "Donut"; 15 const char kDonut[] = "Donut";
16 const char kEclair[] = "Eclair"; 16 const char kEclair[] = "Eclair";
17 const char kFroyo[] = "Froyo"; 17 const char kFroyo[] = "Froyo";
18 const char kGingerbread[] = "Gingerbread"; 18 const char kGingerbread[] = "Gingerbread";
19 const char kHoneycomb[] = "Honeycomb"; 19 const char kHoneycomb[] = "Honeycomb";
20 const char kIceCreamSandwich[] = "Ice Cream Sandwich";
21 const char kJellyBean[] = "Jelly Bean";
22 const char kKitKat[] = "KitKat";
20 23
21 // Asserts that the fixed-size array |expected_stack| matches the pseudo 24 // Returns a pointer past the end of the fixed-size array |array| of |T| of
22 // stack. Syntax note: |const StackFrame (&expected_stack)[N]| is the syntax 25 // length |N|, identical to C++11 |std::end|.
23 // for "expected_stack is a reference to a const fixed-size array of StackFrame 26 template <typename T, int N>
24 // of length N". 27 const T* End(const T(&array)[N]) {
28 return array + N;
29 }
30
31 // Asserts that the fixed-size array |expected_backtrace| matches the backtrace
32 // in |AllocationContextTracker::GetContext|.
25 template <size_t N> 33 template <size_t N>
26 void AssertPseudoStackEquals(const StackFrame(&expected_stack)[N]) { 34 void AssertBacktraceEquals(const StackFrame(&expected_backtrace)[N]) {
27 auto pseudo_stack = AllocationContextTracker::GetPseudoStackForTesting(); 35 AllocationContext ctx = AllocationContextTracker::GetContext();
28 auto actual = pseudo_stack->top(); 36
29 auto actual_bottom = pseudo_stack->bottom(); 37 auto actual = ctx.backtrace.frames;
30 auto expected = expected_stack; 38 auto actual_bottom = End(ctx.backtrace.frames);
31 auto expected_bottom = expected_stack + N; 39 auto expected = expected_backtrace;
40 auto expected_bottom = End(expected_backtrace);
32 41
33 // Note that this requires the pointers to be equal, this is not doing a deep 42 // Note that this requires the pointers to be equal, this is not doing a deep
34 // string comparison. 43 // string comparison.
35 for (; actual != actual_bottom && expected != expected_bottom; 44 for (; actual != actual_bottom && expected != expected_bottom;
36 actual++, expected++) 45 actual++, expected++)
37 ASSERT_EQ(*expected, *actual); 46 ASSERT_EQ(*expected, *actual);
38 47
39 // Ensure that the height of the stacks is the same. 48 // Ensure that the height of the stacks is the same.
40 ASSERT_EQ(actual, actual_bottom); 49 ASSERT_EQ(actual, actual_bottom);
41 ASSERT_EQ(expected, expected_bottom); 50 ASSERT_EQ(expected, expected_bottom);
42 } 51 }
43 52
44 void AssertPseudoStackEmpty() { 53 void AssertBacktraceEmpty() {
45 auto pseudo_stack = AllocationContextTracker::GetPseudoStackForTesting(); 54 AllocationContext ctx = AllocationContextTracker::GetContext();
46 ASSERT_EQ(pseudo_stack->top(), pseudo_stack->bottom()); 55
56 for (StackFrame frame : ctx.backtrace.frames)
57 ASSERT_EQ(nullptr, frame);
47 } 58 }
48 59
49 class AllocationContextTest : public testing::Test { 60 class AllocationContextTest : public testing::Test {
50 public: 61 public:
51 void EnableTracing() { 62 void SetUp() override {
52 TraceConfig config(""); 63 TraceConfig config("");
53 TraceLog::GetInstance()->SetEnabled(config, TraceLog::RECORDING_MODE); 64 TraceLog::GetInstance()->SetEnabled(config, TraceLog::RECORDING_MODE);
54 AllocationContextTracker::SetCaptureEnabled(true); 65 AllocationContextTracker::SetCaptureEnabled(true);
55 } 66 }
56 67
57 void DisableTracing() { 68 void TearDown() override {
58 AllocationContextTracker::SetCaptureEnabled(false); 69 AllocationContextTracker::SetCaptureEnabled(false);
59 TraceLog::GetInstance()->SetDisabled(); 70 TraceLog::GetInstance()->SetDisabled();
60 } 71 }
61 }; 72 };
62 73
74 // Check that |TRACE_EVENT| macros push and pop to the pseudo stack correctly.
75 // Also check that |GetContext| fills the backtrace with null pointers when the
76 // pseudo stack height is less than the capacity.
63 TEST_F(AllocationContextTest, PseudoStackScopedTrace) { 77 TEST_F(AllocationContextTest, PseudoStackScopedTrace) {
64 StackFrame c = kCupcake; 78 StackFrame c = kCupcake;
65 StackFrame d = kDonut; 79 StackFrame d = kDonut;
66 StackFrame e = kEclair; 80 StackFrame e = kEclair;
67 StackFrame f = kFroyo; 81 StackFrame f = kFroyo;
68 82
69 EnableTracing(); 83 AssertBacktraceEmpty();
70 AssertPseudoStackEmpty();
71 84
72 { 85 {
73 TRACE_EVENT0("Testing", kCupcake); 86 TRACE_EVENT0("Testing", kCupcake);
74 StackFrame frame_c[] = {c}; 87 StackFrame frame_c[] = {c, 0, 0, 0, 0, 0, 0, 0};
75 AssertPseudoStackEquals(frame_c); 88 AssertBacktraceEquals(frame_c);
76 89
77 { 90 {
78 TRACE_EVENT0("Testing", kDonut); 91 TRACE_EVENT0("Testing", kDonut);
79 StackFrame frame_dc[] = {d, c}; 92 StackFrame frame_dc[] = {d, c, 0, 0, 0, 0, 0, 0};
80 AssertPseudoStackEquals(frame_dc); 93 AssertBacktraceEquals(frame_dc);
81 } 94 }
82 95
83 AssertPseudoStackEquals(frame_c); 96 AssertBacktraceEquals(frame_c);
84 97
85 { 98 {
86 TRACE_EVENT0("Testing", kEclair); 99 TRACE_EVENT0("Testing", kEclair);
87 StackFrame frame_ec[] = {e, c}; 100 StackFrame frame_ec[] = {e, c, 0, 0, 0, 0, 0, 0};
88 AssertPseudoStackEquals(frame_ec); 101 AssertBacktraceEquals(frame_ec);
89 } 102 }
90 103
91 AssertPseudoStackEquals(frame_c); 104 AssertBacktraceEquals(frame_c);
92 } 105 }
93 106
94 AssertPseudoStackEmpty(); 107 AssertBacktraceEmpty();
95 108
96 { 109 {
97 TRACE_EVENT0("Testing", kFroyo); 110 TRACE_EVENT0("Testing", kFroyo);
98 StackFrame frame_f[] = {f}; 111 StackFrame frame_f[] = {f, 0, 0, 0, 0, 0, 0, 0};
99 AssertPseudoStackEquals(frame_f); 112 AssertBacktraceEquals(frame_f);
100 } 113 }
101 114
102 AssertPseudoStackEmpty(); 115 AssertBacktraceEmpty();
103 DisableTracing();
104 } 116 }
105 117
118 // Same as |PseudoStackScopedTrace|, but now test the |TRACE_EVENT_BEGIN| and
119 // |TRACE_EVENT_END| macros.
106 TEST_F(AllocationContextTest, PseudoStackBeginEndTrace) { 120 TEST_F(AllocationContextTest, PseudoStackBeginEndTrace) {
107 StackFrame c = kCupcake; 121 StackFrame c = kCupcake;
108 StackFrame d = kDonut; 122 StackFrame d = kDonut;
109 StackFrame e = kEclair; 123 StackFrame e = kEclair;
110 StackFrame f = kFroyo; 124 StackFrame f = kFroyo;
111 125
112 StackFrame frame_c[] = {c}; 126 StackFrame frame_c[] = {c, 0, 0, 0, 0, 0, 0, 0};
113 StackFrame frame_dc[] = {d, c}; 127 StackFrame frame_dc[] = {d, c, 0, 0, 0, 0, 0, 0};
114 StackFrame frame_ec[] = {e, c}; 128 StackFrame frame_ec[] = {e, c, 0, 0, 0, 0, 0, 0};
115 StackFrame frame_f[] = {f}; 129 StackFrame frame_f[] = {f, 0, 0, 0, 0, 0, 0, 0};
116 130
117 EnableTracing(); 131 AssertBacktraceEmpty();
118 AssertPseudoStackEmpty();
119 132
120 TRACE_EVENT_BEGIN0("Testing", kCupcake); 133 TRACE_EVENT_BEGIN0("Testing", kCupcake);
121 AssertPseudoStackEquals(frame_c); 134 AssertBacktraceEquals(frame_c);
122 135
123 TRACE_EVENT_BEGIN0("Testing", kDonut); 136 TRACE_EVENT_BEGIN0("Testing", kDonut);
124 AssertPseudoStackEquals(frame_dc); 137 AssertBacktraceEquals(frame_dc);
125 TRACE_EVENT_END0("Testing", kDonut); 138 TRACE_EVENT_END0("Testing", kDonut);
126 139
127 AssertPseudoStackEquals(frame_c); 140 AssertBacktraceEquals(frame_c);
128 141
129 TRACE_EVENT_BEGIN0("Testing", kEclair); 142 TRACE_EVENT_BEGIN0("Testing", kEclair);
130 AssertPseudoStackEquals(frame_ec); 143 AssertBacktraceEquals(frame_ec);
131 TRACE_EVENT_END0("Testing", kEclair); 144 TRACE_EVENT_END0("Testing", kEclair);
132 145
133 AssertPseudoStackEquals(frame_c); 146 AssertBacktraceEquals(frame_c);
134 TRACE_EVENT_END0("Testing", kCupcake); 147 TRACE_EVENT_END0("Testing", kCupcake);
135 148
136 AssertPseudoStackEmpty(); 149 AssertBacktraceEmpty();
137 150
138 TRACE_EVENT_BEGIN0("Testing", kFroyo); 151 TRACE_EVENT_BEGIN0("Testing", kFroyo);
139 AssertPseudoStackEquals(frame_f); 152 AssertBacktraceEquals(frame_f);
140 TRACE_EVENT_END0("Testing", kFroyo); 153 TRACE_EVENT_END0("Testing", kFroyo);
141 154
142 AssertPseudoStackEmpty(); 155 AssertBacktraceEmpty();
143 DisableTracing();
144 } 156 }
145 157
146 TEST_F(AllocationContextTest, PseudoStackMixedTrace) { 158 TEST_F(AllocationContextTest, PseudoStackMixedTrace) {
147 StackFrame c = kCupcake; 159 StackFrame c = kCupcake;
148 StackFrame d = kDonut; 160 StackFrame d = kDonut;
149 StackFrame e = kEclair; 161 StackFrame e = kEclair;
150 StackFrame f = kFroyo; 162 StackFrame f = kFroyo;
151 163
152 StackFrame frame_c[] = {c}; 164 StackFrame frame_c[] = {c, 0, 0, 0, 0, 0, 0, 0};
153 StackFrame frame_dc[] = {d, c}; 165 StackFrame frame_dc[] = {d, c, 0, 0, 0, 0, 0, 0};
154 StackFrame frame_e[] = {e}; 166 StackFrame frame_e[] = {e, 0, 0, 0, 0, 0, 0, 0};
155 StackFrame frame_fe[] = {f, e}; 167 StackFrame frame_fe[] = {f, e, 0, 0, 0, 0, 0, 0};
156 168
157 EnableTracing(); 169 AssertBacktraceEmpty();
158 AssertPseudoStackEmpty();
159 170
160 TRACE_EVENT_BEGIN0("Testing", kCupcake); 171 TRACE_EVENT_BEGIN0("Testing", kCupcake);
161 AssertPseudoStackEquals(frame_c); 172 AssertBacktraceEquals(frame_c);
162 173
163 { 174 {
164 TRACE_EVENT0("Testing", kDonut); 175 TRACE_EVENT0("Testing", kDonut);
165 AssertPseudoStackEquals(frame_dc); 176 AssertBacktraceEquals(frame_dc);
166 } 177 }
167 178
168 AssertPseudoStackEquals(frame_c); 179 AssertBacktraceEquals(frame_c);
169 TRACE_EVENT_END0("Testing", kCupcake); 180 TRACE_EVENT_END0("Testing", kCupcake);
170 AssertPseudoStackEmpty(); 181 AssertBacktraceEmpty();
171 182
172 { 183 {
173 TRACE_EVENT0("Testing", kEclair); 184 TRACE_EVENT0("Testing", kEclair);
174 AssertPseudoStackEquals(frame_e); 185 AssertBacktraceEquals(frame_e);
175 186
176 TRACE_EVENT_BEGIN0("Testing", kFroyo); 187 TRACE_EVENT_BEGIN0("Testing", kFroyo);
177 AssertPseudoStackEquals(frame_fe); 188 AssertBacktraceEquals(frame_fe);
178 TRACE_EVENT_END0("Testing", kFroyo); 189 TRACE_EVENT_END0("Testing", kFroyo);
179 AssertPseudoStackEquals(frame_e); 190 AssertBacktraceEquals(frame_e);
180 } 191 }
181 192
182 AssertPseudoStackEmpty(); 193 AssertBacktraceEmpty();
183 DisableTracing();
184 } 194 }
185 195
186 TEST_F(AllocationContextTest, PseudoStackEnableWithEventInScope) { 196 TEST_F(AllocationContextTest, BacktraceTakesTop) {
187 StackFrame h = kHoneycomb; 197 TRACE_EVENT0("Testing", kCupcake);
198 TRACE_EVENT0("Testing", kDonut);
199 TRACE_EVENT0("Testing", kEclair);
200 TRACE_EVENT0("Testing", kFroyo);
201 TRACE_EVENT0("Testing", kGingerbread);
202 TRACE_EVENT0("Testing", kHoneycomb);
203 TRACE_EVENT0("Testing", kIceCreamSandwich);
204 TRACE_EVENT0("Testing", kJellyBean);
188 205
189 { 206 {
190 TRACE_EVENT0("Testing", kGingerbread); 207 TRACE_EVENT0("Testing", kKitKat);
191 EnableTracing(); 208 AllocationContext ctx = AllocationContextTracker::GetContext();
192 AssertPseudoStackEmpty();
193 209
194 { 210 // The pseudo stack relies on pointer equality, not deep string comparisons.
195 TRACE_EVENT0("Testing", kHoneycomb); 211 ASSERT_EQ(kKitKat, ctx.backtrace.frames[0]);
196 StackFrame frame_h[] = {h}; 212 ASSERT_EQ(kDonut, ctx.backtrace.frames[7]);
197 AssertPseudoStackEquals(frame_h); 213 }
198 }
199 214
200 AssertPseudoStackEmpty(); 215 {
201 216 AllocationContext ctx = AllocationContextTracker::GetContext();
202 // The pop at the end of this scope for the 'Gingerbread' frame must not 217 ASSERT_EQ(kJellyBean, ctx.backtrace.frames[0]);
203 // cause a stack underflow. 218 ASSERT_EQ(kCupcake, ctx.backtrace.frames[7]);
204 } 219 }
205 AssertPseudoStackEmpty();
206 DisableTracing();
207 } 220 }
208 221
209 } // namespace trace_event 222 } // namespace trace_event
210 } // namespace base 223 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698